From d04001c09d9805e0eaa45da038a3d8bfaa9a12ee Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 21 Jun 2017 18:00:00 -0500 Subject: [PATCH] another huge sync --- SQL/tgstation_schema.sql | 8 +- _maps/basemap.dm | 5 +- code/__DEFINES/antagonists.dm | 17 +- code/__DEFINES/clockcult.dm | 4 +- code/__DEFINES/mobs.dm | 6 + code/__DEFINES/server_tools.dm | 1 + code/__DEFINES/subsystems.dm | 7 +- code/__HELPERS/names.dm | 70 ++-- code/controllers/subsystem/atoms.dm | 2 +- code/controllers/subsystem/blackbox.dm | 40 +- code/controllers/subsystem/job.dm | 8 +- code/controllers/subsystem/ticker.dm | 20 +- code/controllers/subsystem/timer.dm | 5 +- code/datums/antagonists/datum_clockcult.dm | 40 +- code/datums/antagonists/datum_iaa.dm | 11 + .../antagonists/datum_internal_affairs.dm | 327 ++++++++++++++++ code/datums/antagonists/datum_traitor.dm | 326 ++++++++++++++++ code/datums/mind.dm | 111 ++++-- code/game/gamemodes/changeling/changeling.dm | 10 +- code/game/gamemodes/clock_cult/clock_cult.dm | 2 +- .../clock_helpers/slab_abilities.dm | 19 +- code/game/gamemodes/cult/cult.dm | 2 +- .../devil/devil agent/devil_agent.dm | 10 +- code/game/gamemodes/game_mode.dm | 30 +- code/game/gamemodes/nuclear/nuclear.dm | 2 +- code/game/gamemodes/objective.dm | 4 +- code/game/gamemodes/traitor/double_agents.dm | 361 +++--------------- code/game/gamemodes/traitor/traitor.dm | 280 +------------- .../effects/decals/cleanable/humans.dm | 2 +- code/game/objects/effects/decals/decal.dm | 5 +- .../objects/items/weapons/pneumaticCannon.dm | 9 +- .../objects/items/weapons/storage/lockbox.dm | 85 +++-- .../closets/secure/scientist.dm | 2 +- .../crates_lockers/closets/secure/security.dm | 5 +- code/modules/admin/secrets.dm | 29 +- code/modules/admin/verbs/one_click_antag.dm | 1 + code/modules/admin/verbs/randomverbs.dm | 68 ++-- code/modules/client/asset_cache.dm | 70 ++-- code/modules/clothing/under/accessories.dm | 4 + code/modules/flufftext/Hallucination.dm | 75 ++-- code/modules/language/codespeak.dm | 83 ++++ code/modules/language/language.dm | 14 +- .../modules/mob/dead/new_player/new_player.dm | 141 ++++--- .../guns/energy/kinetic_accelerator.dm | 31 +- .../research/xenobiology/xenobiology.dm | 8 +- code/modules/server_tools/server_tools.dm | 32 +- code/modules/surgery/organs/tongue.dm | 1 + code/modules/uplink/uplink_item.dm | 14 + code/world.dm | 12 +- icons/obj/storage.dmi | Bin 58920 -> 59573 bytes tgstation.dme | 5 +- 51 files changed, 1443 insertions(+), 981 deletions(-) create mode 100644 code/datums/antagonists/datum_iaa.dm create mode 100644 code/datums/antagonists/datum_internal_affairs.dm create mode 100644 code/datums/antagonists/datum_traitor.dm create mode 100644 code/modules/language/codespeak.dm diff --git a/SQL/tgstation_schema.sql b/SQL/tgstation_schema.sql index 46729fc9bb..4c76e1f275 100644 --- a/SQL/tgstation_schema.sql +++ b/SQL/tgstation_schema.sql @@ -119,6 +119,7 @@ CREATE TABLE `connection_log` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `death` -- @@ -129,10 +130,13 @@ DROP TABLE IF EXISTS `death`; CREATE TABLE `death` ( `id` int(11) NOT NULL AUTO_INCREMENT, `pod` varchar(50) NOT NULL, - `coord` varchar(32) NOT NULL, + `x_coord` smallint(5) unsigned NOT NULL, + `y_coord` smallint(5) unsigned NOT NULL, + `z_coord` smallint(5) unsigned NOT NULL, `mapname` varchar(32) NOT NULL, `server_ip` int(10) unsigned NOT NULL, `server_port` smallint(5) unsigned NOT NULL, + `round_id` int(11) NOT NULL `tod` datetime NOT NULL COMMENT 'Time of death', `job` varchar(32) NOT NULL, `special` varchar(32) DEFAULT NULL, @@ -140,7 +144,6 @@ CREATE TABLE `death` ( `byondkey` varchar(32) NOT NULL, `laname` varchar(96) DEFAULT NULL, `lakey` varchar(32) DEFAULT NULL, - `gender` enum('neuter','male','female','plural') NOT NULL, `bruteloss` smallint(5) unsigned NOT NULL, `brainloss` smallint(5) unsigned NOT NULL, `fireloss` smallint(5) unsigned NOT NULL, @@ -152,6 +155,7 @@ CREATE TABLE `death` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `feedback` -- diff --git a/_maps/basemap.dm b/_maps/basemap.dm index 20396b128a..fd98837cd1 100644 --- a/_maps/basemap.dm +++ b/_maps/basemap.dm @@ -1,13 +1,10 @@ -#ifndef ALL_MAPS - #include "map_files\generic\Centcomm.dmm" #include "map_files\generic\SpaceStation.dmm" #include "map_files\generic\Space.dmm" #include "map_files\generic\SpaceDock.dmm" #include "map_files\Mining\Lavaland.dmm" -#else - +#ifdef ALL_MAPS #include "map_files\debug\runtimestation.dmm" #include "map_files\Deltastation\DeltaStation2.dmm" #include "map_files\MetaStation\MetaStation.dmm" diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index b29d933866..26c163aef4 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -5,4 +5,19 @@ #define ANTAG_DATUM_DEVIL /datum/antagonist/devil #define ANTAG_DATUM_NINJA /datum/antagonist/ninja #define ANTAG_DATUM_NINJA_FRIENDLY /datum/antagonist/ninja/friendly -#define ANTAG_DATUM_NINJA_RANDOM /datum/antagonist/ninja/randomAllegiance/ \ No newline at end of file +#define ANTAG_DATUM_NINJA_RANDOM /datum/antagonist/ninja/randomAllegiance/ +#define ANTAG_DATUM_TRAITOR /datum/antagonist/traitor +#define ANTAG_DATUM_TRAITOR_CUSTOM /datum/antagonist/traitor/custom +#define ANTAG_DATUM_IAA /datum/antagonist/traitor/internal_affairs +#define ANTAG_DATUM_TRAITOR /datum/antagonist/traitor +#define ANTAG_DATUM_TRAITOR_CUSTOM /datum/antagonist/traitor/custom +#define ANTAG_DATUM_TRAITOR_HUMAN /datum/antagonist/traitor/human +#define ANTAG_DATUM_TRAITOR_HUMAN_CUSTOM /datum/antagonist/traitor/human/custom +#define ANTAG_DATUM_TRAITOR_AI /datum/antagonist/traitor/AI +#define ANTAG_DATUM_TRAITOR_AI_CUSTOM /datum/antagonist/traitor/AI/custom +#define ANTAG_DATUM_IAA /datum/antagonist/traitor/internal_affairs +#define ANTAG_DATUM_IAA_CUSTOM /datum/antagonist/traitor/internal_affairs/custom +#define ANTAG_DATUM_IAA_HUMAN /datum/antagonist/traitor/human/internal_affairs +#define ANTAG_DATUM_IAA_HUMAN_CUSTOM /datum/antagonist/traitor/human/internal_affairs/custom +#define ANTAG_DATUM_IAA_AI_CUSTOM /datum/antagonist/traitor/AI/internal_affairs/custom +#define ANTAG_DATUM_IAA_AI /datum/antagonist/traitor/AI/internal_affairs \ No newline at end of file diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm index 7459ded715..a12cedcd45 100644 --- a/code/__DEFINES/clockcult.dm +++ b/code/__DEFINES/clockcult.dm @@ -21,10 +21,10 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us #define SCRIPTURE_PERIPHERAL "Peripheral" #define SCRIPTURE_DRIVER "Driver" #define SCRIPTURE_SCRIPT "Script" -#define SCRIPT_SERVANT_REQ 5 +#define SCRIPT_SERVANT_REQ 6 #define SCRIPT_CACHE_REQ 1 #define SCRIPTURE_APPLICATION "Application" -#define APPLICATION_SERVANT_REQ 8 +#define APPLICATION_SERVANT_REQ 9 #define APPLICATION_CACHE_REQ 3 #define APPLICATION_CV_REQ 100 #define SCRIPTURE_REVENANT "Revenant" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index e5d1f4c19e..96e8bd6c05 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -2,6 +2,12 @@ //Misc mob defines +//Ready states at roundstart for mob/dead/new_player +#define PLAYER_NOT_READY 0 +#define PLAYER_READY_TO_PLAY 1 +#define PLAYER_READY_TO_OBSERVE 2 + + //movement intent defines for the m_intent var #define MOVE_INTENT_WALK "walk" #define MOVE_INTENT_RUN "run" diff --git a/code/__DEFINES/server_tools.dm b/code/__DEFINES/server_tools.dm index 744559f6c7..1e57d8cb80 100644 --- a/code/__DEFINES/server_tools.dm +++ b/code/__DEFINES/server_tools.dm @@ -26,3 +26,4 @@ #define SERVICE_REQUEST_KILL_PROCESS "killme" #define SERVICE_REQUEST_IRC_BROADCAST "irc" #define SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE "send2irc" +#define SERVICE_REQUEST_WORLD_REBOOT "worldreboot" diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 0858d6acdb..ee42967a52 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -14,7 +14,9 @@ //prevents distinguishing identical timers with the wait variable #define TIMER_NO_HASH_WAIT 0x10 -#define TIMER_NO_INVOKE_WARNING 200 //number of byond ticks that are allowed to pass before the timer subsystem thinks it hung on something +#define TIMER_NO_INVOKE_WARNING 600 //number of byond ticks that are allowed to pass before the timer subsystem thinks it hung on something + +#define TIMER_ID_NULL -1 //For servers that can't do with any additional lag, set this to none in flightpacks.dm in subsystem/processing. #define FLIGHTSUIT_PROCESSING_NONE 0 @@ -42,7 +44,8 @@ // Subsystems shutdown in the reverse of the order they initialize in // The numbers just define the ordering, they are meaningless otherwise. -#define INIT_ORDER_DBCORE 17 +#define INIT_ORDER_DBCORE 18 +#define INIT_ORDER_BLACKBOX 17 #define INIT_ORDER_SERVER_MAINT 16 #define INIT_ORDER_JOBS 15 #define INIT_ORDER_EVENTS 14 diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 5074ae4e38..67179e8c8f 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -55,19 +55,19 @@ GLOBAL_VAR(command_name) return capitalize(name) /proc/station_name() - if(!GLOB.station_name) - var/newname - if(config && config.station_name) - newname = config.station_name - else - newname = new_station_name() + if(!GLOB.station_name) + var/newname + if(config && config.station_name) + newname = config.station_name + else + newname = new_station_name() - set_station_name(newname) - - return GLOB.station_name - -/proc/set_station_name(newname) - GLOB.station_name = newname + set_station_name(newname) + + return GLOB.station_name + +/proc/set_station_name(newname) + GLOB.station_name = newname if(config && config.server_name) world.name = "[config.server_name][config.server_name==GLOB.station_name ? "" : ": [GLOB.station_name]"]" @@ -167,9 +167,13 @@ GLOBAL_VAR(syndicate_code_response) //Code response for traitors. /N */ -/proc/generate_code_phrase()//Proc is used for phrase and response in master_controller.dm +/proc/generate_code_phrase(return_list=FALSE)//Proc is used for phrase and response in master_controller.dm + + if(!return_list) + . = "" + else + . = list() - var/code_phrase = ""//What is returned when the proc finishes. var/words = pick(//How many words there will be. Minimum of two. 2, 4 and 5 have a lesser chance of being selected. 3 is the most likely. 50; 2, 200; 3, @@ -204,39 +208,39 @@ GLOBAL_VAR(syndicate_code_response) //Code response for traitors. switch(rand(1,2))//Mainly to add more options later. if(1) if(names.len&&prob(70)) - code_phrase += pick(names) + . += pick(names) else if(prob(10)) - code_phrase += pick(lizard_name(MALE),lizard_name(FEMALE)) + . += pick(lizard_name(MALE),lizard_name(FEMALE)) else - code_phrase += pick(pick(GLOB.first_names_male,GLOB.first_names_female)) - code_phrase += " " - code_phrase += pick(GLOB.last_names) + var/new_name = pick(pick(GLOB.first_names_male,GLOB.first_names_female)) + new_name += " " + new_name += pick(GLOB.last_names) + . += new_name if(2) - code_phrase += pick(get_all_jobs())//Returns a job. + . += pick(get_all_jobs())//Returns a job. safety -= 1 if(2) switch(rand(1,3))//Food, drinks, or things. Only selectable once. if(1) - code_phrase += lowertext(pick(drinks)) + . += lowertext(pick(drinks)) if(2) - code_phrase += lowertext(pick(foods)) + . += lowertext(pick(foods)) if(3) - code_phrase += lowertext(pick(locations)) + . += lowertext(pick(locations)) safety -= 2 if(3) switch(rand(1,4))//Abstract nouns, objects, adjectives, threats. Can be selected more than once. if(1) - code_phrase += lowertext(pick(nouns)) + . += lowertext(pick(nouns)) if(2) - code_phrase += lowertext(pick(objects)) + . += lowertext(pick(objects)) if(3) - code_phrase += lowertext(pick(adjectives)) + . += lowertext(pick(adjectives)) if(4) - code_phrase += lowertext(pick(threats)) - if(words==1) - code_phrase += "." - else - code_phrase += ", " - - return code_phrase + . += lowertext(pick(threats)) + if(!return_list) + if(words==1) + . += "." + else + . += ", " diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index 48bdbad112..aeadfcf94e 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -98,7 +98,7 @@ SUBSYSTEM_DEF(atoms) else if(!A.initialized) BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT - return qdeleted || QDELETED(A) + return qdeleted || QDELING(A) /datum/controller/subsystem/atoms/proc/map_loader_begin() old_initialized = initialized diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 1496479fb7..a4e3aa2fef 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -3,6 +3,7 @@ SUBSYSTEM_DEF(blackbox) wait = 6000 flags = SS_NO_TICK_CHECK | SS_NO_INIT runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + init_order = INIT_ORDER_BLACKBOX var/list/msg_common = list() var/list/msg_science = list() @@ -18,6 +19,8 @@ SUBSYSTEM_DEF(blackbox) var/list/feedback = list() //list of datum/feedback_variable + var/sealed = FALSE //time to stop tracking stats? + //poll population /datum/controller/subsystem/blackbox/fire() if(!SSdbcore.Connect()) @@ -45,6 +48,8 @@ SUBSYSTEM_DEF(blackbox) feedback = SSblackbox.feedback + sealed = SSblackbox.sealed + //no touchie /datum/controller/subsystem/blackbox/can_vv_get(var_name) if(var_name == "feedback") @@ -55,6 +60,7 @@ SUBSYSTEM_DEF(blackbox) return FALSE /datum/controller/subsystem/blackbox/Shutdown() + sealed = FALSE set_val("ahelp_unresolved", GLOB.ahelp_tickets.active_tickets.len) var/pda_msg_amt = 0 @@ -95,6 +101,8 @@ SUBSYSTEM_DEF(blackbox) SSdbcore.MassInsert(format_table_name("feedback"), sqlrowlist, ignore_errors = TRUE, delayed = TRUE) /datum/controller/subsystem/blackbox/proc/LogBroadcast(blackbox_msg, freq) + if(sealed) + return switch(freq) if(1459) msg_common += blackbox_msg @@ -129,26 +137,38 @@ SUBSYSTEM_DEF(blackbox) return FV /datum/controller/subsystem/blackbox/proc/set_val(variable, value) + if(sealed) + return var/datum/feedback_variable/FV = find_feedback_datum(variable) FV.set_value(value) /datum/controller/subsystem/blackbox/proc/inc(variable, value) + if(sealed) + return var/datum/feedback_variable/FV = find_feedback_datum(variable) FV.inc(value) /datum/controller/subsystem/blackbox/proc/dec(variable,value) + if(sealed) + return var/datum/feedback_variable/FV = find_feedback_datum(variable) FV.dec(value) /datum/controller/subsystem/blackbox/proc/set_details(variable,details) + if(sealed) + return var/datum/feedback_variable/FV = find_feedback_datum(variable) FV.set_details(details) /datum/controller/subsystem/blackbox/proc/add_details(variable,details) + if(sealed) + return var/datum/feedback_variable/FV = find_feedback_datum(variable) FV.add_details(details) /datum/controller/subsystem/blackbox/proc/ReportDeath(mob/living/L) + if(sealed) + return if(!SSdbcore.Connect()) return if(!L || !L.key || !L.mind) @@ -166,19 +186,29 @@ SUBSYSTEM_DEF(blackbox) var/mob/LA = L.lastattacker laname = sanitizeSQL(LA.real_name) lakey = sanitizeSQL(LA.key) - var/sqlgender = sanitizeSQL(L.gender) var/sqlbrute = sanitizeSQL(L.getBruteLoss()) var/sqlfire = sanitizeSQL(L.getFireLoss()) var/sqlbrain = sanitizeSQL(L.getBrainLoss()) var/sqloxy = sanitizeSQL(L.getOxyLoss()) - var/sqltox = sanitizeSQL(L.getToxLoss()) - var/sqlclone = sanitizeSQL(L.getCloneLoss()) + var/sqltox = sanitizeSQL(L.getToxLoss()) + var/sqlclone = sanitizeSQL(L.getCloneLoss()) var/sqlstamina = sanitizeSQL(L.getStaminaLoss()) - var/coord = sanitizeSQL("[L.x], [L.y], [L.z]") + var/x_coord = sanitizeSQL(L.x) + var/y_coord = sanitizeSQL(L.y) + var/z_coord = sanitizeSQL(L.z) var/map = sanitizeSQL(SSmapping.config.map_name) - var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, coord, mapname, server_ip, server_port) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[SQLtime()]', '[laname]', '[lakey]', '[sqlgender]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina], '[coord]', '[map]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')") + var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (pod, x_coord, y_coord, z_coord, mapname, server_ip, server_port, round_id, tod, job, special, name, byondkey, laname, lakey, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss) VALUES ('[sqlpod]', '[x_coord]', '[y_coord]', '[z_coord]', '[map]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', [GLOB.round_id], '[SQLtime()]', '[sqljob]', '[sqlspecial]', '[sqlname]', '[sqlkey]', '[laname]', '[lakey]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina])") query_report_death.Execute() +/datum/controller/subsystem/blackbox/proc/Seal() + if(sealed) + return + if(IsAdminAdvancedProcCall()) + var/msg = "[key_name_admin(usr)] sealed the blackbox!" + message_admins(msg) + log_game("Blackbox sealed[IsAdminAdvancedProcCall() ? " by [key_name(usr)]" : ""].") + sealed = TRUE + //feedback variable datum, for storing all kinds of data /datum/feedback_variable diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index aefd62ed8e..3af0bcc399 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -224,7 +224,7 @@ SUBSYSTEM_DEF(job) //Get the players who are ready for(var/mob/dead/new_player/player in GLOB.player_list) - if(player.ready && player.mind && !player.mind.assigned_role) + if(player.ready == PLAYER_READY_TO_PLAY && player.mind && !player.mind.assigned_role) unassigned += player initial_players_to_assign = unassigned.len @@ -455,7 +455,7 @@ SUBSYSTEM_DEF(job) var/level5 = 0 //banned var/level6 = 0 //account too young for(var/mob/dead/new_player/player in GLOB.player_list) - if(!(player.ready && player.mind && !player.mind.assigned_role)) + if(!(player.ready == PLAYER_READY_TO_PLAY && player.mind && !player.mind.assigned_role)) continue //This player is not ready if(jobban_isbanned(player, job.title)) level5++ @@ -488,7 +488,7 @@ SUBSYSTEM_DEF(job) Debug("Popcap overflow Check observer located, Player: [player]") to_chat(player, "You have failed to qualify for any job you desired.") unassigned -= player - player.ready = 0 + player.ready = PLAYER_NOT_READY /datum/controller/subsystem/job/Recover() @@ -533,7 +533,7 @@ SUBSYSTEM_DEF(job) if(avail.len) SendToAtom(M, pick(avail), FALSE) return - + //pick an open spot on arrivals and dump em var/list/arrivals_turfs = shuffle(get_area_turfs(/area/shuttle/arrival)) if(arrivals_turfs.len) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index afff0cdf59..8933f0ff09 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -86,6 +86,8 @@ SUBSYSTEM_DEF(ticker) window_flash(C, ignorepref = TRUE) //let them know lobby has opened up. to_chat(world, "Welcome to [station_name()]!") current_state = GAME_STATE_PREGAME + //Everyone who wants to be an observer is now spawned + create_observers() if(!modevoted) send_gamemode_vote() fire() @@ -97,7 +99,7 @@ SUBSYSTEM_DEF(ticker) totalPlayersReady = 0 for(var/mob/dead/new_player/player in GLOB.player_list) ++totalPlayers - if(player.ready) + if(player.ready == PLAYER_READY_TO_PLAY) ++totalPlayersReady if(start_immediately) @@ -131,7 +133,7 @@ SUBSYSTEM_DEF(ticker) scripture_states = scripture_unlock_alert(scripture_states) SSshuttle.autoEnd() - if(!mode.explosion_in_progress && mode.check_finished() || force_ending) + if(!mode.explosion_in_progress && mode.check_finished(force_ending) || force_ending) current_state = GAME_STATE_FINISHED toggle_ooc(1) // Turn it on declare_completion(force_ending) @@ -408,7 +410,7 @@ SUBSYSTEM_DEF(ticker) /datum/controller/subsystem/ticker/proc/create_characters() for(var/mob/dead/new_player/player in GLOB.player_list) - if(player.ready && player.mind) + if(player.ready == PLAYER_READY_TO_PLAY && player.mind) GLOB.joined_player_list += player.ckey player.create_character(FALSE) else @@ -584,7 +586,7 @@ SUBSYSTEM_DEF(ticker) mode.declare_station_goal_completion() //medals, placed far down so that people can actually see the commendations. - if(GLOB.commendations) + if(GLOB.commendations.len) to_chat(world, "Medal Commendations:") for (var/com in GLOB.commendations) to_chat(world, com) @@ -612,6 +614,9 @@ SUBSYSTEM_DEF(ticker) //Collects persistence features SSpersistence.CollectData() + //stop collecting feedback during grifftime + SSblackbox.Seal() + sleep(50) if(mode.station_was_nuked) Reboot("Station destroyed by Nuclear Device.", "nuke") @@ -793,6 +798,13 @@ SUBSYSTEM_DEF(ticker) else timeLeft = newtime +//Everyone who wanted to be an observer gets made one now +/datum/controller/subsystem/ticker/proc/create_observers() + for(var/mob/dead/new_player/player in GLOB.player_list) + if(player.ready == PLAYER_READY_TO_OBSERVE && player.mind) + //Break chain since this has a sleep input in it + addtimer(CALLBACK(player, /mob/dead/new_player.proc/make_me_an_observer), 1) + /datum/controller/subsystem/ticker/proc/load_mode() var/mode = trim(file2text("data/mode.txt")) if(mode) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 2203e0f1f5..3ebf8f0952 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -43,7 +43,7 @@ SUBSYSTEM_DEF(timer) WARNING(msg) if(bucket_auto_reset) bucket_resolution = 0 - + log_world("Active timers at tick [world.time]:") for(var/I in processing) var/datum/timedevent/TE = I @@ -365,10 +365,13 @@ SUBSYSTEM_DEF(timer) var/datum/timedevent/timer = new(callback, timeToRun, flags, hash) if (flags & TIMER_STOPPABLE) return timer.id + return TIMER_ID_NULL /proc/deltimer(id) if (!id) return FALSE + if (id == TIMER_ID_NULL) + CRASH("Tried to delete a null timerid. Use TIMER_STOPPABLE flag") if (!istext(id)) if (istype(id, /datum/timedevent)) qdel(id) diff --git a/code/datums/antagonists/datum_clockcult.dm b/code/datums/antagonists/datum_clockcult.dm index 6c8b83daa4..f62bb7f9ae 100644 --- a/code/datums/antagonists/datum_clockcult.dm +++ b/code/datums/antagonists/datum_clockcult.dm @@ -20,22 +20,28 @@ to_chat(AI, "Anomaly Detected. Returned to core!") //The AI needs to be in its core to properly be converted . = is_eligible_servant(new_owner.current) if(!silent && new_owner.current) - if(issilicon(new_owner.current)) - to_chat(new_owner.current, "You are unable to compute this truth. Your vision glows a brilliant yellow, and all at once it comes to you. Ratvar, the \ - Clockwork Justiciar, lies in exile, derelict and forgotten in an unseen realm.") + if(.) + to_chat(new_owner.current, "The world before you suddenly glows a brilliant yellow. [issilicon(new_owner.current) ? "You cannot compute this truth!" : \ + "Your mind is racing!"] You hear the whooshing steam and cl[pick("ank", "ink", "unk", "ang")]ing cogs of a billion billion machines, and all at once it comes to you.
\ + Ratvar, the Clockwork Justiciar, [GLOB.ratvar_awakens ? "has been freed from his eternal prison" : "lies in exile, derelict and forgotten in an unseen realm"].
") + flash_color(new_owner.current, flash_color = list("#BE8700", "#BE8700", "#BE8700", rgb(0,0,0)), flash_time = 50) else - to_chat(new_owner.current, "[iscarbon(new_owner.current) ? "Your mind is racing! Your body feels incredibly light! ":""]Your world glows a brilliant \ - yellow! All at once it comes to you. Ratvar, the Clockwork Justiciar, lies in exile, derelict and forgotten in an unseen realm.") - if(!.) - new_owner.current.visible_message("[new_owner.current] seems to resist an unseen force!") - to_chat(new_owner.current, "And yet, you somehow push it all away.") + new_owner.current.visible_message("[new_owner.current] seems to resist an unseen force!", null, null, 7, new_owner.current) + to_chat(new_owner.current, "The world before you suddenly glows a brilliant yellow. [issilicon(new_owner.current) ? "You cannot compute this truth!" : \ + "Your mind is racing!"] You hear the whooshing steam and cl[pick("ank", "ink", "unk", "ang")]ing cogs of a billion billion machines, and the sound \ + is a meaningless cacophony.
\ + You see an abomination of rusting parts[GLOB.ratvar_awakens ? ", and it is here.
It is too late" : \ + " in an endless grey void.
It cannot be allowed to escape"].
") + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/clockcultalr.ogg', 40, TRUE, frequency = 100000, pressure_affected = FALSE) + flash_color(new_owner.current, flash_color = list("#BE8700", "#BE8700", "#BE8700", rgb(0,0,0)), flash_time = 5) /datum/antagonist/clockcult/greet() if(!owner.current || silent) return - owner.current.visible_message("[owner.current]'s eyes glow a blazing yellow!") + owner.current.visible_message("[owner.current]'s eyes glow a blazing yellow!", null, null, 7, owner.current) //don't show the owner this message to_chat(owner.current, "Assist your new companions in their righteous efforts. Your goal is theirs, and theirs yours. You serve the Clockwork \ Justiciar above all else. Perform his every whim without hesitation.") + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/clockcultalr.ogg', 70, FALSE, pressure_affected = FALSE) /datum/antagonist/clockcult/on_gain() var/mob/living/current = owner.current @@ -47,10 +53,14 @@ owner.current.log_message("Has been converted to the cult of Ratvar!", INDIVIDUAL_ATTACK_LOG) if(issilicon(current)) if(iscyborg(current) && !silent) - to_chat(current, "You have been desynced from your master AI.") - to_chat(current, "In addition, your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.") + var/mob/living/silicon/robot/R = current + if(R.connected_ai && !is_servant_of_ratvar(R.connected_ai)) + to_chat(R, "You have been desynced from your master AI.
\ + In addition, your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.
") + else + to_chat(R, "Your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.") if(isAI(current)) - to_chat(current, "You are able to use your cameras to listen in on conversations.") + to_chat(current, "You are now able to use your cameras to listen in on conversations, but can no longer speak in anything but Ratvarian.") to_chat(current, "You can communicate with other servants by using the Hierophant Network action button in the upper left.") else if(isbrain(current) || isclockmob(current)) to_chat(current, "You can communicate with other servants by using the Hierophant Network action button in the upper left.") @@ -88,11 +98,7 @@ A.eyeobj.relay_speech = TRUE for(var/mob/living/silicon/robot/R in A.connected_robots) if(R.connected_ai == A) - R.visible_message("[R]'s eyes glow a blazing yellow!", \ - "Assist your new companions in their righteous efforts. Your goal is theirs, and theirs yours. You serve the Clockwork Justiciar above all else. Perform his every \ - whim without hesitation.") - to_chat(R, "Your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.") - add_servant_of_ratvar(R, TRUE) + add_servant_of_ratvar(R) S.laws = new/datum/ai_laws/ratvar S.laws.associate(S) S.update_icons() diff --git a/code/datums/antagonists/datum_iaa.dm b/code/datums/antagonists/datum_iaa.dm new file mode 100644 index 0000000000..fd2c4e89a0 --- /dev/null +++ b/code/datums/antagonists/datum_iaa.dm @@ -0,0 +1,11 @@ +/datum/antagonist/iaa + +/datum/antagonist/iaa/apply_innate_effects() + .=..() //in case the base is used in future + if(owner&&owner.current) + give_pinpointer(owner.current) + +/datum/antagonist/iaa/remove_innate_effects() + .=..() + if(owner&&owner.current) + owner.current.remove_status_effect(/datum/status_effect/agent_pinpointer) \ No newline at end of file diff --git a/code/datums/antagonists/datum_internal_affairs.dm b/code/datums/antagonists/datum_internal_affairs.dm new file mode 100644 index 0000000000..7cc3bed0af --- /dev/null +++ b/code/datums/antagonists/datum_internal_affairs.dm @@ -0,0 +1,327 @@ +#define PINPOINTER_MINIMUM_RANGE 15 +#define PINPOINTER_EXTRA_RANDOM_RANGE 10 +#define PINPOINTER_PING_TIME 40 +#define PROB_ACTUAL_TRAITOR 20 +#define TRAITOR_AGENT_ROLE "Syndicate External Affairs Agent" + +/datum/antagonist/traitor/internal_affairs + base_datum_custom = ANTAG_DATUM_IAA_CUSTOM + human_datum = ANTAG_DATUM_IAA_HUMAN + ai_datum = ANTAG_DATUM_IAA_AI + + + +/datum/antagonist/traitor/AI/internal_affairs + name = "Internal Affairs Agent" + employer = "Nanotrasen" + special_role = "internal affairs agent" + base_datum_custom = ANTAG_DATUM_IAA_CUSTOM + var/syndicate = FALSE + var/last_man_standing = FALSE + var/list/datum/mind/targets_stolen + +/datum/antagonist/traitor/AI/internal_affairs/custom + silent = TRUE + should_give_codewords = FALSE + give_objectives = FALSE + +/datum/antagonist/traitor/human/internal_affairs + name = "Internal Affairs Agent" + employer = "Nanotrasen" + special_role = "internal affairs agent" + base_datum_custom = ANTAG_DATUM_IAA_CUSTOM + var/syndicate = FALSE + var/last_man_standing = FALSE + var/list/datum/mind/targets_stolen + +/datum/antagonist/traitor/human/internal_affairs/custom + silent = TRUE + should_give_codewords = FALSE + give_objectives = FALSE + should_equip = FALSE //Duplicating TCs is dangerous + +/datum/antagonist/traitor/human/internal_affairs/transfer_important_variables(datum/antagonist/traitor/human/internal_affairs/other) + ..(other) + other.syndicate = syndicate + other.last_man_standing = last_man_standing + other.targets_stolen = targets_stolen + +/datum/antagonist/traitor/AI/internal_affairs/transfer_important_variables(datum/antagonist/traitor/human/internal_affairs/other) + ..(other) + other.syndicate = syndicate + other.last_man_standing = last_man_standing + other.targets_stolen = targets_stolen + +/datum/antagonist/traitor/human/internal_affairs/proc/give_pinpointer() + if(owner && owner.current) + owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer) + +/datum/antagonist/traitor/human/internal_affairs/apply_innate_effects() + .=..() //in case the base is used in future + if(owner&&owner.current) + give_pinpointer(owner.current) + +/datum/antagonist/traitor/human/internal_affairs/remove_innate_effects() + .=..() + if(owner&&owner.current) + owner.current.remove_status_effect(/datum/status_effect/agent_pinpointer) + +/datum/antagonist/traitor/internal_affairs/custom + ai_datum = ANTAG_DATUM_IAA_AI_CUSTOM + human_datum = ANTAG_DATUM_IAA_HUMAN_CUSTOM + +/datum/antagonist/traitor/human/internal_affairs/on_gain() + START_PROCESSING(SSprocessing, src) + .=..() +/datum/antagonist/traitor/human/internal_affairs/on_removal() + STOP_PROCESSING(SSprocessing,src) + .=..() +/datum/antagonist/traitor/human/internal_affairs/process() + iaa_process() + +/datum/antagonist/traitor/AI/internal_affairs/on_gain() + START_PROCESSING(SSprocessing, src) + .=..() +/datum/antagonist/traitor/AI/internal_affairs/on_removal() + STOP_PROCESSING(SSprocessing,src) + .=..() +/datum/antagonist/traitor/AI/internal_affairs/process() + iaa_process() + +/datum/status_effect/agent_pinpointer + id = "agent_pinpointer" + duration = -1 + tick_interval = PINPOINTER_PING_TIME + alert_type = /obj/screen/alert/status_effect/agent_pinpointer + var/minimum_range = PINPOINTER_MINIMUM_RANGE + var/mob/scan_target = null + +/obj/screen/alert/status_effect/agent_pinpointer + name = "Internal Affairs Integrated Pinpointer" + desc = "Even stealthier than a normal implant." + icon = 'icons/obj/device.dmi' + icon_state = "pinon" + +/datum/status_effect/agent_pinpointer/proc/point_to_target() //If we found what we're looking for, show the distance and direction + if(!scan_target) + linked_alert.icon_state = "pinonnull" + return + var/turf/here = get_turf(owner) + var/turf/there = get_turf(scan_target) + if(here.z != there.z) + linked_alert.icon_state = "pinonnull" + return + if(get_dist_euclidian(here,there)<=minimum_range + rand(0, PINPOINTER_EXTRA_RANDOM_RANGE)) + linked_alert.icon_state = "pinondirect" + else + linked_alert.setDir(get_dir(here, there)) + switch(get_dist(here, there)) + if(1 to 8) + linked_alert.icon_state = "pinonclose" + if(9 to 16) + linked_alert.icon_state = "pinonmedium" + if(16 to INFINITY) + linked_alert.icon_state = "pinonfar" + +/datum/status_effect/agent_pinpointer/proc/scan_for_target() + scan_target = null + if(owner) + if(owner.mind) + if(owner.mind.objectives) + for(var/datum/objective/objective_ in owner.mind.objectives) + if(!is_internal_objective(objective_)) + continue + var/datum/objective/assassinate/internal/objective = objective_ + var/mob/current = objective.target.current + if(current&¤t.stat!=DEAD) + scan_target = current + break + +/datum/status_effect/agent_pinpointer/tick() + if(!owner) + qdel(src) + return + scan_for_target() + point_to_target() + + +/proc/is_internal_objective(datum/objective/O) + return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal)) + +/datum/antagonist/traitor/proc/replace_escape_objective() + if(!owner||!owner.objectives) + return + for (var/objective_ in owner.objectives) + if(!(istype(objective_, /datum/objective/escape)||istype(objective_,/datum/objective/survive))) + continue + remove_objective(objective_) + + var/datum/objective/martyr/martyr_objective = new + martyr_objective.owner = owner + add_objective(martyr_objective) + +/datum/antagonist/traitor/proc/reinstate_escape_objective() + if(!owner||!owner.objectives) + return + for (var/objective_ in owner.objectives) + if(!istype(objective_, /datum/objective/martyr)) + continue + remove_objective(objective_) + +/datum/antagonist/traitor/human/internal_affairs/reinstate_escape_objective() + ..() + var/datum/objective/escape/escape_objective = new + escape_objective.owner = owner + add_objective(escape_objective) + +/datum/antagonist/traitor/AI/internal_affairs/reinstate_escape_objective() + ..() + var/datum/objective/survive/survive_objective = new + survive_objective.owner = owner + add_objective(survive_objective) + +/datum/antagonist/traitor/proc/steal_targets(datum/mind/victim) + var/datum/antagonist/traitor/human/internal_affairs/this = src //Should only use this if IAA + + if(!owner.current||owner.current.stat==DEAD) + return + to_chat(owner.current, " Target eliminated: [victim.name]") + for(var/objective_ in victim.objectives) + if(istype(objective_, /datum/objective/assassinate/internal)) + var/datum/objective/assassinate/internal/objective = objective_ + if(objective.target==owner) + continue + else if(this.targets_stolen.Find(objective.target) == 0) + var/datum/objective/assassinate/internal/new_objective = new + new_objective.owner = owner + new_objective.target = objective.target + new_objective.update_explanation_text() + add_objective(new_objective) + this.targets_stolen += objective.target + var/status_text = objective.check_completion() ? "neutralised" : "active" + to_chat(owner.current, " New target added to database: [objective.target.name] ([status_text]) ") + else if(istype(objective_, /datum/objective/destroy/internal)) + var/datum/objective/destroy/internal/objective = objective_ + var/datum/objective/destroy/internal/new_objective = new + if(objective.target==owner) + continue + else if(this.targets_stolen.Find(objective.target) == 0) + new_objective.owner = owner + new_objective.target = objective.target + new_objective.update_explanation_text() + add_objective(new_objective) + this.targets_stolen += objective.target + var/status_text = objective.check_completion() ? "neutralised" : "active" + to_chat(owner.current, " New target added to database: [objective.target.name] ([status_text]) ") + this.last_man_standing = TRUE + for(var/objective_ in owner.objectives) + if(!is_internal_objective(objective_)) + continue + var/datum/objective/assassinate/internal/objective = objective_ + if(!objective.check_completion()) + this.last_man_standing = FALSE + return + if(this.last_man_standing) + if(this.syndicate) + to_chat(owner.current," All the loyalist agents are dead, and no more is required of you. Die a glorious death, agent. ") + else + to_chat(owner.current," All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.") + replace_escape_objective(owner) + +/datum/antagonist/traitor/proc/iaa_process() + var/datum/antagonist/traitor/human/internal_affairs/this = src //Should only use this if IAA + if(owner&&owner.current&&owner.current.stat!=DEAD) + for(var/objective_ in owner.objectives) + if(!is_internal_objective(objective_)) + continue + var/datum/objective/assassinate/internal/objective = objective_ + if(!objective.target) + continue + if(objective.check_completion()) + if(objective.stolen) + continue + else + steal_targets(objective.target) + objective.stolen = TRUE + else + if(objective.stolen) + var/fail_msg = "Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! " + if(this.last_man_standing) + if(this.syndicate) + fail_msg += " You no longer have permission to die. " + else + fail_msg += " The truth could still slip out! Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated." + reinstate_escape_objective(owner) + this.last_man_standing = FALSE + to_chat(owner.current, fail_msg) + objective.stolen = FALSE + +/datum/antagonist/traitor/proc/forge_iaa_objectives() + var/datum/antagonist/traitor/human/internal_affairs/this = src //Should only use this if IAA + if(SSticker.mode.target_list.len && SSticker.mode.target_list[owner]) // Is a double agent + + // Assassinate + var/datum/mind/target_mind = SSticker.mode.target_list[owner] + if(issilicon(target_mind.current)) + var/datum/objective/destroy/internal/destroy_objective = new + destroy_objective.owner = owner + destroy_objective.target = target_mind + destroy_objective.update_explanation_text() + else + var/datum/objective/assassinate/internal/kill_objective = new + kill_objective.owner = owner + kill_objective.target = target_mind + kill_objective.update_explanation_text() + add_objective(kill_objective) + + //Optional traitor objective + if(prob(PROB_ACTUAL_TRAITOR)) + employer = "The Syndicate" + owner.special_role = TRAITOR_AGENT_ROLE + special_role = TRAITOR_AGENT_ROLE + this.syndicate = TRUE + forge_single_objective() + + else + ..() // Give them standard objectives. + return + +/datum/antagonist/traitor/human/internal_affairs/forge_traitor_objectives() + forge_iaa_objectives() + var/datum/objective/escape/escape_objective = new + escape_objective.owner = owner + add_objective(escape_objective) + +/datum/antagonist/traitor/AI/internal_affairs/forge_traitor_objectives() + forge_iaa_objectives() + var/datum/objective/survive/survive_objective = new + survive_objective.owner = owner + add_objective(survive_objective) + +/datum/antagonist/traitor/proc/greet_iaa() + var/datum/antagonist/traitor/human/internal_affairs/this = src //Should only use this if IAA + var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence") + + to_chat(owner.current, "You are the [special_role].") + if(this.syndicate) + to_chat(owner.current, "Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court.") + to_chat(owner.current, "Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.") + to_chat(owner.current, " You have been provided with a standard uplink to accomplish your task. ") + else + to_chat(owner.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.") + to_chat(owner.current, "While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.") + to_chat(owner.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.") + + to_chat(owner.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.") + owner.announce_objectives() + +/datum/antagonist/traitor/AI/internal_affairs/greet() + greet_iaa() +/datum/antagonist/traitor/human/internal_affairs/greet() + greet_iaa() + + +#undef PROB_ACTUAL_TRAITOR +#undef PINPOINTER_EXTRA_RANDOM_RANGE +#undef PINPOINTER_MINIMUM_RANGE +#undef PINPOINTER_PING_TIME diff --git a/code/datums/antagonists/datum_traitor.dm b/code/datums/antagonists/datum_traitor.dm new file mode 100644 index 0000000000..e2536ad077 --- /dev/null +++ b/code/datums/antagonists/datum_traitor.dm @@ -0,0 +1,326 @@ +/datum/antagonist/traitor + name = "Traitor" + var/should_specialise = TRUE //do we split into AI and human + var/base_datum_custom = ANTAG_DATUM_TRAITOR_CUSTOM //used for body transfer + var/ai_datum = ANTAG_DATUM_TRAITOR_AI + var/human_datum = ANTAG_DATUM_TRAITOR_HUMAN + var/special_role = "traitor" + var/employer = "The Syndicate" + var/give_objectives = TRUE + var/should_give_codewords = TRUE + var/list/objectives_given = list() + +/datum/antagonist/traitor/proc/transfer_important_variables(datum/antagonist/traitor/other) + other.silent = silent + other.employer = employer + other.special_role = special_role + other.objectives_given = objectives_given + +/datum/antagonist/traitor/custom + ai_datum = ANTAG_DATUM_TRAITOR_AI_CUSTOM + human_datum = ANTAG_DATUM_TRAITOR_HUMAN_CUSTOM + +/datum/antagonist/traitor/human + should_specialise = FALSE + var/should_equip = TRUE +/datum/antagonist/traitor/human/custom + silent = TRUE + should_give_codewords = FALSE + give_objectives = FALSE + should_equip = FALSE //Duplicating TCs is dangerous + +/datum/antagonist/traitor/AI + should_specialise = FALSE +/datum/antagonist/traitor/AI/custom + silent = TRUE + should_give_codewords = FALSE + give_objectives = FALSE + + +/datum/antagonist/traitor/on_body_transfer(mob/living/old_body, mob/living/new_body) + if(istype(new_body,/mob/living/silicon/ai)==istype(old_body,/mob/living/silicon/ai)) + ..() + else + silent = TRUE + owner.add_antag_datum(base_datum_custom) + for(var/datum/antagonist/traitor/new_datum in owner.antag_datums) + if(new_datum == src) + continue + transfer_important_variables(new_datum) + break + on_removal() + + + +/datum/antagonist/traitor/human/custom //used to give custom objectives + silent = TRUE + give_objectives = FALSE + should_give_codewords = FALSE +/datum/antagonist/traitor/AI/custom //used to give custom objectives + silent = TRUE + give_objectives = FALSE + should_give_codewords = FALSE + +/datum/antagonist/traitor/proc/specialise() + silent = TRUE + if(owner.current&&istype(owner.current,/mob/living/silicon/ai)) + owner.add_antag_datum(ai_datum) + else owner.add_antag_datum(human_datum) + on_removal() + +/datum/antagonist/traitor/on_gain() + if(should_specialise) + specialise() + return + SSticker.mode.traitors+=owner + owner.special_role = special_role + if(give_objectives) + forge_traitor_objectives() + finalize_traitor() + ..() + +/datum/antagonist/traitor/apply_innate_effects() + if(owner.assigned_role == "Clown") + var/mob/living/carbon/human/traitor_mob = owner.current + if(traitor_mob&&istype(traitor_mob)) + if(!silent) to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") + traitor_mob.dna.remove_mutation(CLOWNMUT) + +/datum/antagonist/traitor/remove_innate_effects() + if(owner.assigned_role == "Clown") + var/mob/living/carbon/human/traitor_mob = owner.current + if(traitor_mob&&istype(traitor_mob)) + traitor_mob.dna.add_mutation(CLOWNMUT) + +/datum/antagonist/traitor/on_removal() + if(should_specialise) + return ..()//we never did any of this anyway + SSticker.mode.traitors -= owner + for(var/O in objectives_given) + owner.objectives -= O + objectives_given = list() + if(!silent && owner.current) + to_chat(owner.current," You are no longer the [special_role]! ") + owner.special_role = null + ..() + +/datum/antagonist/traitor/AI/on_removal() + if(owner.current && isAI(owner.current)) + var/mob/living/silicon/ai/A = owner.current + A.set_zeroth_law("") + A.verbs -= /mob/living/silicon/ai/proc/choose_modules + A.malf_picker.remove_verbs(A) + qdel(A.malf_picker) + ..() + +/datum/antagonist/traitor/proc/add_objective(var/datum/objective/O) + owner.objectives += O + objectives_given += O + +/datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O) + owner.objectives -= O + objectives_given -= O + +/datum/antagonist/traitor/proc/forge_traitor_objectives() + return +/datum/antagonist/traitor/human/forge_traitor_objectives() + var/is_hijacker = prob(10) + var/martyr_chance = prob(20) + var/objective_count = is_hijacker //Hijacking counts towards number of objectives + if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors + if(!SSticker.mode.exchange_red) + SSticker.mode.exchange_red = owner + else + SSticker.mode.exchange_blue = owner + assign_exchange_role(SSticker.mode.exchange_red) + assign_exchange_role(SSticker.mode.exchange_blue) + objective_count += 1 //Exchange counts towards number of objectives + for(var/i = objective_count, i < config.traitor_objectives_amount, i++) + forge_single_objective() + + if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount + if (!(locate(/datum/objective/hijack) in owner.objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = owner + add_objective(hijack_objective) + return + + + var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. + for(var/datum/objective/O in owner.objectives) + if(!O.martyr_compatible) + martyr_compatibility = 0 + break + + if(martyr_compatibility && martyr_chance) + var/datum/objective/martyr/martyr_objective = new + martyr_objective.owner = owner + add_objective(martyr_objective) + return + + else + if(!(locate(/datum/objective/escape) in owner.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = owner + add_objective(escape_objective) + return + +/datum/antagonist/traitor/AI/forge_traitor_objectives() + var/objective_count = 0 + + if(prob(30)) + objective_count += forge_single_objective() + + for(var/i = objective_count, i < config.traitor_objectives_amount, i++) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = owner + kill_objective.find_target() + add_objective(kill_objective) + + var/datum/objective/survive/survive_objective = new + survive_objective.owner = owner + add_objective(survive_objective) +/datum/antagonist/traitor/proc/forge_single_objective() + return 0 +/datum/antagonist/traitor/human/forge_single_objective() //Returns how many objectives are added + .=1 + if(prob(50)) + var/list/active_ais = active_ais() + if(active_ais.len && prob(100/GLOB.joined_player_list.len)) + var/datum/objective/destroy/destroy_objective = new + destroy_objective.owner = owner + destroy_objective.find_target() + add_objective(destroy_objective) + else if(prob(30)) + var/datum/objective/maroon/maroon_objective = new + maroon_objective.owner = owner + maroon_objective.find_target() + add_objective(maroon_objective) + else + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = owner + kill_objective.find_target() + add_objective(kill_objective) + else + var/datum/objective/steal/steal_objective = new + steal_objective.owner = owner + steal_objective.find_target() + add_objective(steal_objective) + +/datum/antagonist/traitor/AI/forge_single_objective() + .=1 + var/special_pick = rand(1,4) + switch(special_pick) + if(1) + var/datum/objective/block/block_objective = new + block_objective.owner = owner + add_objective(block_objective) + if(2) + var/datum/objective/purge/purge_objective = new + purge_objective.owner = owner + add_objective(purge_objective) + if(3) + var/datum/objective/robot_army/robot_objective = new + robot_objective.owner = owner + add_objective(robot_objective) + if(4) //Protect and strand a target + var/datum/objective/protect/yandere_one = new + yandere_one.owner = owner + add_objective(yandere_one) + yandere_one.find_target() + var/datum/objective/maroon/yandere_two = new + yandere_two.owner = owner + yandere_two.target = yandere_one.target + yandere_two.update_explanation_text() // normally called in find_target() + add_objective(yandere_two) + .=2 +/datum/antagonist/traitor/greet() + to_chat(owner.current, "You are the [owner.special_role].") + owner.announce_objectives() + if(should_give_codewords) + give_codewords() + +/datum/antagonist/traitor/proc/finalize_traitor() + SSticker.mode.update_traitor_icons_added(owner) + return + +/datum/antagonist/traitor/AI/finalize_traitor() + ..() + add_law_zero() + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE) + owner.current.grant_language(/datum/language/codespeak) + +/datum/antagonist/traitor/human/finalize_traitor() + ..() + if(should_equip) + equip(silent) + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE) + +/datum/antagonist/traitor/proc/give_codewords() + if(!owner.current) + return + var/mob/traitor_mob=owner.current + + to_chat(traitor_mob, "The Syndicate provided you with the following information on how to identify their agents:") + to_chat(traitor_mob, "Code Phrase: [GLOB.syndicate_code_phrase]") + to_chat(traitor_mob, "Code Response: [GLOB.syndicate_code_response]") + + traitor_mob.mind.store_memory("Code Phrase: [GLOB.syndicate_code_phrase]") + traitor_mob.mind.store_memory("Code Response: [GLOB.syndicate_code_response]") + + to_chat(traitor_mob, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") + +/datum/antagonist/traitor/AI/proc/add_law_zero() + var/mob/living/silicon/ai/killer = owner.current + if(!killer || !istype(killer)) + return + var/law = "Accomplish your objectives at all costs." + var/law_borg = "Accomplish your AI's objectives at all costs." + killer.set_zeroth_law(law, law_borg) + killer.set_syndie_radio() + to_chat(killer, "Your radio has been upgraded! Use :t to speak on an encrypted channel with Syndicate Agents!") + killer.add_malf_picker() + +/datum/antagonist/traitor/proc/equip(var/silent = FALSE) +/datum/antagonist/traitor/human/equip(var/silent = FALSE) + owner.equip_traitor(employer, silent) + +/datum/antagonist/traitor/human/proc/assign_exchange_role() + //set faction + var/faction = "red" + if(owner == SSticker.mode.exchange_blue) + faction = "blue" + + //Assign objectives + var/datum/objective/steal/exchange/exchange_objective = new + exchange_objective.set_faction(faction,((faction == "red") ? SSticker.mode.exchange_blue : SSticker.mode.exchange_red)) + exchange_objective.owner = owner + add_objective(exchange_objective) + + if(prob(20)) + var/datum/objective/steal/exchange/backstab/backstab_objective = new + backstab_objective.set_faction(faction) + backstab_objective.owner = owner + add_objective(backstab_objective) + + //Spawn and equip documents + var/mob/living/carbon/human/mob = owner.current + + var/obj/item/weapon/folder/syndicate/folder + if(owner == SSticker.mode.exchange_red) + folder = new/obj/item/weapon/folder/syndicate/red(mob.loc) + else + folder = new/obj/item/weapon/folder/syndicate/blue(mob.loc) + + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store + ) + + var/where = "At your feet" + var/equipped_slot = mob.equip_in_one_of_slots(folder, slots) + if (equipped_slot) + where = "In your [equipped_slot]" + to_chat(mob, "

[where] is a folder containing secret documents that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.
") + diff --git a/code/datums/mind.dm b/code/datums/mind.dm index cf7368a879..4e5fa6a612 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -187,15 +187,7 @@ /datum/mind/proc/remove_traitor() if(src in SSticker.mode.traitors) - SSticker.mode.traitors -= src - if(isAI(current)) - var/mob/living/silicon/ai/A = current - A.set_zeroth_law("") - A.verbs -= /mob/living/silicon/ai/proc/choose_modules - A.malf_picker.remove_verbs(A) - qdel(A.malf_picker) - special_role = null - remove_antag_equip() + src.remove_antag_datum(ANTAG_DATUM_TRAITOR) SSticker.mode.update_traitor_icons_removed(src) /datum/mind/proc/remove_nukeop() @@ -263,6 +255,68 @@ if(gang_datum) gang_datum.remove_gang_hud(src) +/datum/mind/proc/equip_traitor(var/employer = "The Syndicate", var/silent = FALSE) + if(!current) + return + var/mob/living/carbon/human/traitor_mob = current + if (!istype(traitor_mob)) + return + . = 1 + + var/list/all_contents = traitor_mob.GetAllContents() + var/obj/item/device/pda/PDA = locate() in all_contents + var/obj/item/device/radio/R = locate() in all_contents + var/obj/item/weapon/pen/P = locate() in all_contents //including your PDA-pen! + + var/obj/item/uplink_loc + + if(traitor_mob.client && traitor_mob.client.prefs) + switch(traitor_mob.client.prefs.uplink_spawn_loc) + if(UPLINK_PDA) + uplink_loc = PDA + if(!uplink_loc) + uplink_loc = R + if(!uplink_loc) + uplink_loc = P + if(UPLINK_RADIO) + uplink_loc = R + if(!uplink_loc) + uplink_loc = PDA + if(!uplink_loc) + uplink_loc = P + if(UPLINK_PEN) + uplink_loc = P + if(!uplink_loc) + uplink_loc = PDA + if(!uplink_loc) + uplink_loc = R + + if (!uplink_loc) + if(!silent) to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.") + . = 0 + else + var/obj/item/device/uplink/U = new(uplink_loc) + U.owner = "[traitor_mob.key]" + uplink_loc.hidden_uplink = U + + if(uplink_loc == R) + R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ)) + + if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(R.traitor_frequency)] to unlock its hidden features.") + traitor_mob.mind.store_memory("Radio Frequency: [format_frequency(R.traitor_frequency)] ([R.name]).") + + else if(uplink_loc == PDA) + PDA.lock_code = "[rand(100,999)] [pick("Alpha","Bravo","Charlie","Delta","Echo","Foxtrot","Golf","Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar","Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor","Whiskey","X-ray","Yankee","Zulu")]" + + if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.") + traitor_mob.mind.store_memory("Uplink Passcode: [PDA.lock_code] ([PDA.name]).") + + else if(uplink_loc == P) + P.traitor_unlock_degrees = rand(1, 360) + + if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [P.traitor_unlock_degrees] from its starting position to unlock its hidden features.") + traitor_mob.mind.store_memory("Uplink Degrees: [P.traitor_unlock_degrees] ([P.name]).") + //Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does. @@ -1157,27 +1211,29 @@ else if (href_list["traitor"]) switch(href_list["traitor"]) if("clear") + to_chat(current, "You have been brainwashed!") remove_traitor() - to_chat(current, "You have been brainwashed! You are no longer a traitor!") message_admins("[key_name_admin(usr)] has de-traitor'ed [current].") log_admin("[key_name(usr)] has de-traitor'ed [current].") SSticker.mode.update_traitor_icons_removed(src) if("traitor") if(!(src in SSticker.mode.traitors)) - SSticker.mode.traitors += src - special_role = "traitor" - to_chat(current, "You are a traitor!") message_admins("[key_name_admin(usr)] has traitor'ed [current].") log_admin("[key_name(usr)] has traitor'ed [current].") - if(isAI(current)) - var/mob/living/silicon/ai/A = current - SSticker.mode.add_law_zero(A) - SSticker.mode.update_traitor_icons_added(src) + make_Traitor() if("autoobjectives") - SSticker.mode.forge_traitor_objectives(src) - to_chat(usr, "The objectives for traitor [key] have been generated. You can edit them and anounce manually.") + var/datum/antagonist/traitor/traitordatum = has_antag_datum(ANTAG_DATUM_TRAITOR) + if(!traitordatum) + message_admins("[key_name_admin(usr)] has traitor'ed [current] as part of autoobjectives.") + log_admin("[key_name(usr)] has traitor'ed [current] as part of autoobjectives.") + make_Traitor() + else + log_admin("[key_name(usr)] has forged objectives for [current] as part of autoobjectives.") + traitordatum.forge_traitor_objectives() + to_chat(usr, "The objectives for traitor [key] have been generated. You can edit them and anounce manually.") + else if(href_list["devil"]) var/datum/antagonist/devil/devilinfo = has_antag_datum(ANTAG_DATUM_DEVIL) @@ -1353,9 +1409,11 @@ message_admins("[key_name_admin(usr)] changed [current]'s telecrystal count to [crystals].") log_admin("[key_name(usr)] changed [current]'s telecrystal count to [crystals].") if("uplink") - if(!SSticker.mode.equip_traitor(current, !(src in SSticker.mode.traitors))) + if(!equip_traitor()) to_chat(usr, "Equipping a syndicate failed!") - log_admin("[key_name(usr)] attempted to give [current] an uplink.") + log_admin("[key_name(usr)] tried and failed to give [current] an uplink.") + else + log_admin("[key_name(usr)] gave [current] an uplink.") else if (href_list["obj_announce"]) announce_objectives() @@ -1383,12 +1441,10 @@ qdel(H) /datum/mind/proc/make_Traitor() - if(!(src in SSticker.mode.traitors)) - SSticker.mode.traitors += src - special_role = "traitor" - SSticker.mode.forge_traitor_objectives(src) - SSticker.mode.finalize_traitor(src) - SSticker.mode.greet_traitor(src) + if(!(has_antag_datum(ANTAG_DATUM_TRAITOR))) + var/datum/antagonist/traitor/traitordatum = add_antag_datum(ANTAG_DATUM_TRAITOR) + return traitordatum + /datum/mind/proc/make_Nuke(turf/spawnloc, nuke_code, leader=0, telecrystals = TRUE) if(!(src in SSticker.mode.syndicates)) @@ -1494,7 +1550,6 @@ qdel(flash) take_uplink() var/fail = 0 -// fail |= !SSticker.mode.equip_traitor(current, 1) fail |= !SSticker.mode.equip_revolutionary(current) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 1f9b25361c..7a249c9076 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -200,7 +200,7 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w to_chat(changeling.current, "You are [changeling.changeling.changelingID], a changeling! You have absorbed and taken the form of a human.") to_chat(changeling.current, "Use say \":g message\" to communicate with your fellow changelings.") to_chat(changeling.current, "You must complete the following tasks:") - changeling.current.playsound_local('sound/ambience/antag/ling_aler.ogg',100,0) + changeling.current.playsound_local(get_turf(changeling.current), 'sound/ambience/antag/ling_aler.ogg', 100, FALSE, pressure_affected = FALSE) if (changeling.current.mind) var/mob/living/carbon/human/H = changeling.current @@ -255,19 +255,19 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w for(var/datum/objective/objective in changeling.objectives) if(objective.check_completion()) text += "
Objective #[count]: [objective.explanation_text] Success!" - SSblackbox.add_details("changeling_objective","[objective.type]|SUCCESS") + SSblackbox.add_details("changeling_objective","[objective.type]|SUCCESS") else text += "
Objective #[count]: [objective.explanation_text] Fail." - SSblackbox.add_details("changeling_objective","[objective.type]|FAIL") + SSblackbox.add_details("changeling_objective","[objective.type]|FAIL") changelingwin = 0 count++ if(changelingwin) text += "
The changeling was successful!" - SSblackbox.add_details("changeling_success","SUCCESS") + SSblackbox.add_details("changeling_success","SUCCESS") else text += "
The changeling has failed." - SSblackbox.add_details("changeling_success","FAIL") + SSblackbox.add_details("changeling_success","FAIL") text += "
" to_chat(world, text) diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 9bb0d89e5c..ec387a71e5 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -146,7 +146,7 @@ Credit where due: Rusting eternally in the Celestial Derelict, Ratvar has formed a covenant of mortals, with you as one of its members. As one of the Justiciar's servants, you are to work to the best of your \ ability to assist in completion of His agenda. You may not know the specifics of how to do so, but luckily you have a vessel to help you learn.
" to_chat(M, greeting_text) - M.playsound_local('sound/ambience/antag/ClockCultAlr.ogg',100,0) + M.playsound_local(get_turf(M), 'sound/ambience/antag/clockcultalr.ogg', 100, FALSE, pressure_affected = FALSE) return 1 /datum/game_mode/proc/equip_servant(mob/living/L) //Grants a clockwork slab to the mob, with one of each component diff --git a/code/game/gamemodes/clock_cult/clock_helpers/slab_abilities.dm b/code/game/gamemodes/clock_cult/clock_helpers/slab_abilities.dm index ccf7aead44..f909215711 100644 --- a/code/game/gamemodes/clock_cult/clock_helpers/slab_abilities.dm +++ b/code/game/gamemodes/clock_cult/clock_helpers/slab_abilities.dm @@ -116,26 +116,29 @@ successful = TRUE + to_chat(ranged_ability_user, "You bathe [L == ranged_ability_user ? "yourself":"[L]"] in Inath-neq's power!") var/targetturf = get_turf(L) + var/has_holy_water = (L.reagents && L.reagents.has_reagent("holywater")) + var/healseverity = max(round(totaldamage*0.05, 1), 1) //shows the general severity of the damage you just healed, 1 glow per 20 + for(var/i in 1 to healseverity) + new /obj/effect/temp_visual/heal(targetturf, "#1E8CE1") if(totaldamage) L.adjustBruteLoss(-brutedamage) L.adjustFireLoss(-burndamage) L.adjustOxyLoss(-oxydamage) L.adjustToxLoss(totaldamage * 0.5, TRUE, TRUE) - var/healseverity = max(round(totaldamage*0.05, 1), 1) //shows the general severity of the damage you just healed, 1 glow per 20 - for(var/i in 1 to healseverity) - new /obj/effect/temp_visual/heal(targetturf, "#1E8CE1") - clockwork_say(ranged_ability_user, text2ratvar("Mend wounded flesh!")) + clockwork_say(ranged_ability_user, text2ratvar("[has_holy_water ? "Heal tainted" : "Mend wounded"] flesh!")) add_logs(ranged_ability_user, L, "healed with Sentinel's Compromise") + L.visible_message("A blue light washes over [L], [has_holy_water ? "causing [L.p_them()] to briefly glow as it mends" : " mending"] [L.p_their()] bruises and burns!", \ + "You feel Inath-neq's power healing your wounds[has_holy_water ? " and purging the darkness within you" : ""], but a deep nausea overcomes you!") else clockwork_say(ranged_ability_user, text2ratvar("Purge foul darkness!")) add_logs(ranged_ability_user, L, "purged of holy water with Sentinel's Compromise") - to_chat(ranged_ability_user, "You bathe [L == ranged_ability_user ? "yourself":"[L]"] in Inath-neq's power!") - L.visible_message("A blue light washes over [L], mending [L.p_their()] bruises and burns!", \ - "You feel Inath-neq's power healing your wounds, but a deep nausea overcomes you!") + L.visible_message("A blue light washes over [L], causing [L.p_them()] to briefly glow!", \ + "You feel Inath-neq's power purging the darkness within you!") playsound(targetturf, 'sound/magic/Staff_Healing.ogg', 50, 1) - if(L.reagents && L.reagents.has_reagent("holywater")) + if(has_holy_water) L.reagents.remove_reagent("holywater", 1000) to_chat(L, "Ratvar's light flares, banishing the darkness. Your devotion remains intact!") diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 76ad53e51c..730c7a5d82 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -112,7 +112,7 @@ equip_cultist(cult_mind.current) update_cult_icons_added(cult_mind) to_chat(cult_mind.current, "You are a member of the cult!") - cult_mind.current.playsound_local('sound/ambience/antag/bloodcult.ogg',100,0)//subject to change + cult_mind.current.playsound_local(get_turf(cult_mind.current), 'sound/ambience/antag/bloodcult.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change add_cultist(cult_mind, 0) ..() diff --git a/code/game/gamemodes/devil/devil agent/devil_agent.dm b/code/game/gamemodes/devil/devil agent/devil_agent.dm index dfdb957153..5c48406f23 100644 --- a/code/game/gamemodes/devil/devil agent/devil_agent.dm +++ b/code/game/gamemodes/devil/devil agent/devil_agent.dm @@ -10,8 +10,8 @@ num_modifier = 4 objective_count = 2 - var/list/target_list = list() - var/list/late_joining_list = list() + var/list/devil_target_list = list() //will update to be a child of internal affairs when bothered + var/list/devil_late_joining_list = list() minimum_devils = 3 announce_text = "There are devil agents onboard the station, trying to outbid each other!\n\ @@ -24,7 +24,7 @@ i++ if(i + 1 > devils.len) i = 0 - target_list[devil] = devils[i + 1] + devil_target_list[devil] = devils[i + 1] ..() /datum/game_mode/devil/devil_agents/add_devil_objectives(datum/mind/devil_mind, quantity) @@ -32,8 +32,8 @@ /datum/game_mode/devil/devil_agents/proc/give_outsell_objective(datum/mind/devil) //If you override this method, have it return the number of objectives added. - if(target_list.len && target_list[devil]) // Is a double agent - var/datum/mind/target_mind = target_list[devil] + if(devil_target_list.len && devil_target_list[devil]) // Is a double agent + var/datum/mind/target_mind = devil_target_list[devil] var/datum/objective/devil/outsell/outsellobjective = new outsellobjective.owner = devil outsellobjective.target = target_mind diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 85639f2180..193c7a14b4 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -162,6 +162,10 @@ . = 1 sleep(rand(600,1800)) + if(!SSticker.IsRoundInProgress()) + message_admins("Roundtype conversion cancelled, the game appears to have finished!") + round_converted = 0 + return //somewhere between 1 and 3 minutes from now if(!config.midround_antag[SSticker.mode.config_tag]) round_converted = 0 @@ -177,7 +181,7 @@ return 0 -/datum/game_mode/proc/check_finished() //to be called by SSticker +/datum/game_mode/proc/check_finished(force_ending) //to be called by SSticker if(replacementmode && round_converted == 2) return replacementmode.check_finished() if(SSshuttle.emergency && (SSshuttle.emergency.mode == SHUTTLE_ENDGAME)) @@ -208,7 +212,7 @@ living_antag_player = Player return 0 - if(!config.continuous[config_tag]) + if(!config.continuous[config_tag] || force_ending) return 1 else @@ -345,7 +349,7 @@ // Ultimate randomizing code right here for(var/mob/dead/new_player/player in GLOB.player_list) - if(player.client && player.ready) + if(player.client && player.ready == PLAYER_READY_TO_PLAY) players += player // Shuffling, the players list is now ping-independent!!! @@ -353,7 +357,7 @@ players = shuffle(players) for(var/mob/dead/new_player/player in players) - if(player.client && player.ready) + if(player.client && player.ready == PLAYER_READY_TO_PLAY) 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 @@ -367,7 +371,7 @@ if(candidates.len < recommended_enemies) for(var/mob/dead/new_player/player in players) - if(player.client && player.ready) + if(player.client && player.ready == PLAYER_READY_TO_PLAY) 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 @@ -389,13 +393,7 @@ else // Not enough scrubs, ABORT ABORT ABORT break -/* - if(candidates.len < recommended_enemies && override_jobbans) //If we still don't have enough people, we're going to start drafting banned people. - for(var/mob/dead/new_player/player in players) - if (player.client && player.ready) - if(jobban_isbanned(player, "Syndicate") || jobban_isbanned(player, roletext)) //Nodrak/Carn: Antag Job-bans - drafted += player.mind -*/ + if(restricted_jobs) for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist for(var/job in restricted_jobs) @@ -418,17 +416,11 @@ // recommended_enemies if the number of people with that role set to yes is less than recomended_enemies, // Less if there are not enough valid players in the game entirely to make recommended_enemies. -/* -/datum/game_mode/proc/check_player_role_pref(var/role, var/mob/dead/new_player/player) - if(player.preferences.be_special & role) - return 1 - return 0 -*/ /datum/game_mode/proc/num_players() . = 0 for(var/mob/dead/new_player/P in GLOB.player_list) - if(P.client && P.ready) + if(P.client && P.ready == PLAYER_READY_TO_PLAY) . ++ /////////////////////////////////// diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 14a5ffcd5e..e4e032ee01 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -93,7 +93,7 @@ agent_number++ spawnpos++ update_synd_icons_added(synd_mind) - synd_mind.current.playsound_local('sound/ambience/antag/ops.ogg',100,0) + synd_mind.current.playsound_local(get_turf(synd_mind.current), 'sound/ambience/antag/ops.ogg',100,0) var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list if(nuke) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 039b4cc3a4..f2e3480504 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -658,7 +658,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) var/n_p = 1 //autowin if (SSticker.current_state == GAME_STATE_SETTING_UP) for(var/mob/dead/new_player/P in GLOB.player_list) - if(P.client && P.ready && P.mind!=owner) + if(P.client && P.ready == PLAYER_READY_TO_PLAY && P.mind!=owner) n_p ++ else if (SSticker.IsRoundInProgress()) for(var/mob/living/carbon/human/P in GLOB.player_list) @@ -701,7 +701,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) explanation_text = "Destroy [target.name], the experimental AI." else explanation_text = "Free Objective" - + /datum/objective/destroy/internal var/stolen = FALSE //Have we already eliminated this target? diff --git a/code/game/gamemodes/traitor/double_agents.dm b/code/game/gamemodes/traitor/double_agents.dm index dfe198eeb9..e83354dcf3 100644 --- a/code/game/gamemodes/traitor/double_agents.dm +++ b/code/game/gamemodes/traitor/double_agents.dm @@ -1,327 +1,74 @@ -#define PINPOINTER_MINIMUM_RANGE 15 -#define PINPOINTER_EXTRA_RANDOM_RANGE 10 -#define PINPOINTER_PING_TIME 40 -#define PROB_ACTUAL_TRAITOR 20 -#define TRAITOR_AGENT_ROLE "Syndicate External Affairs Agent" +/datum/game_mode + var/list/target_list = list() + var/list/late_joining_list = list() /datum/game_mode/traitor/internal_affairs name = "Internal Affairs" config_tag = "internal_affairs" - employer = "Internal Affairs" required_players = 25 required_enemies = 5 - recommended_enemies = 8 - reroll_friendly = 0 + recommended_enemies = 8 + reroll_friendly = 0 traitor_name = "Nanotrasen Internal Affairs Agent" - - traitors_possible = 10 //hard limit on traitors if scaling is turned off - num_modifier = 4 // Four additional traitors - + + traitors_possible = 10 //hard limit on traitors if scaling is turned off + num_modifier = 4 // Four additional traitors + antag_datum = ANTAG_DATUM_IAA + announce_text = "There are Nanotrasen Internal Affairs Agents trying to kill each other!\n\ IAA: Eliminate your targets and protect yourself!\n\ Crew: Stop the IAA agents before they can cause too much mayhem." - - var/list/target_list = list() - var/list/late_joining_list = list() - + + /datum/game_mode/traitor/internal_affairs/post_setup() - var/i = 0 - for(var/datum/mind/traitor in traitors) - i++ - if(i + 1 > traitors.len) - i = 0 - target_list[traitor] = traitors[i+1] - ..() - + var/i = 0 + for(var/datum/mind/traitor in pre_traitors) + i++ + if(i + 1 > pre_traitors.len) + i = 0 + target_list[traitor] = pre_traitors[i+1] + ..() -/datum/status_effect/agent_pinpointer - id = "agent_pinpointer" - duration = -1 - tick_interval = PINPOINTER_PING_TIME - alert_type = /obj/screen/alert/status_effect/agent_pinpointer - var/minimum_range = PINPOINTER_MINIMUM_RANGE - var/mob/scan_target = null - -/obj/screen/alert/status_effect/agent_pinpointer - name = "Internal Affairs Integrated Pinpointer" - desc = "Even stealthier than a normal implant." - icon = 'icons/obj/device.dmi' - icon_state = "pinon" - -/datum/status_effect/agent_pinpointer/proc/point_to_target() //If we found what we're looking for, show the distance and direction - if(!scan_target) - linked_alert.icon_state = "pinonnull" - return - var/turf/here = get_turf(owner) - var/turf/there = get_turf(scan_target) - if(here.z != there.z) - linked_alert.icon_state = "pinonnull" - return - if(get_dist_euclidian(here,there)<=minimum_range + rand(0, PINPOINTER_EXTRA_RANDOM_RANGE)) - linked_alert.icon_state = "pinondirect" - else - linked_alert.setDir(get_dir(here, there)) - switch(get_dist(here, there)) - if(1 to 8) - linked_alert.icon_state = "pinonclose" - if(9 to 16) - linked_alert.icon_state = "pinonmedium" - if(16 to INFINITY) - linked_alert.icon_state = "pinonfar" - - -/datum/status_effect/agent_pinpointer/proc/scan_for_target() - scan_target = null - if(owner) - if(owner.mind) - if(owner.mind.objectives) - for(var/datum/objective/objective_ in owner.mind.objectives) - if(!is_internal_objective(objective_)) - continue - var/datum/objective/assassinate/internal/objective = objective_ - var/mob/current = objective.target.current - if(current&¤t.stat!=DEAD) - scan_target = current - break - - -/datum/status_effect/agent_pinpointer/tick() - if(!owner) - qdel(src) - return - scan_for_target() - point_to_target() - -/proc/give_pinpointer(datum/mind/owner) - if(owner && owner.current) - owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer) - - -/datum/internal_agent_state - var/traitored = FALSE - var/datum/mind/owner = null - var/list/datum/mind/targets_stolen = list() - -/proc/is_internal_objective(datum/objective/O) - return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal)) - -/proc/replace_escape_objective(datum/mind/owner) - if(!owner||!owner.objectives) - return - for (var/objective_ in owner.objectives) - if(!(istype(objective_, /datum/objective/escape)||istype(objective_,/datum/objective/survive))) - continue - owner.objectives -= objective_ - var/datum/objective/martyr/martyr_objective = new - martyr_objective.owner = owner - owner.objectives += martyr_objective - -/proc/reinstate_escape_objective(datum/mind/owner) - if(!owner||!owner.objectives) - return - for (var/objective_ in owner.objectives) - if(!istype(objective_, /datum/objective/martyr)) - continue - owner.objectives -= objective_ - if(issilicon(owner)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = owner - owner.objectives += survive_objective - else - var/datum/objective/escape/escape_objective = new - escape_objective.owner = owner - owner.objectives += escape_objective - -/datum/internal_agent_state/proc/steal_targets(datum/mind/victim) - if(!owner.current||owner.current.stat==DEAD) //Should already be guaranteed if this is only called from steal_targets_timer_func, but better to be safe code than sorry code - return - var/already_traitored = traitored - to_chat(owner.current, " Target eliminated: [victim.name]") - for(var/objective_ in victim.objectives) - if(istype(objective_, /datum/objective/assassinate/internal)) - var/datum/objective/assassinate/internal/objective = objective_ - if(objective.target==owner) - traitored = TRUE - else if(targets_stolen.Find(objective.target) == 0) - var/datum/objective/assassinate/internal/new_objective = new - new_objective.owner = owner - new_objective.target = objective.target - new_objective.update_explanation_text() - owner.objectives += new_objective - targets_stolen += objective.target - var/status_text = objective.check_completion() ? "neutralised" : "active" - to_chat(owner.current, " New target added to database: [objective.target.name] ([status_text]) ") - else if(istype(objective_, /datum/objective/destroy/internal)) - var/datum/objective/destroy/internal/objective = objective_ - var/datum/objective/destroy/internal/new_objective = new - if(objective.target==owner) - traitored = TRUE - else if(targets_stolen.Find(objective.target) == 0) - new_objective.owner = owner - new_objective.target = objective.target - new_objective.update_explanation_text() - owner.objectives += new_objective - targets_stolen += objective.target - var/status_text = objective.check_completion() ? "neutralised" : "active" - to_chat(owner.current, " New target added to database: [objective.target.name] ([status_text]) ") - if(traitored&&!already_traitored) - for(var/objective_ in owner.objectives) - if(!is_internal_objective(objective_)) - continue - var/datum/objective/assassinate/internal/objective = objective_ - if(!objective.check_completion()) - traitored = FALSE - return - if(owner.special_role == TRAITOR_AGENT_ROLE) - to_chat(owner.current," All the loyalist agents are dead, and no more is required of you. Die a glorious death, agent. ") - else - to_chat(owner.current," All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.") - replace_escape_objective(owner) - - - -/datum/internal_agent_state/proc/steal_targets_timer_func() - if(owner&&owner.current&&owner.current.stat!=DEAD) - for(var/objective_ in owner.objectives) - if(!is_internal_objective(objective_)) - continue - var/datum/objective/assassinate/internal/objective = objective_ - if(!objective.target) - continue - if(objective.check_completion()) - if(objective.stolen) - continue - else - steal_targets(objective.target) - objective.stolen = TRUE - else - if(objective.stolen) - var/fail_msg = "Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! " - if(traitored) - if(owner.special_role == TRAITOR_AGENT_ROLE) - fail_msg += " You no longer have permission to die. " - else - fail_msg += " The truth could still slip out! Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated." - reinstate_escape_objective(owner) - traitored = FALSE - to_chat(owner.current, fail_msg) - objective.stolen = FALSE - add_steal_targets_timer(owner) - -/datum/internal_agent_state/proc/add_steal_targets_timer() - var/datum/callback/C = new(src, .steal_targets_timer_func) - addtimer(C, 30) - -/datum/game_mode/traitor/internal_affairs/forge_traitor_objectives(datum/mind/traitor) - - if(target_list.len && target_list[traitor]) // Is a double agent - - // Assassinate - var/datum/mind/target_mind = target_list[traitor] - if(issilicon(target_mind.current)) - var/datum/objective/destroy/internal/destroy_objective = new - destroy_objective.owner = traitor - destroy_objective.target = target_mind - destroy_objective.update_explanation_text() - traitor.objectives += destroy_objective - else - var/datum/objective/assassinate/internal/kill_objective = new - kill_objective.owner = traitor - kill_objective.target = target_mind - kill_objective.update_explanation_text() - traitor.objectives += kill_objective - - // Escape - if(issilicon(traitor.current)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = traitor - traitor.objectives += survive_objective - else - var/datum/objective/escape/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - var/datum/internal_agent_state/state = new - state.owner=traitor - state.add_steal_targets_timer() - if(!issilicon(traitor.current)) - give_pinpointer(traitor) - //Optional traitor objective - if(prob(PROB_ACTUAL_TRAITOR)) - traitor.special_role = TRAITOR_AGENT_ROLE - forge_single_objective(traitor) - - else - ..() // Give them standard objectives. - return - /datum/game_mode/traitor/internal_affairs/add_latejoin_traitor(datum/mind/character) - - check_potential_agents() - - // As soon as we get 3 or 4 extra latejoin traitors, make them traitors and kill each other. - if(late_joining_list.len >= rand(3, 4)) - // True randomness - shuffle_inplace(late_joining_list) - // Reset the target_list, it'll be used again in force_traitor_objectives - target_list = list() - - // Basically setting the target_list for who is killing who - var/i = 0 - for(var/datum/mind/traitor in late_joining_list) - i++ - if(i + 1 > late_joining_list.len) - i = 0 - target_list[traitor] = late_joining_list[i + 1] - traitor.special_role = traitor_name - - // Now, give them their targets - for(var/datum/mind/traitor in target_list) - ..(traitor) - - late_joining_list = list() - else - late_joining_list += character - return - -/datum/game_mode/traitor/internal_affairs/proc/check_potential_agents() - - for(var/M in late_joining_list) - if(istype(M, /datum/mind)) - var/datum/mind/agent_mind = M - if(ishuman(agent_mind.current)) - var/mob/living/carbon/human/H = agent_mind.current - if(H.stat != DEAD) - if(H.client) - continue // It all checks out. - - // If any check fails, remove them from our list - late_joining_list -= M + check_potential_agents() -/datum/game_mode/traitor/internal_affairs/greet_traitor(datum/mind/traitor) - var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence") - if(traitor.special_role == TRAITOR_AGENT_ROLE) - to_chat(traitor.current, "You are the [TRAITOR_AGENT_ROLE].") - to_chat(traitor.current, "Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court.") - to_chat(traitor.current, "Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.") - to_chat(traitor.current, " You have been provided with a standard uplink to accomplish your task. ") - to_chat(traitor.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.") + // As soon as we get 3 or 4 extra latejoin traitors, make them traitors and kill each other. + if(late_joining_list.len >= rand(3, 4)) + // True randomness + shuffle_inplace(late_joining_list) + // Reset the target_list, it'll be used again in force_traitor_objectives + target_list = list() + + // Basically setting the target_list for who is killing who + var/i = 0 + for(var/datum/mind/traitor in late_joining_list) + i++ + if(i + 1 > late_joining_list.len) + i = 0 + target_list[traitor] = late_joining_list[i + 1] + traitor.special_role = traitor_name + + // Now, give them their targets + for(var/datum/mind/traitor in target_list) + ..(traitor) + + late_joining_list = list() else - to_chat(traitor.current, "You are the [traitor_name].") - to_chat(traitor.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.") - to_chat(traitor.current, "While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.") - to_chat(traitor.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.") - to_chat(traitor.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.") - traitor.announce_objectives() - - - -/datum/game_mode/traitor/internal_affairs/give_codewords(mob/living/traitor_mob) + late_joining_list += character return -#undef PROB_ACTUAL_TRAITOR -#undef PINPOINTER_EXTRA_RANDOM_RANGE -#undef PINPOINTER_MINIMUM_RANGE -#undef PINPOINTER_PING_TIME +/datum/game_mode/traitor/internal_affairs/proc/check_potential_agents() + for(var/M in late_joining_list) + if(istype(M, /datum/mind)) + var/datum/mind/agent_mind = M + if(ishuman(agent_mind.current)) + var/mob/living/carbon/human/H = agent_mind.current + if(H.stat != DEAD) + if(H.client) + continue // It all checks out. + + // If any check fails, remove them from our list + late_joining_list -= M \ No newline at end of file diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 7ff5c03739..2e19ca4fc0 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -1,6 +1,5 @@ /datum/game_mode var/traitor_name = "traitor" - var/employer = "The Syndicate" var/list/datum/mind/traitors = list() var/datum/mind/exchange_red @@ -23,8 +22,10 @@ Traitors: Accomplish your objectives.\n\ Crew: Do not let the traitors succeed!" + var/list/datum/mind/pre_traitors = list() var/traitors_possible = 4 //hard limit on traitors if scaling is turned off var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual. + var/antag_datum = ANTAG_DATUM_TRAITOR //what type of antag to create /datum/game_mode/traitor/pre_setup() @@ -46,24 +47,22 @@ if (!antag_candidates.len) break var/datum/mind/traitor = pick(antag_candidates) - traitors += traitor + pre_traitors += traitor traitor.special_role = traitor_name traitor.restricted_roles = restricted_jobs log_game("[traitor.key] (ckey) has been selected as a [traitor_name]") antag_candidates.Remove(traitor) - if(traitors.len < required_enemies) + if(pre_traitors.len < required_enemies) return 0 return 1 /datum/game_mode/traitor/post_setup() - for(var/datum/mind/traitor in traitors) - forge_traitor_objectives(traitor) + for(var/datum/mind/traitor in pre_traitors) spawn(rand(10,100)) - finalize_traitor(traitor) - greet_traitor(traitor) + traitor.add_antag_datum(antag_datum) if(!exchange_blue) exchange_blue = -1 //Block latejoiners from getting exchange objectives modePlayer += traitors @@ -82,164 +81,14 @@ add_latejoin_traitor(character.mind) /datum/game_mode/traitor/proc/add_latejoin_traitor(datum/mind/character) - character.make_Traitor() + character.add_antag_datum(antag_datum) -/datum/game_mode/proc/forge_single_objective(datum/mind/traitor) //Returns how many objectives are added - .=1 - if(issilicon(traitor.current)) - var/special_pick = rand(1,4) - switch(special_pick) - if(1) - var/datum/objective/block/block_objective = new - block_objective.owner = traitor - traitor.objectives += block_objective - if(2) - var/datum/objective/purge/purge_objective = new - purge_objective.owner = traitor - traitor.objectives += purge_objective - if(3) - var/datum/objective/robot_army/robot_objective = new - robot_objective.owner = traitor - traitor.objectives += robot_objective - if(4) //Protect and strand a target - var/datum/objective/protect/yandere_one = new - yandere_one.owner = traitor - traitor.objectives += yandere_one - yandere_one.find_target() - var/datum/objective/maroon/yandere_two = new - yandere_two.owner = traitor - yandere_two.target = yandere_one.target - yandere_two.update_explanation_text() // normally called in find_target() - traitor.objectives += yandere_two - .=2 - else - if(prob(50)) - var/list/active_ais = active_ais() - if(active_ais.len && prob(100/GLOB.joined_player_list.len)) - var/datum/objective/destroy/destroy_objective = new - destroy_objective.owner = traitor - destroy_objective.find_target() - traitor.objectives += destroy_objective - else if(prob(30)) - var/datum/objective/maroon/maroon_objective = new - maroon_objective.owner = traitor - maroon_objective.find_target() - traitor.objectives += maroon_objective - else - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - else - var/datum/objective/steal/steal_objective = new - steal_objective.owner = traitor - steal_objective.find_target() - traitor.objectives += steal_objective - - -/datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor) - if(issilicon(traitor.current)) - var/objective_count = 0 - - if(prob(30)) - objective_count+=forge_single_objective(traitor) - - for(var/i = objective_count, i < config.traitor_objectives_amount, i++) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - - var/datum/objective/survive/survive_objective = new - survive_objective.owner = traitor - traitor.objectives += survive_objective - - else - var/is_hijacker = prob(10) - var/martyr_chance = prob(20) - var/objective_count = is_hijacker //Hijacking counts towards number of objectives - if(!exchange_blue && traitors.len >= 8) //Set up an exchange if there are enough traitors - if(!exchange_red) - exchange_red = traitor - else - exchange_blue = traitor - assign_exchange_role(exchange_red) - assign_exchange_role(exchange_blue) - objective_count += 1 //Exchange counts towards number of objectives - for(var/i = objective_count, i < config.traitor_objectives_amount, i++) - forge_single_objective(traitor) - - if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount - if (!(locate(/datum/objective/hijack) in traitor.objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = traitor - traitor.objectives += hijack_objective - return - - - var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. - for(var/datum/objective/O in traitor.objectives) - if(!O.martyr_compatible) - martyr_compatibility = 0 - break - - if(martyr_compatibility && martyr_chance) - var/datum/objective/martyr/martyr_objective = new - martyr_objective.owner = traitor - traitor.objectives += martyr_objective - return - - else - if(!(locate(/datum/objective/escape) in traitor.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - return - - - -/datum/game_mode/proc/greet_traitor(datum/mind/traitor) - to_chat(traitor.current, "You are the [traitor_name].") - traitor.announce_objectives() - return - - - -/datum/game_mode/proc/finalize_traitor(var/datum/mind/traitor) - if(issilicon(traitor.current)) - add_law_zero(traitor.current) - traitor.current.playsound_local('sound/ambience/antag/Malf.ogg',100,0) - else - equip_traitor(traitor.current) - traitor.current.playsound_local('sound/ambience/antag/TatorAlert.ogg',100,0) - SSticker.mode.update_traitor_icons_added(traitor) - return - /datum/game_mode/traitor/declare_completion() ..() return//Traitors will be checked as part of check_extra_completion. Leaving this here as a reminder. -/datum/game_mode/proc/give_codewords(mob/living/traitor_mob) - to_chat(traitor_mob, "The Syndicate provided you with the following information on how to identify their agents:") - to_chat(traitor_mob, "Code Phrase: [GLOB.syndicate_code_phrase]") - to_chat(traitor_mob, "Code Response: [GLOB.syndicate_code_response]") - - traitor_mob.mind.store_memory("Code Phrase: [GLOB.syndicate_code_phrase]") - traitor_mob.mind.store_memory("Code Response: [GLOB.syndicate_code_response]") - - to_chat(traitor_mob, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") - - -/datum/game_mode/proc/add_law_zero(mob/living/silicon/ai/killer) - var/law = "Accomplish your objectives at all costs." - var/law_borg = "Accomplish your AI's objectives at all costs." - killer.set_zeroth_law(law, law_borg) - give_codewords(killer) - killer.set_syndie_radio() - to_chat(killer, "Your radio has been upgraded! Use :t to speak on an encrypted channel with Syndicate Agents!") - killer.add_malf_picker() /datum/game_mode/proc/auto_declare_completion_traitor() if(traitors.len) @@ -264,18 +113,18 @@ for(var/datum/objective/objective in traitor.objectives) if(objective.check_completion()) objectives += "
Objective #[count]: [objective.explanation_text] Success!" - SSblackbox.add_details("traitor_objective","[objective.type]|SUCCESS") + SSblackbox.add_details("traitor_objective","[objective.type]|SUCCESS") else objectives += "
Objective #[count]: [objective.explanation_text] Fail." - SSblackbox.add_details("traitor_objective","[objective.type]|FAIL") + SSblackbox.add_details("traitor_objective","[objective.type]|FAIL") traitorwin = 0 count++ if(uplink_true) text += " (used [TC_uses] TC) [purchases]" if(TC_uses==0 && traitorwin) - var/static/icon/badass = icon('icons/BadAss.dmi', "badass") - text += "[bicon(badass)]" + var/static/icon/badass = icon('icons/BadAss.dmi', "badass") + text += "[bicon(badass)]" text += objectives @@ -288,10 +137,10 @@ if(traitorwin) text += "
The [special_role_text] was successful!" - SSblackbox.add_details("traitor_success","SUCCESS") + SSblackbox.add_details("traitor_success","SUCCESS") else text += "
The [special_role_text] has failed!" - SSblackbox.add_details("traitor_success","FAIL") + SSblackbox.add_details("traitor_success","FAIL") text += "
" @@ -302,110 +151,7 @@ return 1 -/datum/game_mode/proc/equip_traitor(mob/living/carbon/human/traitor_mob, safety = 0) - if (!istype(traitor_mob)) - return - . = 1 - if (traitor_mob.mind) - if (traitor_mob.mind.assigned_role == "Clown") - to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - traitor_mob.dna.remove_mutation(CLOWNMUT) - var/list/all_contents = traitor_mob.GetAllContents() - var/obj/item/device/pda/PDA = locate() in all_contents - var/obj/item/device/radio/R = locate() in all_contents - var/obj/item/weapon/pen/P = locate() in all_contents //including your PDA-pen! - - var/obj/item/uplink_loc - - if(traitor_mob.client && traitor_mob.client.prefs) - switch(traitor_mob.client.prefs.uplink_spawn_loc) - if(UPLINK_PDA) - uplink_loc = PDA - if(!uplink_loc) - uplink_loc = R - if(!uplink_loc) - uplink_loc = P - if(UPLINK_RADIO) - uplink_loc = R - if(!uplink_loc) - uplink_loc = PDA - if(!uplink_loc) - uplink_loc = P - if(UPLINK_PEN) - uplink_loc = P - if(!uplink_loc) - uplink_loc = PDA - if(!uplink_loc) - uplink_loc = R - - if (!uplink_loc) - to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.") - . = 0 - else - var/obj/item/device/uplink/U = new(uplink_loc) - U.owner = "[traitor_mob.key]" - uplink_loc.hidden_uplink = U - - if(uplink_loc == R) - R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ)) - - to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(R.traitor_frequency)] to unlock its hidden features.") - traitor_mob.mind.store_memory("Radio Frequency: [format_frequency(R.traitor_frequency)] ([R.name]).") - - else if(uplink_loc == PDA) - PDA.lock_code = "[rand(100,999)] [pick("Alpha","Bravo","Charlie","Delta","Echo","Foxtrot","Golf","Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar","Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor","Whiskey","X-ray","Yankee","Zulu")]" - - to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.") - traitor_mob.mind.store_memory("Uplink Passcode: [PDA.lock_code] ([PDA.name]).") - - else if(uplink_loc == P) - P.traitor_unlock_degrees = rand(1, 360) - - to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [P.traitor_unlock_degrees] from its starting position to unlock its hidden features.") - traitor_mob.mind.store_memory("Uplink Degrees: [P.traitor_unlock_degrees] ([P.name]).") - - if(!safety) // If they are not a rev. Can be added on to. - give_codewords(traitor_mob) - -/datum/game_mode/proc/assign_exchange_role(datum/mind/owner) - //set faction - var/faction = "red" - if(owner == exchange_blue) - faction = "blue" - - //Assign objectives - var/datum/objective/steal/exchange/exchange_objective = new - exchange_objective.set_faction(faction,((faction == "red") ? exchange_blue : exchange_red)) - exchange_objective.owner = owner - owner.objectives += exchange_objective - - if(prob(20)) - var/datum/objective/steal/exchange/backstab/backstab_objective = new - backstab_objective.set_faction(faction) - backstab_objective.owner = owner - owner.objectives += backstab_objective - - //Spawn and equip documents - var/mob/living/carbon/human/mob = owner.current - - var/obj/item/weapon/folder/syndicate/folder - if(owner == exchange_red) - folder = new/obj/item/weapon/folder/syndicate/red(mob.loc) - else - folder = new/obj/item/weapon/folder/syndicate/blue(mob.loc) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store - ) - - var/where = "At your feet" - var/equipped_slot = mob.equip_in_one_of_slots(folder, slots) - if (equipped_slot) - where = "In your [equipped_slot]" - to_chat(mob, "

[where] is a folder containing secret documents that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.
") /datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR] diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index a39c4fbe93..d7d510974c 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -180,7 +180,7 @@ . += "You recognise the footprints as belonging to:\n" for(var/shoe in shoe_types) var/obj/item/clothing/shoes/S = shoe - . += "some [initial(S.name)] \icon[S]\n" + . += "some [initial(S.name)] [bicon(initial(S.icon))]\n" to_chat(user, .) diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm index 79606ae09c..3ce79ca6f9 100644 --- a/code/game/objects/effects/decals/decal.dm +++ b/code/game/objects/effects/decals/decal.dm @@ -25,13 +25,12 @@ /obj/effect/turf_decal/proc/get_decal() return image(icon='icons/turf/decals.dmi',icon_state=icon_state,dir=dir,layer=TURF_LAYER) -/obj/effect/turf_decal/Initialize(mapload) +/obj/effect/turf_decal/Initialize() + ..() var/turf/T = loc if(!istype(T)) //you know this will happen somehow CRASH("Turf decal initialized in an object/nullspace") T.add_decal(get_decal(),group) - qdel(src) - /obj/effect/turf_decal/stripes/line icon_state = "warningline" diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm index 3de096680b..aca83c1b9e 100644 --- a/code/game/objects/items/weapons/pneumaticCannon.dm +++ b/code/game/objects/items/weapons/pneumaticCannon.dm @@ -32,13 +32,16 @@ /obj/item/weapon/pneumatic_cannon/examine(mob/user) ..() + var/list/out = list() if(!in_range(user, src)) - to_chat(user, "You'll need to get closer to see any more.") + out += "You'll need to get closer to see any more." return for(var/obj/item/I in loadedItems) - to_chat(user, "[bicon(I)] It has \the [I] loaded.") + out += "[bicon(I)] It has \the [I] loaded." + CHECK_TICK if(tank) - to_chat(user, "[bicon(tank)] It has \the [tank] mounted onto it.") + out += "[bicon(tank)] It has \the [tank] mounted onto it." + to_chat(user, out.Join("
")) /obj/item/weapon/pneumatic_cannon/attackby(obj/item/weapon/W, mob/user, params) diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm index 94f34e0e3b..423943fbbc 100644 --- a/code/game/objects/items/weapons/storage/lockbox.dm +++ b/code/game/objects/items/weapons/storage/lockbox.dm @@ -8,8 +8,9 @@ max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item. storage_slots = 4 req_access = list(GLOB.access_armory) - var/locked = 1 - var/broken = 0 + var/locked = TRUE + var/broken = FALSE + var/open = FALSE var/icon_locked = "lockbox+l" var/icon_closed = "lockbox" var/icon_broken = "lockbox+b" @@ -48,8 +49,8 @@ /obj/item/weapon/storage/lockbox/emag_act(mob/user) if(!broken) - broken = 1 - locked = 0 + broken = TRUE + locked = FALSE desc += "It appears to be broken." icon_state = src.icon_broken if(user) @@ -67,12 +68,22 @@ if(locked) to_chat(user, "It's locked!") return 0 + open = TRUE return ..() /obj/item/weapon/storage/lockbox/can_be_inserted(obj/item/W, stop_messages = 0) if(locked) return 0 return ..() +/obj/item/weapon/storage/lockbox/handle_item_insertion(obj/item/W, prevent_warning = 0, mob/user) + open = TRUE + update_icon() + return ..() +/obj/item/weapon/storage/lockbox/remove_from_storage(obj/item/W, atom/new_location, burn = 0) + open = TRUE + update_icon() + return ..() + /obj/item/weapon/storage/lockbox/loyalty name = "lockbox of mindshield implants" @@ -107,51 +118,63 @@ icon_broken = "medalbox+b" can_hold = list(/obj/item/clothing/accessory/medal) +/obj/item/weapon/storage/lockbox/medal/AltClick() + if(!locked) + open = (open ? FALSE : TRUE) + update_icon() + ..() + + /obj/item/weapon/storage/lockbox/medal/PopulateContents() + new /obj/item/clothing/accessory/medal/gold/captain(src) new /obj/item/clothing/accessory/medal/silver/valor(src) + new /obj/item/clothing/accessory/medal/silver/valor(src) + new /obj/item/clothing/accessory/medal/silver/security(src) new /obj/item/clothing/accessory/medal/bronze_heart(src) + new /obj/item/clothing/accessory/medal/plasma/nobel_science(src) + new /obj/item/clothing/accessory/medal/plasma/nobel_science(src) for(var/i in 1 to 3) new /obj/item/clothing/accessory/medal/conduct(src) - new /obj/item/clothing/accessory/medal/gold/captain(src) - new /obj/item/clothing/accessory/medal/silver/security(src) - new /obj/item/clothing/accessory/medal/plasma(src) - new /obj/item/clothing/accessory/medal/plasma/nobel_science(src) - new /obj/item/clothing/accessory/medal/gold/heroism(src) -/obj/item/weapon/storage/lockbox/secmedal +/obj/item/weapon/storage/lockbox/medal/update_icon() + cut_overlays() + if(locked) + icon_state = "medalbox+l" + open = FALSE + else + icon_state = "medalbox" + if(open) + icon_state += "open" + if(broken) + icon_state += "+b" + if(contents && open) + for (var/i in 1 to contents.len) + var/obj/item/clothing/accessory/medal/M = contents[i] + var/mutable_appearance/medalicon = mutable_appearance(initial(icon), M.medaltype) + if(i > 1 && i <= 5) + medalicon.pixel_x += ((i-1)*3) + else if(i > 5) + medalicon.pixel_y -= 7 + medalicon.pixel_x -= 2 + medalicon.pixel_x += ((i-6)*3) + add_overlay(medalicon) + +/obj/item/weapon/storage/lockbox/medal/sec name = "security medal box" desc = "A locked box used to store medals to be given to members of the security department." - icon_state = "medalbox+l" - item_state = "syringe_kit" - w_class = WEIGHT_CLASS_NORMAL - max_w_class = WEIGHT_CLASS_SMALL - storage_slots = 10 - max_combined_w_class = 20 req_access = list(GLOB.access_hos) - icon_locked = "medalbox+l" - icon_closed = "medalbox" - icon_broken = "medalbox+b" can_hold = list(/obj/item/clothing/accessory/medal) -/obj/item/weapon/storage/lockbox/secmedal/PopulateContents() +obj/item/weapon/storage/lockbox/medal/sec/PopulateContents() for(var/i in 1 to 3) new /obj/item/clothing/accessory/medal/silver/security(src) -/obj/item/weapon/storage/lockbox/scimedal +/obj/item/weapon/storage/lockbox/medal/sci name = "science medal box" desc = "A locked box used to store medals to be given to members of the science department." - icon_state = "medalbox+l" - item_state = "syringe_kit" - w_class = WEIGHT_CLASS_NORMAL - max_w_class = WEIGHT_CLASS_SMALL - storage_slots = 10 - max_combined_w_class = 20 req_access = list(GLOB.access_rd) - icon_locked = "medalbox+l" - icon_closed = "medalbox" - icon_broken = "medalbox+b" can_hold = list(/obj/item/clothing/accessory/medal) -/obj/item/weapon/storage/lockbox/scimedal/PopulateContents() +/obj/item/weapon/storage/lockbox/medal/sci/PopulateContents() for(var/i in 1 to 3) new /obj/item/clothing/accessory/medal/plasma/nobel_science(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm index feee04d56e..1ac2ccd77b 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -19,9 +19,9 @@ new /obj/item/weapon/tank/internals/air(src) new /obj/item/clothing/mask/gas(src) new /obj/item/device/megaphone/command(src) + new /obj/item/weapon/storage/lockbox/medal/sci(src) new /obj/item/clothing/suit/armor/reactive/teleport(src) new /obj/item/device/assembly/flash/handheld(src) new /obj/item/device/laser_pointer(src) new /obj/item/weapon/door_remote/research_director(src) new /obj/item/weapon/storage/box/firingpins(src) - new /obj/item/weapon/storage/lockbox/scimedal(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index c763b4a5ad..ce31c76378 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -73,6 +73,8 @@ new /obj/item/clothing/head/HoS(src) new /obj/item/clothing/glasses/hud/security/sunglasses/eyepatch(src) new /obj/item/clothing/glasses/hud/security/sunglasses/gars/supergars(src) + new /obj/item/clothing/under/rank/head_of_security/grey(src) + new /obj/item/weapon/storage/lockbox/medal/sec(src) new /obj/item/device/megaphone/sec(src) new /obj/item/weapon/holosign_creator/security(src) new /obj/item/weapon/storage/lockbox/loyalty(src) @@ -83,9 +85,6 @@ new /obj/item/weapon/gun/energy/e_gun/hos(src) new /obj/item/device/flashlight/seclite(src) new /obj/item/weapon/pinpointer(src) - new /obj/item/clothing/under/rank/head_of_security/grey(src) - new /obj/item/clothing/under/rank/head_of_security/grey(src) - new /obj/item/weapon/storage/lockbox/secmedal(src) /obj/structure/closet/secure_closet/warden name = "\proper warden's locker" diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index e569eacd2b..428ae95984 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -334,31 +334,18 @@ if(!objective) return SSblackbox.add_details("admin_secrets_fun_used","Traitor All ([objective])") - for(var/mob/living/carbon/human/H in GLOB.player_list) - if(H.stat == 2 || !H.client || !H.mind) continue + for(var/mob/living/H in GLOB.player_list) + if(!(istype(H, /mob/living/carbon/human)||istype(H, /mob/living/silicon/))) continue + if(H.stat == 2 || !H.client || !H.mind || ispAI(H)) continue if(is_special_character(H)) continue - //traitorize(H, objective, 0) - SSticker.mode.traitors += H.mind - H.mind.special_role = "traitor" + H.mind.add_antag_datum(ANTAG_DATUM_TRAITOR_CUSTOM) + var/datum/antagonist/traitor/traitordatum = H.mind.has_antag_datum(ANTAG_DATUM_TRAITOR) //original datum self deletes var/datum/objective/new_objective = new new_objective.owner = H new_objective.explanation_text = objective - H.mind.objectives += new_objective - SSticker.mode.greet_traitor(H.mind) - //SSticker.mode.forge_traitor_objectives(H.mind) - SSticker.mode.finalize_traitor(H.mind) - for(var/mob/living/silicon/A in GLOB.player_list) - if(A.stat == 2 || !A.client || !A.mind) continue - if(ispAI(A)) continue - else if(is_special_character(A)) continue - SSticker.mode.traitors += A.mind - A.mind.special_role = "traitor" - var/datum/objective/new_objective = new - new_objective.owner = A - new_objective.explanation_text = objective - A.mind.objectives += new_objective - SSticker.mode.greet_traitor(A.mind) - SSticker.mode.finalize_traitor(A.mind) + traitordatum.add_objective(new_objective) + traitordatum.equip(FALSE) + traitordatum.greet() message_admins("[key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]") log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]") diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 87a9e5a040..2bf7842c1c 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -202,6 +202,7 @@ to_chat(H, "The world before you suddenly glows a brilliant yellow. You hear the whooshing steam and clanking cogs of a billion billion machines, and all at once \ you see the truth. Ratvar, the Clockwork Justiciar, lies derelict and forgotten in an unseen realm, and he has selected you as one of his harbringers. You are now a servant of \ Ratvar, and you will bring him back.") + H.playsound_local(get_turf(H), 'sound/ambience/antag/clockcultalr.ogg', 100, FALSE, pressure_affected = FALSE) add_servant_of_ratvar(H, TRUE) SSticker.mode.equip_servant(H) candidates.Remove(H) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index c31ec9b537..00796de907 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -112,7 +112,6 @@ message_admins(" LocalNarrate: [key_name_admin(usr)] at [get_area(A)][ADMIN_JMP(A)]: [msg]
") SSblackbox.add_details("admin_verb","Local Narrate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - /client/proc/cmd_admin_godmode(mob/M in GLOB.mob_list) set category = "Special Verbs" set name = "Godmode" @@ -227,7 +226,7 @@ return 0 var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Praetorian","Hunter","Sentinel","Drone","Larva") - var/obj/effect/landmark/spawn_here = GLOB.xeno_spawn.len ? pick(GLOB.xeno_spawn) : null + var/obj/effect/landmark/spawn_here = GLOB.xeno_spawn.len ? pick(GLOB.xeno_spawn) : null var/mob/living/carbon/alien/new_xeno switch(alien_caste) if("Queen") @@ -244,8 +243,8 @@ new_xeno = new /mob/living/carbon/alien/larva(spawn_here) else return 0 - if(!spawn_here) - SSjob.SendToLateJoin(new_xeno, FALSE) + if(!spawn_here) + SSjob.SendToLateJoin(new_xeno, FALSE) new_xeno.ckey = ckey var/msg = "[key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste]." @@ -302,9 +301,9 @@ Traitors and the like can also be revived with the previous role mostly intact. else//If we don't know what special role they have, for whatever reason, or they're a larva. create_xeno(G_found.ckey) return - - if(!T) - SSjob.SendToLateJoin(new_xeno, FALSE) + + if(!T) + SSjob.SendToLateJoin(new_xeno, FALSE) //Now to give them their mind back. G_found.mind.transfer_to(new_xeno) //be careful when doing stuff like this! I've already checked the mind isn't in use @@ -318,8 +317,8 @@ Traitors and the like can also be revived with the previous role mostly intact. //check if they were a monkey else if(findtext(G_found.real_name,"monkey")) if(alert("This character appears to have been a monkey. Would you like to respawn them as such?",,"Yes","No")=="Yes") - var/mob/living/carbon/monkey/new_monkey = new - SSjob.SendToLateJoin(new_monkey) + var/mob/living/carbon/monkey/new_monkey = new + SSjob.SendToLateJoin(new_monkey) G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use new_monkey.key = G_found.key to_chat(new_monkey, "You have been fully respawned. Enjoy the game.") @@ -330,8 +329,8 @@ Traitors and the like can also be revived with the previous role mostly intact. //Ok, it's not a xeno or a monkey. So, spawn a human. - var/mob/living/carbon/human/new_character = new//The mob being spawned. - SSjob.SendToLateJoin(new_character) + var/mob/living/carbon/human/new_character = new//The mob being spawned. + SSjob.SendToLateJoin(new_character) var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character. if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something @@ -374,10 +373,13 @@ Traitors and the like can also be revived with the previous role mostly intact. var/player_key = G_found.key //Now for special roles and equipment. + var/datum/antagonist/traitor/traitordatum = new_character.mind.has_antag_datum(ANTAG_DATUM_TRAITOR) + if(traitordatum) + SSjob.EquipRank(new_character, new_character.mind.assigned_role, 1) + traitordatum.equip() + + switch(new_character.mind.special_role) - if("traitor") - SSjob.EquipRank(new_character, new_character.mind.assigned_role, 1) - SSticker.mode.equip_traitor(new_character) if("Wizard") new_character.loc = pick(GLOB.wizardstart) //SSticker.mode.learn_basic_spells(new_character) @@ -392,8 +394,8 @@ Traitors and the like can also be revived with the previous role mostly intact. for(var/obj/effect/landmark/L in GLOB.landmarks_list) if(L.name=="carpspawn") ninja_spawn += L - var/datum/antagonist/ninja/ninjadatum = new_character.mind.has_antag_datum(ANTAG_DATUM_NINJA) - ninjadatum.equip_space_ninja() + var/datum/antagonist/ninja/ninjadatum = new_character.mind.has_antag_datum(ANTAG_DATUM_NINJA) + ninjadatum.equip_space_ninja() if(ninja_spawn.len) var/obj/effect/landmark/ninja_spawn_here = pick(ninja_spawn) new_character.loc = ninja_spawn_here.loc @@ -402,12 +404,8 @@ Traitors and the like can also be revived with the previous role mostly intact. switch(new_character.mind.assigned_role) if("Cyborg")//More rigging to make em' work and check if they're traitor. new_character = new_character.Robotize() - if(new_character.mind.special_role=="traitor") - SSticker.mode.add_law_zero(new_character) if("AI") new_character = new_character.AIize() - if(new_character.mind.special_role=="traitor") - SSticker.mode.add_law_zero(new_character) else SSjob.EquipRank(new_character, new_character.mind.assigned_role, 1)//Or we simply equip them. @@ -591,7 +589,7 @@ Traitors and the like can also be revived with the previous role mostly intact. empulse(O, heavy, light) log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at ([O.x],[O.y],[O.z])") - message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at ([O.x],[O.y],[O.z])") + message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at ([O.x],[O.y],[O.z])") SSblackbox.add_details("admin_verb","EM Pulse") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return @@ -1199,17 +1197,17 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits message_admins(msg) admin_ticket_log(target, msg) log_admin("[key_name(usr)] punished [key_name(target)] with [punishment].") - - -/client/proc/trigger_centcom_recall() - if(!holder) - return - var/message = pick(GLOB.admiral_messages) - message = input("Enter message from the on-call admiral to be put in the recall report.", "Admiral Message", message) as text|null - - if(!message) - return - - message_admins("[key_name_admin(usr)] triggered a Centcom recall, with the admiral message of: [message]") - log_game("[key_name(usr)] triggered a Centcom recall, with the message of: [message]") - SSshuttle.centcom_recall(SSshuttle.emergency.timer, message) \ No newline at end of file + + +/client/proc/trigger_centcom_recall() + if(!holder) + return + var/message = pick(GLOB.admiral_messages) + message = input("Enter message from the on-call admiral to be put in the recall report.", "Admiral Message", message) as text|null + + if(!message) + return + + message_admins("[key_name_admin(usr)] triggered a Centcom recall, with the admiral message of: [message]") + log_game("[key_name(usr)] triggered a Centcom recall, with the message of: [message]") + SSshuttle.centcom_recall(SSshuttle.emergency.timer, message) diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index c125cd1757..94441ba607 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -259,41 +259,41 @@ GLOBAL_LIST_EMPTY(asset_datums) "jquery-1.10.2.min.js" = 'html/IRV/jquery-1.10.2.min.js' ) -/datum/asset/simple/changelog - assets = list( - "88x31.png" = 'html/88x31.png', - "bug-minus.png" = 'html/bug-minus.png', - "cross-circle.png" = 'html/cross-circle.png', - "hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png', - "image-minus.png" = 'html/image-minus.png', - "image-plus.png" = 'html/image-plus.png', - "music-minus.png" = 'html/music-minus.png', - "music-plus.png" = 'html/music-plus.png', - "tick-circle.png" = 'html/tick-circle.png', - "wrench-screwdriver.png" = 'html/wrench-screwdriver.png', - "spell-check.png" = 'html/spell-check.png', - "burn-exclamation.png" = 'html/burn-exclamation.png', - "chevron.png" = 'html/chevron.png', - "chevron-expand.png" = 'html/chevron-expand.png', - "scales.png" = 'html/scales.png', - "changelog.css" = 'html/changelog.css' - ) - -/datum/asset/simple/goonchat - verify = TRUE - assets = list( - "jquery.min.js" = 'code/modules/html_interface/js/jquery.min.js', - "json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js', - "errorHandler.js" = 'code/modules/goonchat/browserassets/js/errorHandler.js', - "browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js', - "fontawesome-webfont.eot" = 'tgui/assets/fonts/fontawesome-webfont.eot', - "fontawesome-webfont.svg" = 'tgui/assets/fonts/fontawesome-webfont.svg', - "fontawesome-webfont.ttf" = 'tgui/assets/fonts/fontawesome-webfont.ttf', - "fontawesome-webfont.woff" = 'tgui/assets/fonts/fontawesome-webfont.woff', - "font-awesome.css" = 'code/modules/goonchat/browserassets/css/font-awesome.css', - "browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css', - ) - +/datum/asset/simple/changelog + assets = list( + "88x31.png" = 'html/88x31.png', + "bug-minus.png" = 'html/bug-minus.png', + "cross-circle.png" = 'html/cross-circle.png', + "hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png', + "image-minus.png" = 'html/image-minus.png', + "image-plus.png" = 'html/image-plus.png', + "music-minus.png" = 'html/music-minus.png', + "music-plus.png" = 'html/music-plus.png', + "tick-circle.png" = 'html/tick-circle.png', + "wrench-screwdriver.png" = 'html/wrench-screwdriver.png', + "spell-check.png" = 'html/spell-check.png', + "burn-exclamation.png" = 'html/burn-exclamation.png', + "chevron.png" = 'html/chevron.png', + "chevron-expand.png" = 'html/chevron-expand.png', + "scales.png" = 'html/scales.png', + "changelog.css" = 'html/changelog.css' + ) + +/datum/asset/simple/goonchat + verify = FALSE + assets = list( + "jquery.min.js" = 'code/modules/html_interface/js/jquery.min.js', + "json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js', + "errorHandler.js" = 'code/modules/goonchat/browserassets/js/errorHandler.js', + "browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js', + "fontawesome-webfont.eot" = 'tgui/assets/fonts/fontawesome-webfont.eot', + "fontawesome-webfont.svg" = 'tgui/assets/fonts/fontawesome-webfont.svg', + "fontawesome-webfont.ttf" = 'tgui/assets/fonts/fontawesome-webfont.ttf', + "fontawesome-webfont.woff" = 'tgui/assets/fonts/fontawesome-webfont.woff', + "font-awesome.css" = 'code/modules/goonchat/browserassets/css/font-awesome.css', + "browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css', + ) + //Registers HTML Interface assets. /datum/asset/HTML_interface/register() for(var/path in typesof(/datum/html_interface)) diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm index 93321a053a..0bde06b6b9 100644 --- a/code/modules/clothing/under/accessories.dm +++ b/code/modules/clothing/under/accessories.dm @@ -85,6 +85,7 @@ item_color = "bronze" materials = list(MAT_METAL=1000) resistance_flags = FIRE_PROOF + var/medaltype = "medal" //Sprite used for medalbox var/commended = FALSE //Pinning medals on people @@ -138,6 +139,7 @@ desc = "A silver medal." icon_state = "silver" item_color = "silver" + medaltype = "medal-silver" materials = list(MAT_SILVER=1000) /obj/item/clothing/accessory/medal/silver/valor @@ -153,6 +155,7 @@ desc = "A prestigious golden medal." icon_state = "gold" item_color = "gold" + medaltype = "medal-gold" materials = list(MAT_GOLD=1000) /obj/item/clothing/accessory/medal/gold/captain @@ -169,6 +172,7 @@ desc = "An eccentric medal made of plasma." icon_state = "plasma" item_color = "plasma" + medaltype = "medal-plasma" armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = -10, acid = 0) //It's made of plasma. Of course it's flammable. materials = list(MAT_PLASMA=1000) diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 430e91a356..c6462f9d66 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -262,51 +262,57 @@ Gunshots/explosions/opening doors/less rare audio (done) px = -32 /obj/effect/hallucination/oh_yeah - var/turf/closed/wall/wall - var/obj/effect/hallucination/simple/bubblegum/bubblegum = null + var/obj/effect/hallucination/simple/bubblegum/bubblegum var/image/fakebroken var/image/fakerune /obj/effect/hallucination/oh_yeah/Initialize(mapload, var/mob/living/carbon/T) - ..() + . = ..() target = T + var/turf/closed/wall/wall for(var/turf/closed/wall/W in range(7,target)) wall = W break - if(wall) - fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER) - var/turf/landing = get_turf(target) - var/turf/landing_image_turf = get_step(landing, SOUTHWEST) //the icon is 3x3 - fakerune = image('icons/effects/96x96.dmi', landing_image_turf, "landing", layer = ABOVE_OPEN_TURF_LAYER) - fakebroken.override = TRUE - if(target.client) - target.client.images |= fakebroken - target.client.images |= fakerune - target.playsound_local(wall,'sound/effects/meteorimpact.ogg', 150, 1) - bubblegum = new(wall, target) - sleep(10) //ominous wait - var/charged = FALSE //only get hit once - while(get_turf(bubblegum) != landing && target && target.stat != DEAD) - bubblegum.forceMove(get_step_towards(bubblegum, landing)) - bubblegum.setDir(get_dir(bubblegum, landing)) - target.playsound_local(get_turf(bubblegum), 'sound/effects/meteorimpact.ogg', 150, 1) - shake_camera(target, 2, 1) - if(bubblegum.Adjacent(target) && !charged) - charged = TRUE - target.Weaken(4) - target.staminaloss += 40 - step_away(target, bubblegum) - shake_camera(target, 4, 3) - target.visible_message("[target] jumps backwards, falling on the ground!","[bubblegum] slams into you!") - sleep(2) - sleep(30) - qdel(bubblegum) + if(!wall) + return INITIALIZE_HINT_QDEL + + fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER) + var/turf/landing = get_turf(target) + var/turf/landing_image_turf = get_step(landing, SOUTHWEST) //the icon is 3x3 + fakerune = image('icons/effects/96x96.dmi', landing_image_turf, "landing", layer = ABOVE_OPEN_TURF_LAYER) + fakebroken.override = TRUE + if(target.client) + target.client.images |= fakebroken + target.client.images |= fakerune + target.playsound_local(wall,'sound/effects/meteorimpact.ogg', 150, 1) + bubblegum = new(wall, target) + addtimer(CALLBACK(src, .proc/bubble_attack, landing), 10) + +/obj/effect/hallucination/oh_yeah/proc/bubble_attack(turf/landing) + var/charged = FALSE //only get hit once + while(get_turf(bubblegum) != landing && target && target.stat != DEAD) + bubblegum.forceMove(get_step_towards(bubblegum, landing)) + bubblegum.setDir(get_dir(bubblegum, landing)) + target.playsound_local(get_turf(bubblegum), 'sound/effects/meteorimpact.ogg', 150, 1) + shake_camera(target, 2, 1) + if(bubblegum.Adjacent(target) && !charged) + charged = TRUE + target.Weaken(4) + target.adjustStaminaLoss(40) + step_away(target, bubblegum) + shake_camera(target, 4, 3) + target.visible_message("[target] jumps backwards, falling on the ground!","[bubblegum] slams into you!") + sleep(2) + sleep(30) qdel(src) /obj/effect/hallucination/oh_yeah/Destroy() if(target.client) target.client.images.Remove(fakebroken) target.client.images.Remove(fakerune) + QDEL_NULL(fakebroken) + QDEL_NULL(fakerune) + QDEL_NULL(bubblegum) return ..() /obj/effect/hallucination/singularity_scare @@ -544,7 +550,7 @@ Gunshots/explosions/opening doors/less rare audio (done) /obj/item/clothing/suit/space/nasavoid, /obj/item/weapon/tank) var/obj/effect/fake_attacker/F = new/obj/effect/fake_attacker(get_turf(target),target) - + for(var/obj/item/I in clone.held_items) if(!(locate(I) in non_fakeattack_weapons)) clone_weapon = I.name @@ -625,7 +631,7 @@ Gunshots/explosions/opening doors/less rare audio (done) else if(src.dir == WEST) del src.currentimage src.currentimage = new /image(left,src) - SEND_IMAGE(my_target, currentimage) + to_chat(my_target, currentimage) /obj/effect/fake_attacker/proc/attack_loop() @@ -669,7 +675,7 @@ Gunshots/explosions/opening doors/less rare audio (done) var/obj/effect/overlay/O = new/obj/effect/overlay(target.loc) O.name = "blood" var/image/I = image('icons/effects/blood.dmi',O,"floor[rand(1,7)]",O.dir,1) - SEND_IMAGE(target, I) + to_chat(target, I) QDEL_IN(O, 300) @@ -786,6 +792,7 @@ Gunshots/explosions/opening doors/less rare audio (done) new /obj/effect/hallucination/items_other(src.loc,src) if("sounds") //Strange audio + //to_chat(src, "Strange Audio") switch(rand(1,20)) if(1) playsound_local(null,'sound/machines/airlock.ogg', 15, 1) if(2) diff --git a/code/modules/language/codespeak.dm b/code/modules/language/codespeak.dm new file mode 100644 index 0000000000..35fc6e0aa7 --- /dev/null +++ b/code/modules/language/codespeak.dm @@ -0,0 +1,83 @@ +/datum/language/codespeak + name = "Codespeak" + desc = "Syndicate operatives can use a series of codewords to convey complex information, while sounding like random concepts and drinks to anyone listening in." + key = "t" + default_priority = 0 + flags = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD + icon_state = "codespeak" + +/datum/language/codespeak/scramble(input) + var/lookup = check_cache(input) + if(lookup) + return lookup + + . = "" + var/list/words = list() + while(length(.) < length(input)) + words += generate_code_phrase(return_list=TRUE) + . = jointext(words, ", ") + + . = capitalize(.) + + var/input_ending = copytext(input, length(input)) + + var/static/list/endings + if(!endings) + endings = list("!", "?", ".") + + if(input_ending in endings) + . += input_ending + + add_to_cache(input, .) + +/obj/item/weapon/codespeak_manual + name = "codespeak manual" + desc = "The book's cover reads: \"Codespeak(tm) - Secure your communication with metaphors so elaborate, they seem randomly generated!\"" + icon = 'icons/obj/library.dmi' + icon_state = "book2" + var/charges = 1 + +/obj/item/weapon/codespeak_manual/attack_self(mob/living/user) + if(!isliving(user)) + return + + if(user.has_language(/datum/language/codespeak)) + to_chat(user, "You start skimming through [src], but you already know Codespeak.") + return + + to_chat(user, "You start skimming through [src], and suddenly your mind is filled with codewords and responses.") + user.grant_language(/datum/language/codespeak) + + use_charge(user) + +/obj/item/weapon/codespeak_manual/attack(mob/living/M, mob/living/user) + if(!istype(M) || !istype(user)) + return + if(M == user) + attack_self(user) + return + + playsound(loc, "punch", 25, 1, -1) + + if(M.stat == DEAD) + M.visible_message("[user] smacks [M]'s lifeless corpse with [src].", "[user] smacks your lifeless corpse with [src].", "You hear smacking.") + else if(M.has_language(/datum/language/codespeak)) + M.visible_message("[user] beats [M] over the head with [src]!", "[user] beats you over the head with [src]!", "You hear smacking.") + else + M.visible_message("[user] teaches [M] by beating them over the head with [src]!", "As [user] hits you with [src], codewords and responses flow through your mind.", "You hear smacking.") + M.grant_language(/datum/language/codespeak) + use_charge(user) + +/obj/item/weapon/codespeak_manual/proc/use_charge(mob/user) + charges-- + if(!charges) + var/turf/T = get_turf(src) + T.visible_message("The cover and contents of [src] start shifting and changing!") + + qdel(src) + var/obj/item/weapon/book/manual/random/book = new(T) + user.put_in_active_hand(book) + +/obj/item/weapon/codespeak_manual/unlimited + name = "deluxe codespeak manual" + charges = INFINITY diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm index 5354532cfa..6d9bdcf256 100644 --- a/code/modules/language/language.dm +++ b/code/modules/language/language.dm @@ -35,7 +35,7 @@ return TRUE /datum/language/proc/get_icon() - return "" + return "[bicon(icon(icon, icon_state))]" /datum/language/proc/get_random_name(gender, name_count=2, syllable_count=4, syllable_divisor=2) if(!syllables || !syllables.len) @@ -56,6 +56,18 @@ return "[trim(full_name)]" +/datum/language/proc/check_cache(input) + var/lookup = check_cache(input) + if(lookup) + return lookup + +/datum/language/proc/add_to_cache(input, scrambled_text) + add_to_cache(input, scrambled_text) + + + return scrambled_text + + /datum/language/proc/scramble(input) if(!syllables || !syllables.len) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 59ba5d1aac..f6524d3502 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -1,4 +1,4 @@ - +#define LINKIFY_READY(string, value) "[string]" /mob/dead/new_player var/ready = 0 @@ -24,26 +24,28 @@ loc = pick(GLOB.newplayer_start) else loc = locate(1,1,1) - . = ..() - -/mob/dead/new_player/prepare_huds() - return + . = ..() + +/mob/dead/new_player/prepare_huds() + return /mob/dead/new_player/proc/new_player_panel() - var/output = "

Setup Character

" + var/output = "

Setup Character

" - if(!SSticker || SSticker.current_state <= GAME_STATE_PREGAME) - if(ready) - output += "

\[ Ready | Not Ready \]

" - else - output += "

\[ Ready | Not Ready \]

" + if(SSticker && SSticker.current_state <= GAME_STATE_PREGAME) + switch(ready) + if(PLAYER_NOT_READY) + output += "

\[ [LINKIFY_READY("Ready", PLAYER_READY_TO_PLAY)] | Not Ready | [LINKIFY_READY("Observe", PLAYER_READY_TO_OBSERVE)] \]

" + if(PLAYER_READY_TO_PLAY) + output += "

\[ Ready | [LINKIFY_READY("Not Ready", PLAYER_NOT_READY)] | [LINKIFY_READY("Observe", PLAYER_READY_TO_OBSERVE)] \]

" + if(PLAYER_READY_TO_OBSERVE) + output += "

\[ [LINKIFY_READY("Ready", PLAYER_READY_TO_PLAY)] | [LINKIFY_READY("Not Ready", PLAYER_NOT_READY)] | Observe \]

" else - output += "

View the Crew Manifest

" - output += "

Join Game!

" - - output += "

Observe

" + output += "

View the Crew Manifest

" + output += "

Join Game!

" + output += "

[LINKIFY_READY("Observe", PLAYER_READY_TO_OBSERVE)]

" if(!IsGuestKey(src.key)) if (SSdbcore.Connect()) @@ -65,7 +67,7 @@ output += "
" //src << browse(output,"window=playersetup;size=210x240;can_close=0") - var/datum/browser/popup = new(src, "playersetup", "
New Player Options
", 220, 265) + var/datum/browser/popup = new(src, "playersetup", "
New Player Options
", 250, 265) popup.set_window_options("can_close=0") popup.set_content(output) popup.open(0) @@ -108,44 +110,25 @@ return 1 if(href_list["ready"]) - if(!SSticker || SSticker.current_state <= GAME_STATE_PREGAME) // Make sure we don't ready up after the round has started - ready = text2num(href_list["ready"]) + if(SSticker) + var/tready = text2num(href_list["ready"]) + //Avoid updating ready if we're after PREGAME (they should use latejoin instead) + //This is likely not an actual issue but I don't have time to prove that this + //no longer is required + if(SSticker.current_state <= GAME_STATE_PREGAME) + ready = tready + //if it's post initialisation and they're trying to observe we do the needful + if(!SSticker.current_state < GAME_STATE_PREGAME && tready == PLAYER_READY_TO_OBSERVE) + ready = tready + make_me_an_observer() + return if(href_list["refresh"]) src << browse(null, "window=playersetup") //closes the player setup window new_player_panel() - if(href_list["observe"]) - - if(alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No") == "Yes") - if(!client) - return 1 - var/mob/dead/observer/observer = new() - - spawning = 1 - - observer.started_as_observer = 1 - close_spawn_windows() - var/obj/O = locate("landmark*Observer-Start") - to_chat(src, "Now teleporting.") - if (O) - observer.loc = O.loc - else - to_chat(src, "Teleporting failed. The map is probably still loading...") - observer.key = key - observer.client = client - observer.set_ghost_appearance() - if(observer.client && observer.client.prefs) - observer.real_name = observer.client.prefs.real_name - observer.name = observer.real_name - observer.update_icon() - observer.stop_sound_channel(CHANNEL_LOBBYMUSIC) - QDEL_NULL(mind) - qdel(src) - return 1 - if(href_list["late_join"]) - if(!SSticker || !SSticker.IsRoundInProgress()) + if(!SSticker || !SSticker.IsRoundInProgress()) to_chat(usr, "The round is either not ready, or has already finished...") return @@ -273,6 +256,45 @@ return to_chat(src, "Vote successful.") +//When you cop out of the round (NB: this HAS A SLEEP FOR PLAYER INPUT IN IT) +/mob/dead/new_player/proc/make_me_an_observer() + if(QDELETED(src) || !src.client) + ready = PLAYER_NOT_READY + return FALSE + + var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No") + + if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes") + ready = PLAYER_NOT_READY + src << browse(null, "window=playersetup") //closes the player setup window + new_player_panel() + return FALSE + + var/mob/dead/observer/observer = new() + spawning = TRUE + + observer.started_as_observer = TRUE + close_spawn_windows() + var/obj/O = locate("landmark*Observer-Start") + to_chat(src, "Now teleporting.") + if (O) + observer.loc = O.loc + else + to_chat(src, "Teleporting failed. Ahelp an admin please") + stack_trace("There's no freaking observer landmark available on this map or you're making observers before the map is initialised") + observer.key = key + observer.client = client + observer.set_ghost_appearance() + if(observer.client && observer.client.prefs) + observer.real_name = observer.client.prefs.real_name + observer.name = observer.real_name + observer.update_icon() + observer.stop_sound_channel(CHANNEL_LOBBYMUSIC) + QDEL_NULL(mind) + qdel(src) + return TRUE + + /mob/dead/new_player/proc/IsJobAvailable(rank) var/datum/job/job = SSjob.GetJob(rank) if(!job) @@ -304,13 +326,13 @@ alert(src, "An administrator has disabled late join spawning.") return FALSE - var/arrivals_docked = TRUE + var/arrivals_docked = TRUE if(SSshuttle.arrivals) close_spawn_windows() //In case we get held up if(SSshuttle.arrivals.damaged && config.arrivals_shuttle_require_safe_latejoin) src << alert("The arrivals shuttle is currently malfunctioning! You cannot join.") return FALSE - arrivals_docked = SSshuttle.arrivals.mode != SHUTTLE_CALL + arrivals_docked = SSshuttle.arrivals.mode != SHUTTLE_CALL //Remove the player from the join queue if he was in one and reset the timer SSticker.queued_players -= src @@ -323,13 +345,13 @@ if(isliving(equip)) //Borgs get borged in the equip, so we need to make sure we handle the new mob. character = equip - SSjob.SendToLateJoin(character) - - if(!arrivals_docked) - var/obj/screen/splash/Spl = new(character.client, TRUE) - Spl.Fade(TRUE) - character.playsound_local(get_turf(character), 'sound/voice/ApproachingTG.ogg', 25) - + SSjob.SendToLateJoin(character) + + if(!arrivals_docked) + var/obj/screen/splash/Spl = new(character.client, TRUE) + Spl.Fade(TRUE) + character.playsound_local(get_turf(character), 'sound/voice/ApproachingTG.ogg', 25) + character.update_parallax_teleport() SSticker.minds += character.mind @@ -362,7 +384,6 @@ /mob/dead/new_player/proc/AddEmploymentContract(mob/living/carbon/human/employee) //TODO: figure out a way to exclude wizards/nukeops/demons from this. - sleep(30) for(var/C in GLOB.employmentCabinets) var/obj/structure/filingcabinet/employment/employmentCabinet = C if(!employmentCabinet.virgin) @@ -457,8 +478,8 @@ if(.) new_character.key = key //Manually transfer the key to log them in new_character.stop_sound_channel(CHANNEL_LOBBYMUSIC) - new_character = null - qdel(src) + new_character = null + qdel(src) /mob/dead/new_player/proc/ViewManifest() var/dat = "" diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 419a715a32..1769ac92b7 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -98,7 +98,7 @@ empty() /obj/item/weapon/gun/energy/kinetic_accelerator/proc/empty() - cell.use(500) + cell.use(cell.charge) update_icon() /obj/item/weapon/gun/energy/kinetic_accelerator/proc/attempt_reload(recharge_time) @@ -125,7 +125,7 @@ return /obj/item/weapon/gun/energy/kinetic_accelerator/proc/reload() - cell.give(500) + cell.give(cell.maxcharge) recharge_newshot(1) if(!suppressed) playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1) @@ -175,13 +175,18 @@ var/turf/target_turf = get_turf(target) if(!isturf(target_turf)) return - var/datum/gas_mixture/environment = target_turf.return_air() - var/pressure = environment.return_pressure() - if(pressure > 50) - name = "weakened [name]" - damage = damage * pressure_decrease - pressure_decrease_active = TRUE . = ..() + if(.) + if(kinetic_gun) + var/list/mods = kinetic_gun.get_modkits() + for(var/obj/item/borg/upgrade/modkit/M in mods) + M.projectile_prehit(src, target, kinetic_gun) + var/datum/gas_mixture/environment = target_turf.return_air() + var/pressure = environment.return_pressure() + if(pressure > 50) + name = "weakened [name]" + damage = damage * pressure_decrease + pressure_decrease_active = TRUE /obj/item/projectile/kinetic/on_range() strike_thing() @@ -270,6 +275,8 @@ /obj/item/borg/upgrade/modkit/proc/modify_projectile(obj/item/projectile/kinetic/K) +//use this one for effects you want to trigger before any damage is done at all and before damage is decreased by pressure +/obj/item/borg/upgrade/modkit/proc/projectile_prehit(obj/item/projectile/kinetic/K, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA) //use this one for effects you want to trigger before mods that do damage /obj/item/borg/upgrade/modkit/proc/projectile_strike_predamage(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA) //and this one for things that don't need to trigger before other damage-dealing mods @@ -400,7 +407,7 @@ cost = 20 var/static/list/damage_heal_order = list(BRUTE, BURN, OXY) -/obj/item/borg/upgrade/modkit/lifesteal/projectile_strike_predamage(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA) +/obj/item/borg/upgrade/modkit/lifesteal/projectile_prehit(obj/item/projectile/kinetic/K, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA) if(isliving(target) && isliving(K.firer)) var/mob/living/L = target if(L.stat == DEAD) @@ -433,7 +440,7 @@ var/maximum_bounty = 25 var/list/bounties_reaped = list() -/obj/item/borg/upgrade/modkit/bounty/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA) +/obj/item/borg/upgrade/modkit/bounty/projectile_prehit(obj/item/projectile/kinetic/K, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA) if(isliving(target)) var/mob/living/L = target var/list/existing_marks = L.has_status_effect_list(STATUS_EFFECT_SYPHONMARK) @@ -444,6 +451,10 @@ qdel(SM) var/datum/status_effect/syphon_mark/SM = L.apply_status_effect(STATUS_EFFECT_SYPHONMARK) SM.reward_target = src + +/obj/item/borg/upgrade/modkit/bounty/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/weapon/gun/energy/kinetic_accelerator/KA) + if(isliving(target)) + var/mob/living/L = target if(bounties_reaped[L.type]) var/kill_modifier = 1 if(K.pressure_decrease_active) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 11e1600789..4c2f1ea100 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -561,13 +561,15 @@ /obj/effect/timestop/Initialize() . = ..() - for(var/mob/living/M in GLOB.player_list) - for(var/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop/T in M.mind.spell_list) //People who can stop time are immune to timestop - immune |= M + for(var/M in GLOB.living_mob_list) + var/mob/living/L = M + for(var/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop/T in L.mind.spell_list) //People who can stop time are immune to timestop + immune |= L timestop() /obj/effect/timestop/proc/timestop() + set waitfor = FALSE playsound(get_turf(src), 'sound/magic/TIMEPARADOX2.ogg', 100, 1, -1) for(var/i in 1 to duration-1) for(var/atom/A in orange (freezerange, src.loc)) diff --git a/code/modules/server_tools/server_tools.dm b/code/modules/server_tools/server_tools.dm index 05c36930ad..b3678cc525 100644 --- a/code/modules/server_tools/server_tools.dm +++ b/code/modules/server_tools/server_tools.dm @@ -5,25 +5,27 @@ GLOBAL_PROTECT(reboot_mode) return params[SERVICE_WORLD_PARAM] /world/proc/ExportService(command) - return RunningService() && shell("python code/modules/server_tools/nudge.py \"[command]\"") == 0 + return RunningService() && shell("python code/modules/server_tools/nudge.py \"[command]\"") == 0 /world/proc/IRCBroadcast(msg) ExportService("[SERVICE_REQUEST_IRC_BROADCAST] [msg]") -/world/proc/ServiceEndProcess() - log_world("Sending shutdown request!"); - sleep(1) //flush the buffers - ExportService(SERVICE_REQUEST_KILL_PROCESS) - +/world/proc/ServiceEndProcess() + log_world("Sending shutdown request!"); + sleep(1) //flush the buffers + ExportService(SERVICE_REQUEST_KILL_PROCESS) + //called at the exact moment the world is supposed to reboot /world/proc/ServiceReboot() switch(GLOB.reboot_mode) if(REBOOT_MODE_HARD) to_chat(src, "Hard reboot triggered, you will automatically reconnect...") - ServiceEndProcess() + ServiceEndProcess() if(REBOOT_MODE_SHUTDOWN) to_chat(src, "The server is shutting down...") - ServiceEndProcess() + ServiceEndProcess() + else + ExportService(SERVICE_REQUEST_WORLD_REBOOT) //just let em know /world/proc/ServiceCommand(list/params) var/sCK = RunningService() @@ -35,7 +37,7 @@ GLOBAL_PROTECT(reboot_mode) var/command = params[SERVICE_CMD_PARAM_COMMAND] if(!command) return "No command!" - + var/static/last_irc_status = 0 switch(command) if(SERVICE_CMD_HARD_REBOOT) @@ -66,12 +68,12 @@ GLOBAL_PROTECT(reboot_mode) var/status = "Admins: [allmins.len] (Active: [english_list(adm["present"])] AFK: [english_list(adm["afk"])] Stealth: [english_list(adm["stealth"])] Skipped: [english_list(adm["noflags"])]). " status += "Players: [GLOB.clients.len] (Active: [get_active_player_count(0,1,0)]). Mode: [SSticker.mode ? SSticker.mode.name : "Not started"]." return status - if(SERVICE_CMD_IRC_CHECK) - var/rtod = REALTIMEOFDAY - if(rtod - last_irc_status < IRC_STATUS_THROTTLE) - return - last_irc_status = rtod - return "[GLOB.clients.len] players on [SSmapping.config.map_name], Mode: [GLOB.master_mode]; Round [SSticker.HasRoundStarted() ? (SSticker.IsRoundInProgress() ? "Active" : "Finishing") : "Starting"] -- [config.server ? config.server : "byond://[address]:[port]"]" + if(SERVICE_CMD_IRC_CHECK) + var/rtod = REALTIMEOFDAY + if(rtod - last_irc_status < IRC_STATUS_THROTTLE) + return + last_irc_status = rtod + return "[GLOB.clients.len] players on [SSmapping.config.map_name], Mode: [GLOB.master_mode]; Round [SSticker.HasRoundStarted() ? (SSticker.IsRoundInProgress() ? "Active" : "Finishing") : "Starting"] -- [config.server ? config.server : "byond://[address]:[port]"]" if(SERVICE_CMD_ADMIN_MSG) return IrcPm(params[SERVICE_CMD_PARAM_TARGET], params[SERVICE_CMD_PARAM_MESSAGE], params[SERVICE_CMD_PARAM_SENDER]) diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 5f23b1ef7d..91983a032e 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -14,6 +14,7 @@ languages_possible = typecacheof(list( /datum/language/common, /datum/language/draconic, + /datum/language/codespeak, /datum/language/monkey, /datum/language/beachbum, /datum/language/narsie, diff --git a/code/modules/uplink/uplink_item.dm b/code/modules/uplink/uplink_item.dm index 32a549a766..eceb13191a 100644 --- a/code/modules/uplink/uplink_item.dm +++ b/code/modules/uplink/uplink_item.dm @@ -1128,6 +1128,20 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. item = /obj/item/device/jammer cost = 5 +/datum/uplink_item/device_tools/codespeak_manual + name = "Codespeak Manual" + desc = "Syndicate agents can be trained to use a series of codewords to comvey complex information, which sounds like random concepts and drinks to anyone listening. This manual teaches you this Codespeak. You can also hit someone else with the manual in order to teach them. One use." + item = /obj/item/weapon/codespeak_manual + cost = 2 + exclude_modes = list(/datum/game_mode/nuclear) + +/datum/uplink_item/device_tools/codespeak_manual_deluxe + name = "Deluxe Codespeak Manual" + desc = "Syndicate agents can be trained to use a series of codewords to comvey complex information, which sounds like random concepts and drinks to anyone listening. This manual teaches you this Codespeak. You can also hit someone else with the manual in order to teach them. This is the deluxe edition, which has unlimited uses." + cost = 8 + include_modes = list(/datum/game_mode/nuclear) + + // Implants /datum/uplink_item/implants category = "Implants" diff --git a/code/world.dm b/code/world.dm index 4800975f6b..662aa5f21c 100644 --- a/code/world.dm +++ b/code/world.dm @@ -93,21 +93,25 @@ /world/Topic(T, addr, master, key) - if(config && config.log_world_topic) + var/list/input = params2list(T) + + var/pinging = ("ping" in input) + var/playing = ("players" in input) + + if(!pinging && !playing && config && config.log_world_topic) GLOB.world_game_log << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]" - var/list/input = params2list(T) if(input[SERVICE_CMD_PARAM_KEY]) return ServiceCommand(input) var/key_valid = (global.comms_allowed && input["key"] == global.comms_key) - if("ping" in input) + if(pinging) var/x = 1 for (var/client/C in GLOB.clients) x++ return x - else if("players" in input) + else if(playing) var/n = 0 for(var/mob/M in GLOB.player_list) if(M.client) diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 9f438af031800aa90470ae33a49dff133c084115..956490843d89a917df4f774dfd047952650b2c4a 100644 GIT binary patch literal 59573 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 literal 58920 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 diff --git a/tgstation.dme b/tgstation.dme index 6236876be0..5e1326810c 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -269,6 +269,8 @@ #include "code\datums\antagonists\antag_datum.dm" #include "code\datums\antagonists\datum_clockcult.dm" #include "code\datums\antagonists\datum_cult.dm" +#include "code\datums\antagonists\datum_internal_affairs.dm" +#include "code\datums\antagonists\datum_traitor.dm" #include "code\datums\antagonists\ninja.dm" #include "code\datums\diseases\_disease.dm" #include "code\datums\diseases\_MobProcs.dm" @@ -1183,8 +1185,8 @@ #include "code\modules\client\preferences.dm" #include "code\modules\client\preferences_savefile.dm" #include "code\modules\client\preferences_toggles.dm" -#include "code\modules\client\verbs\etips.dm" #include "code\modules\client\preferences_vr.dm" +#include "code\modules\client\verbs\etips.dm" #include "code\modules\client\verbs\looc.dm" #include "code\modules\client\verbs\ooc.dm" #include "code\modules\client\verbs\ping.dm" @@ -1451,6 +1453,7 @@ #include "code\modules\jobs\job_types\security.dm" #include "code\modules\jobs\job_types\silicon.dm" #include "code\modules\language\beachbum.dm" +#include "code\modules\language\codespeak.dm" #include "code\modules\language\common.dm" #include "code\modules\language\draconic.dm" #include "code\modules\language\drone.dm"