From fb751312ace43d5fa40716e92aa33dac4efc2b7c Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sat, 25 Nov 2017 17:34:45 -0500 Subject: [PATCH 01/96] Merge pull request #33037 from Jordie0608/nextupweaddsupportformongodb Conversion script MariaDB note --- SQL/feedback_conversion_2017-11-12.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/SQL/feedback_conversion_2017-11-12.py b/SQL/feedback_conversion_2017-11-12.py index b8577460b3..8a60e10b7e 100644 --- a/SQL/feedback_conversion_2017-11-12.py +++ b/SQL/feedback_conversion_2017-11-12.py @@ -5,6 +5,10 @@ #It can be downloaded from command line with pip: #pip install mysqlclient # +#tgstation no longer supports MySQL which has been superseded by MariaDB, a drop-in replacement. +#Before running this script you will need to migrate to MariaDB. +#Migrating is very easy to do, for details on how see: https://mariadb.com/kb/en/library/upgrading-from-mysql-to-mariadb/ +# #You will also have to create a new feedback table for inserting converted data to per the schema: #CREATE TABLE `feedback_new` ( # `id` int(11) unsigned NOT NULL AUTO_INCREMENT, @@ -476,11 +480,25 @@ parser.add_argument("newtable", help="Name of the new table to insert to, can't args = parser.parse_args() db=MySQLdb.connect(host=args.address, user=args.username, passwd=args.password, db=args.database) cursor=db.cursor() +cursor.execute("SELECT @@GLOBAL.version_comment") +db_version = "".join([x for x in cursor.fetchone()]) +database_mysql = False +if 'MySQL' in db_version: + database_mysql = True +elif 'mariadb' not in db_version: + choice = input("Unable to determine database version installed, are you using MySQL? Type Yes or No and press enter...").lower() + if choice == "yes": + database_mysql = True +if database_mysql == True: + print("WARNING Database detected to be MySQL: tgstation no longer supports MySQL which has been superseded by MariaDB, a drop-in replacement.\nBefore running this script you will need to migrate to MariaDB.\nMigrating is very easy to do, for details on how see: https://mariadb.com/kb/en/library/upgrading-from-mysql-to-mariadb/") + input("Press enter to quit...") + quit() current_table = args.curtable new_table = args.newtable -cursor.execute("SELECT max(id) FROM {0}".format(current_table)) +cursor.execute("SELECT max(id), max(round_id) FROM {0}".format(current_table)) query_id = cursor.fetchone() max_id = query_id[0] +max_round_id = query_id[1] start_time = datetime.now() print("Beginning conversion at {0}".format(start_time.strftime("%Y-%m-%d %H:%M:%S"))) try: @@ -493,7 +511,7 @@ try: if not query_row: continue else: - if current_round != query_row[2]: + if current_round != query_row[2] or current_round == max_round_id: multirows_completed.clear() if query_values: query_values = query_values[:-1] @@ -524,8 +542,11 @@ try: print("Conversion completed at {0}".format(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) print("Script duration: {0}".format(end_time - start_time)) except Exception as e: + cursor.execute("SELECT round_id FROM {0} WHERE id = {1}".format(current_table, current_id-1)) + query_round_id = cursor.fetchone() end_time = datetime.now() print("Error encountered on row ID {0} at {1}".format(current_id, datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) + print("Note SQL insertion errors will be due to data from round ID {0}".format(query_round_id[0])) #since data is inserted when the round id changes on a new row print("Script duration: {0}".format(end_time - start_time)) cursor.execute("TRUNCATE {0} ".format(new_table)) raise e From 6bfca33a78662b2db9017e60f76535463d388379 Mon Sep 17 00:00:00 2001 From: AnturK Date: Mon, 11 Dec 2017 17:57:20 +0100 Subject: [PATCH 03/96] Roundend report refactor --- code/__DEFINES/clockcult.dm | 1 - code/__HELPERS/roundend.dm | 412 ++++++++++++++++++ code/_globalvars/game_modes.dm | 18 +- code/_globalvars/misc.dm | 2 + code/_onclick/hud/alert.dm | 31 +- code/controllers/subsystem/blackbox.dm | 8 +- code/controllers/subsystem/ticker.dm | 3 + code/controllers/subsystem/vote.dm | 11 + code/datums/ai_laws.dm | 29 +- code/datums/antagonists/abductor.dm | 63 +++ code/datums/antagonists/antag_datum.dm | 58 ++- code/datums/antagonists/brother.dm | 68 +++ code/datums/antagonists/changeling.dm | 33 +- code/datums/antagonists/clockcult.dm | 53 ++- code/datums/antagonists/cult.dm | 259 ++++++++--- code/datums/antagonists/datum_traitor.dm | 60 ++- code/datums/antagonists/devil.dm | 30 ++ code/datums/antagonists/ninja.dm | 21 +- code/datums/antagonists/nukeop.dm | 322 ++++++++++++++ code/datums/antagonists/pirate.dm | 57 ++- code/datums/antagonists/revolution.dm | 55 ++- code/datums/antagonists/wizard.dm | 48 +- code/datums/mind.dm | 62 ++- code/game/gamemodes/antag_spawner.dm | 1 + code/game/gamemodes/brother/traitor_bro.dm | 43 +- code/game/gamemodes/changeling/changeling.dm | 3 + code/game/gamemodes/clock_cult/clock_cult.dm | 46 +- .../clock_items/construct_chassis.dm | 3 +- .../clock_cult/clock_mobs/_eminence.dm | 22 +- .../clock_structures/eminence_spire.dm | 10 +- code/game/gamemodes/cult/cult.dm | 210 ++------- code/game/gamemodes/cult/cult_comms.dm | 68 +-- code/game/gamemodes/cult/ritual.dm | 23 +- code/game/gamemodes/cult/runes.dm | 25 +- code/game/gamemodes/devil/game_mode.dm | 38 -- code/game/gamemodes/game_mode.dm | 97 +---- code/game/gamemodes/meteor/meteor.dm | 19 +- .../miniantags/abduction/abduction.dm | 43 -- .../abduction/machinery/experiment.dm | 20 +- .../gamemodes/miniantags/monkey/monkey.dm | 11 +- code/game/gamemodes/miniantags/morph/morph.dm | 1 + .../gamemodes/miniantags/revenant/revenant.dm | 1 + .../miniantags/slaughter/slaughterevent.dm | 1 + code/game/gamemodes/nuclear/nuclear.dm | 40 ++ code/game/gamemodes/objective_team.dm | 14 +- code/game/gamemodes/revolution/revolution.dm | 58 +-- code/game/gamemodes/traitor/traitor.dm | 7 +- code/game/gamemodes/wizard/soulstone.dm | 3 +- code/game/gamemodes/wizard/wizard.dm | 20 +- code/game/machinery/wishgranter.dm | 1 + code/modules/admin/admin.dm | 8 +- code/modules/admin/verbs/one_click_antag.dm | 9 + code/modules/admin/verbs/onlyone.dm | 3 + .../awaymissions/mission_code/wildwest.dm | 2 + code/modules/client/client_defines.dm | 6 + code/modules/client/client_procs.dm | 7 + code/modules/client/player_details.dm | 2 + code/modules/clothing/under/accessories.dm | 2 +- code/modules/events/holiday/vday.dm | 7 + code/modules/events/nightmare.dm | 1 + .../modules/events/wizard/departmentrevolt.dm | 1 + code/modules/events/wizard/greentext.dm | 1 + code/modules/mob/living/silicon/robot/life.dm | 1 + .../mob/living/simple_animal/constructs.dm | 10 +- .../friendly/drone/extra_drone_types.dm | 2 +- code/modules/mob/login.dm | 4 + code/modules/ninja/ninja_event.dm | 2 +- code/modules/power/singularity/narsie.dm | 11 +- .../spells/spell_types/rightandwrong.dm | 2 + code/modules/station_goals/station_goal.dm | 6 +- html/browser/roundend.css | 67 +++ tgstation.dme | 2 + 72 files changed, 1928 insertions(+), 760 deletions(-) create mode 100644 code/__HELPERS/roundend.dm create mode 100644 code/datums/antagonists/nukeop.dm create mode 100644 code/modules/client/player_details.dm create mode 100644 html/browser/roundend.css diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm index d51dbfd047..7451c42cab 100644 --- a/code/__DEFINES/clockcult.dm +++ b/code/__DEFINES/clockcult.dm @@ -6,7 +6,6 @@ #define HIEROPHANT_ANSIBLE "hierophant_ansible" //Use this for construction-related scripture! GLOBAL_VAR_INIT(clockwork_construction_value, 0) //The total value of all structures built by the clockwork cult -GLOBAL_VAR_INIT(clockwork_caches, 0) //How many clockwork caches exist in the world (not each individual) GLOBAL_VAR_INIT(clockwork_vitality, 0) //How much Vitality is stored, total GLOBAL_VAR_INIT(clockwork_power, 0) //How many watts of power are globally available to the clockwork cult diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm new file mode 100644 index 0000000000..7bd08167e6 --- /dev/null +++ b/code/__HELPERS/roundend.dm @@ -0,0 +1,412 @@ +/datum/controller/subsystem/ticker/proc/gather_roundend_feedback() + var/clients = GLOB.player_list.len + var/surviving_humans = 0 + var/surviving_total = 0 + var/ghosts = 0 + var/escaped_humans = 0 + var/escaped_total = 0 + + for(var/mob/M in GLOB.player_list) + if(ishuman(M)) + if(!M.stat) + surviving_humans++ + if(M.z == ZLEVEL_CENTCOM) + escaped_humans++ + if(!M.stat) + surviving_total++ + if(M.z == ZLEVEL_CENTCOM) + escaped_total++ + + if(isobserver(M)) + ghosts++ + + if(clients) + SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients")) + if(ghosts) + SSblackbox.record_feedback("nested tally", "round_end_stats", ghosts, list("ghosts")) + if(surviving_humans) + SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_humans, list("survivors", "human")) + if(surviving_total) + SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_total, list("survivors", "total")) + if(escaped_humans) + SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_humans, list("escapees", "human")) + if(escaped_total) + SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_total, list("escapees", "total")) + + gather_antag_success_rate() + +/datum/controller/subsystem/ticker/proc/gather_antag_success_rate() + var/team_gid = 1 + var/list/team_ids = list() + + for(var/datum/antagonist/A in GLOB.antagonists) + var/list/antag_info = list() + antag_info["key"] = A.owner.key + antag_info["name"] = A.owner.name + antag_info["antagonist_type"] = A.type + antag_info["antagonist_name"] = A.name //For auto and custom roles + antag_info["objectives"] = list() + antag_info["team"] = list() + var/datum/objective_team/T = A.get_team() + if(T) + antag_info["team"]["type"] = T.type + antag_info["team"]["name"] = T.name + if(!team_ids[T]) + team_ids[T] = team_gid++ + antag_info["team"]["id"] = team_ids[T] + + if(!A.owner) + continue + if(A.objectives.len) + for(var/datum/objective/O in A.objectives) + var/result = O.check_completion() ? "SUCCESS" : "FAIL" + antag_info["objectives"] += list(list("objective_type"=O.type,"text"=O.explanation_text,"result"=result)) + SSblackbox.record_feedback("associative", "antagonists", 1, antag_info) + + +/datum/controller/subsystem/ticker/proc/declare_completion() + set waitfor = FALSE + + to_chat(world, "


The round has ended.") + if(LAZYLEN(GLOB.round_end_notifiees)) + send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.") + + for(var/client/C in GLOB.clients) + if(!C.credits) + C.RollCredits() + C.playtitlemusic(40) + + display_report() + + gather_roundend_feedback() + + CHECK_TICK + + //Set news report and mode result + mode.set_round_result() + + send2irc("Server", "Round just ended.") + + if(CONFIG_GET(string/cross_server_address)) + send_news_report() + + CHECK_TICK + + //These need update to actually reflect the real antagonists + //Print a list of antagonists to the server log + var/list/total_antagonists = list() + //Look into all mobs in world, dead or alive + for(var/datum/mind/Mind in minds) + var/temprole = Mind.special_role + if(temprole) //if they are an antagonist of some sort. + if(temprole in total_antagonists) //If the role exists already, add the name to it + total_antagonists[temprole] += ", [Mind.name]([Mind.key])" + else + total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob + total_antagonists[temprole] += ": [Mind.name]([Mind.key])" + + CHECK_TICK + + //Now print them all into the log! + log_game("Antagonists at round end were...") + for(var/i in total_antagonists) + log_game("[i]s[total_antagonists[i]].") + + CHECK_TICK + + //Collects persistence features + if(mode.allow_persistence_save) + SSpersistence.CollectData() + + //stop collecting feedback during grifftime + SSblackbox.Seal() + + sleep(50) + ready_for_reboot = TRUE + standard_reboot() + +/datum/controller/subsystem/ticker/proc/standard_reboot() + if(ready_for_reboot) + if(mode.station_was_nuked) + Reboot("Station destroyed by Nuclear Device.", "nuke") + else + Reboot("Round ended.", "proper completion") + else + CRASH("Attempted standard reboot without ticker roundend completion") + +//Common part of the report +/datum/controller/subsystem/ticker/proc/build_roundend_report() + var/list/parts = list() + + //Gamemode specific things. Should be empty most of the time. + parts += mode.special_report() + + CHECK_TICK + + //AI laws + parts += law_report() + + CHECK_TICK + + //Antagonists + parts += antag_report() + + CHECK_TICK + //Medals + parts += medal_report() + //Station Goals + parts += goal_report() + + listclearnulls(parts) + + return parts.Join() + + +/datum/controller/subsystem/ticker/proc/survivor_report() + var/list/parts = list() + var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED + var/num_survivors = 0 + var/num_escapees = 0 + var/num_shuttle_escapees = 0 + + //Player status report + for(var/i in GLOB.mob_list) + var/mob/Player = i + if(Player.mind && !isnewplayer(Player)) + if(Player.stat != DEAD && !isbrain(Player)) + num_survivors++ + if(station_evacuated) //If the shuttle has already left the station + var/list/area/shuttle_areas + if(SSshuttle && SSshuttle.emergency) + shuttle_areas = SSshuttle.emergency.shuttle_areas + if(Player.onCentCom() || Player.onSyndieBase()) + num_escapees++ + if(shuttle_areas[get_area(Player)]) + num_shuttle_escapees++ + + //Round statistics report + var/datum/station_state/end_state = new /datum/station_state() + end_state.count() + var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100) + + parts += "[GLOB.TAB]Shift Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]" + parts += "[GLOB.TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]" + var/total_players = GLOB.joined_player_list.len + if(total_players) + parts+= "[GLOB.TAB]Total Population: [total_players]" + if(station_evacuated) + parts += "
[GLOB.TAB]Evacuation Rate: [num_escapees] ([PERCENT(num_escapees/total_players)]%)" + parts += "[GLOB.TAB](on emergency shuttle): [num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)" + parts += "[GLOB.TAB]Survival Rate: [num_survivors] ([PERCENT(num_survivors/total_players)]%)" + return parts.Join("
") + +/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C,common_report) + var/list/report_parts = list() + + report_parts += personal_report(C) + report_parts += common_report + + var/datum/browser/roundend_report = new(C, "roundend") + roundend_report.width = 800 + roundend_report.height = 600 + roundend_report.set_content(report_parts.Join()) + roundend_report.stylesheets = list() + roundend_report.add_stylesheet("roundend",'html/browser/roundend.css') + + roundend_report.open(0) + +/datum/controller/subsystem/ticker/proc/personal_report(client/C) + var/list/parts = list() + var/mob/M = C.mob + if(M.mind && !isnewplayer(M)) + if(M.stat != DEAD && !isbrain(M)) + if(EMERGENCY_ESCAPED_OR_ENDGAMED) + if(!M.onCentCom() || !M.onSyndieBase()) + parts += "
" + parts += "You managed to survive, but were marooned on [station_name()]..." + else + parts += "
" + parts += "You managed to survive the events on [station_name()] as [M.real_name]." + else + parts += "
" + parts += "You managed to survive the events on [station_name()] as [M.real_name]." + + else + parts += "
" + parts += "You did not survive the events on [station_name()]..." + else + parts += "
" + parts += "
" + if(GLOB.survivor_report) + parts += GLOB.survivor_report + else + parts += survivor_report() + + parts += "
" + + return parts.Join() + +/datum/controller/subsystem/ticker/proc/display_report() + GLOB.common_report = build_roundend_report() + for(var/client/C in GLOB.clients) + show_roundend_report(C,GLOB.common_report) + give_show_report_button(C) + CHECK_TICK + +/datum/controller/subsystem/ticker/proc/law_report() + var/list/parts = list() + //Silicon laws report + for (var/i in GLOB.ai_list) + var/mob/living/silicon/ai/aiPlayer = i + if(aiPlayer.mind) + parts += "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws [aiPlayer.stat != DEAD ? "at the end of the round" : "when it was deactivated"] were:" + parts += aiPlayer.laws.get_law_list(include_zeroth=TRUE) + + parts += "Total law changes: [aiPlayer.law_change_counter]" + + if (aiPlayer.connected_robots.len) + var/robolist = "[aiPlayer.real_name]'s minions were: " + for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots) + if(robo.mind) + robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]" + parts += "[robolist]" + + for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs) + if (!robo.connected_ai && robo.mind) + if (robo.stat != DEAD) + parts += "[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:" + else + parts += "[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:" + + if(robo) //How the hell do we lose robo between here and the world messages directly above this? + parts += robo.laws.get_law_list(include_zeroth=TRUE) + if(parts.len) + return "
[parts.Join("
")]
" + else + return "" + +/datum/controller/subsystem/ticker/proc/goal_report() + var/list/parts = list() + if(mode.station_goals.len) + for(var/V in mode.station_goals) + var/datum/station_goal/G = V + parts += G.get_result() + return "
    [parts.Join()]
" + +/datum/controller/subsystem/ticker/proc/medal_report() + if(GLOB.commendations.len) + var/list/parts = list() + parts += "Medal Commendations:" + for (var/com in GLOB.commendations) + parts += com + return "
[parts.Join("
")]
" + return "" + +/datum/controller/subsystem/ticker/proc/antag_report() + var/list/result = list() + var/list/all_teams = list() + var/list/all_antagonists = list() + + for(var/datum/antagonist/A in GLOB.antagonists) + all_teams |= A.get_team() + all_antagonists += A + + for(var/datum/objective_team/T in all_teams) + result += T.roundend_report() + for(var/datum/antagonist/X in all_antagonists) + if(X.get_team() == T) + all_antagonists -= X + result += " "//newline between teams + + var/currrent_category + var/datum/antagonist/previous_category + + sortTim(all_antagonists, /proc/cmp_antag_category) + + for(var/datum/antagonist/A in all_antagonists) + if(!A.show_in_roundend) + continue + if(A.roundend_category != currrent_category) + if(previous_category) + result += previous_category.roundend_report_footer() + result += "
" + result += "
" + result += A.roundend_report_header() + currrent_category = A.roundend_category + previous_category = A + result += A.roundend_report() + result += "
" + + if(all_antagonists.len) + var/datum/antagonist/last = all_antagonists[all_antagonists.len] + result += last.roundend_report_footer() + result += "
" + + return result.Join() + +/proc/cmp_antag_category(datum/antagonist/A,datum/antagonist/B) + return sorttext(B.roundend_category,A.roundend_category) + + +/datum/controller/subsystem/ticker/proc/give_show_report_button(client/C) + var/datum/action/report/R = new + C.player_details.player_actions += R + R.Grant(C.mob) + to_chat(C,"Show roundend report again") + +/datum/action/report + name = "Show roundend report" + button_icon_state = "vote" + +/datum/action/report/Trigger() + if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED) + SSticker.show_roundend_report(owner.client,GLOB.common_report) + +/datum/action/report/IsAvailable() + return 1 + +/datum/action/report/Topic(href,href_list) + if(usr != owner) + return + if(href_list["report"]) + Trigger() + return + + +/proc/printplayer(datum/mind/ply, fleecheck) + var/text = "[ply.key] was [ply.name] the [ply.assigned_role] and" + if(ply.current) + if(ply.current.stat == DEAD) + text += " died" + else + text += " survived" + if(fleecheck) + var/turf/T = get_turf(ply.current) + if(!T || !(T.z in GLOB.station_z_levels)) + text += " while fleeing the station" + if(ply.current.real_name != ply.name) + text += " as [ply.current.real_name]" + else + text += " had their body destroyed" + return text + +/proc/printplayerlist(list/players,fleecheck) + var/list/parts = list() + + parts += "
    " + for(var/datum/mind/M in players) + parts += "
  • [printplayer(M,fleecheck)]
  • " + parts += "
" + return parts.Join() + + +/proc/printobjectives(datum/mind/ply) + var/list/objective_parts = list() + var/count = 1 + for(var/datum/objective/objective in ply.objectives) + if(objective.check_completion()) + objective_parts += "Objective #[count]: [objective.explanation_text] Success!" + else + objective_parts += "Objective #[count]: [objective.explanation_text] Fail." + count++ + return objective_parts.Join("
") \ No newline at end of file diff --git a/code/_globalvars/game_modes.dm b/code/_globalvars/game_modes.dm index 9c3af923f1..3822f7077d 100644 --- a/code/_globalvars/game_modes.dm +++ b/code/_globalvars/game_modes.dm @@ -1,18 +1,12 @@ GLOBAL_VAR_INIT(master_mode, "traitor") //"extended" GLOBAL_VAR_INIT(secret_force_mode, "secret") // if this is anything but "secret", the secret rotation will forceably choose this mode +GLOBAL_VAR(common_report) //Contains commmon part of roundend report +GLOBAL_VAR(survivor_report) //Contains shared surivor report for roundend report (part of personal report) + GLOBAL_VAR_INIT(wavesecret, 0) // meteor mode, delays wave progression, terrible name GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report -// Cult, needs to be global so admin cultists are functional -GLOBAL_VAR_INIT(blood_target, null) // Cult Master's target or Construct's Master -GLOBAL_DATUM(blood_target_image, /image) -GLOBAL_VAR_INIT(blood_target_reset_timer, null) -GLOBAL_DATUM(sac_mind, /datum/mind) -GLOBAL_VAR_INIT(sac_image, null) -GLOBAL_VAR_INIT(cult_vote_called, FALSE) -GLOBAL_VAR_INIT(cult_mastered, FALSE) -GLOBAL_VAR_INIT(reckoning_complete, FALSE) -GLOBAL_VAR_INIT(sac_complete, FALSE) -GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult) -GLOBAL_LIST_EMPTY(summon_spots) \ No newline at end of file + +//TODO clear this one up too +GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult) \ No newline at end of file diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index bb86b4cbb0..8b8b817586 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -16,3 +16,5 @@ GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a perce GLOBAL_LIST_EMPTY(powernets) GLOBAL_VAR_INIT(bsa_unlock, FALSE) //BSA unlocked by head ID swipes + +GLOBAL_LIST_EMPTY(player_details) // ckey -> /datum/player_details \ No newline at end of file diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 0006d72d3b..2ad2eb76f5 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -302,32 +302,41 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." /obj/screen/alert/bloodsense/process() var/atom/blood_target - if(GLOB.blood_target) - if(!get_turf(GLOB.blood_target)) - GLOB.blood_target = null + + var/datum/antagonist/cult/antag = mob_viewer.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(!antag) + return + var/datum/objective/sacrifice/sac_objective = locate() in antag.cult_team.objectives + + if(antag.cult_team.blood_target) + if(!get_turf(antag.cult_team.blood_target)) + antag.cult_team.blood_target = null else - blood_target = GLOB.blood_target + blood_target = antag.cult_team.blood_target if(Cviewer && Cviewer.seeking && Cviewer.master) blood_target = Cviewer.master desc = "Your blood sense is leading you to [Cviewer.master]" if(!blood_target) - if(!GLOB.sac_complete) + if(sac_objective && !sac_objective.check_completion()) if(icon_state == "runed_sense0") return animate(src, transform = null, time = 1, loop = 0) angle = 0 cut_overlays() icon_state = "runed_sense0" - desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin." - add_overlay(GLOB.sac_image) + desc = "Nar-Sie demands that [sac_objective.target] be sacrificed before the summoning ritual can begin." + add_overlay(sac_objective.sac_image) else + var/datum/objective/eldergod/summon_objective = locate() in antag.cult_team.objectives + if(!summon_objective) + return if(icon_state == "runed_sense1") return animate(src, transform = null, time = 1, loop = 0) angle = 0 cut_overlays() icon_state = "runed_sense1" - desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(GLOB.summon_spots)]!" + desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(summon_objective.summon_spots)]!" add_overlay(narnar) return var/turf/P = get_turf(blood_target) @@ -388,11 +397,13 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." desc = "CHETR
NYY
HAGEHUGF-NAQ-UBABE
RATVAR.
" else var/servants = 0 - var/list/textlist + var/list/textlist = list() for(var/mob/living/L in GLOB.alive_mob_list) if(is_servant_of_ratvar(L)) servants++ - textlist = list("[SSticker.mode.eminence ? "There is an Eminence." : "There is no Eminence! Get one ASAP!"]
") + var/datum/antagonist/clockcult/C = mob_viewer.mind.has_antag_datum(/datum/antagonist/clockcult,TRUE) + if(C && C.clock_team) + textlist += "[C.clock_team.eminence ? "There is an Eminence." : "There is no Eminence! Get one ASAP!"]
" textlist += "There are currently [servants] servant[servants > 1 ? "s" : ""] of Ratvar.
" for(var/i in SSticker.scripture_states) if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 941fcbbcd6..e638de668e 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -10,7 +10,8 @@ SUBSYSTEM_DEF(blackbox) var/sealed = FALSE //time to stop tracking stats? var/list/research_levels = list() //list of highest tech levels attained that isn't lost lost by destruction of RD computers var/list/versions = list("time_dilation_current" = 2, - "science_techweb_unlock" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this + "science_techweb_unlock" = 2, + "antagonists" = 3) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this /datum/controller/subsystem/blackbox/Initialize() @@ -225,7 +226,10 @@ Versioning var/pos = length(FV.json["data"]) + 1 FV.json["data"]["[pos]"] = list() //in 512 "pos" can be replaced with "[FV.json["data"].len+1]" for(var/i in data) - FV.json["data"]["[pos]"]["[i]"] = "[data[i]]" //and here with "[FV.json["data"].len]" + if(islist(data[i])) + FV.json["data"]["[pos]"]["[i]"] = data[i] //and here with "[FV.json["data"].len]" + else + FV.json["data"]["[pos]"]["[i]"] = "[data[i]]" else CRASH("Invalid feedback key_type: [key_type]") diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 881bb7fcb7..f178a1bd24 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -398,6 +398,7 @@ SUBSYSTEM_DEF(ticker) var/mob/living/L = I L.notransform = FALSE +<<<<<<< HEAD /datum/controller/subsystem/ticker/proc/declare_completion() set waitfor = FALSE var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED @@ -596,6 +597,8 @@ SUBSYSTEM_DEF(ticker) else CRASH("Attempted standard reboot without ticker roundend completion") +======= +>>>>>>> 3d81385... Roundend report refactor (#33246) /datum/controller/subsystem/ticker/proc/send_tip_of_the_round() var/m if(selected_tip) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 55624a866c..0ce136f83b 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -206,6 +206,7 @@ SUBSYSTEM_DEF(vote) var/datum/action/vote/V = new if(question) V.name = "Vote: [question]" + C.player_details.player_actions += V V.Grant(C.mob) generated_actions += V return 1 @@ -299,6 +300,7 @@ SUBSYSTEM_DEF(vote) for(var/v in generated_actions) var/datum/action/vote/V = v if(!QDELETED(V)) + V.remove_from_client() V.Remove(V.owner) generated_actions = list() @@ -318,7 +320,16 @@ SUBSYSTEM_DEF(vote) /datum/action/vote/Trigger() if(owner) owner.vote() + remove_from_client() Remove(owner) /datum/action/vote/IsAvailable() return 1 + +/datum/action/vote/proc/remove_from_client() + if(owner.client) + owner.client.player_details.player_actions -= src + else if(owner.ckey) + var/datum/player_details/P = GLOB.player_details[owner.ckey] + if(P) + P.player_actions -= src \ No newline at end of file diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 8d86507271..c12a08a792 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -373,32 +373,9 @@ ion = list() /datum/ai_laws/proc/show_laws(who) - - if (devillaws && devillaws.len) //Yes, devil laws go in FRONT of zeroth laws, as the devil must still obey it's ban/obligation. - for(var/i in devillaws) - to_chat(who, "666. [i]") - - if (zeroth) - to_chat(who, "0. [zeroth]") - - for (var/index = 1, index <= ion.len, index++) - var/law = ion[index] - var/num = ionnum() - to_chat(who, "[num]. [law]") - - var/number = 1 - for (var/index = 1, index <= inherent.len, index++) - var/law = inherent[index] - - if (length(law) > 0) - to_chat(who, "[number]. [law]") - number++ - - for (var/index = 1, index <= supplied.len, index++) - var/law = supplied[index] - if (length(law) > 0) - to_chat(who, "[number]. [law]") - number++ + var/list/printable_laws = get_law_list(include_zeroth = TRUE) + for(var/law in printable_laws) + to_chat(who,law) /datum/ai_laws/proc/clear_zeroth_law(force) //only removes zeroth from antag ai if force is 1 if(force) diff --git a/code/datums/antagonists/abductor.dm b/code/datums/antagonists/abductor.dm index 8d13c48e7c..3b8935d9fa 100644 --- a/code/datums/antagonists/abductor.dm +++ b/code/datums/antagonists/abductor.dm @@ -1,5 +1,6 @@ /datum/antagonist/abductor name = "Abductor" + roundend_category = "abductors" job_rank = ROLE_ABDUCTOR var/datum/objective_team/abductor_team/team var/sub_role @@ -70,3 +71,65 @@ var/mob/living/carbon/human/H = owner.current var/datum/species/abductor/A = H.dna.species A.scientist = TRUE + + +/datum/objective_team/abductor_team + member_name = "abductor" + var/team_number + var/list/datum/mind/abductees = list() + +/datum/objective_team/abductor_team/is_solo() + return FALSE + +/datum/objective_team/abductor_team/proc/add_objective(datum/objective/O) + O.team = src + O.update_explanation_text() + objectives += O + +/datum/objective_team/abductor_team/roundend_report() + var/list/result = list() + + var/won = TRUE + for(var/datum/objective/O in objectives) + if(!O.check_completion()) + won = FALSE + if(won) + result += "[name] team fulfilled its mission!" + else + result += "[name] team failed its mission." + + result += "The abductors of [name] were:" + for(var/datum/mind/abductor_mind in members) + result += printplayer(abductor_mind) + result += printobjectives(abductor_mind) + + return result.Join("
") + + +/datum/antagonist/abductee + name = "Abductee" + roundend_category = "abductees" + +/datum/antagonist/abductee/on_gain() + give_objective() + . = ..() + +/datum/antagonist/abductee/greet() + to_chat(owner, "Your mind snaps!") + to_chat(owner, "You can't remember how you got here...") + owner.announce_objectives() + +/datum/antagonist/abductee/proc/give_objective() + var/mob/living/carbon/human/H = owner.current + if(istype(H)) + H.gain_trauma_type(BRAIN_TRAUMA_MILD) + var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random)) + var/datum/objective/abductee/O = new objtype() + objectives += O + owner.objectives += objectives + +/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override) + SSticker.mode.update_abductor_icons_added(mob_override ? mob_override.mind : owner) + +/datum/antagonist/abductee/remove_innate_effects(mob/living/mob_override) + SSticker.mode.update_abductor_icons_removed(mob_override ? mob_override.mind : owner) \ No newline at end of file diff --git a/code/datums/antagonists/antag_datum.dm b/code/datums/antagonists/antag_datum.dm index 0a7b2aa22f..6b5a573eff 100644 --- a/code/datums/antagonists/antag_datum.dm +++ b/code/datums/antagonists/antag_datum.dm @@ -2,6 +2,8 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist var/name = "Antagonist" + var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section + var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report var/datum/mind/owner //Mind that owns this datum var/silent = FALSE //Silent will prevent the gain/lose texts to show var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum @@ -9,6 +11,7 @@ GLOBAL_LIST_EMPTY(antagonists) var/delete_on_mind_deletion = TRUE var/job_rank var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted. + var/list/objectives = list() /datum/antagonist/New(datum/mind/new_owner) GLOB.antagonists += src @@ -96,9 +99,62 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist/proc/get_team() return +//Individual roundend report +/datum/antagonist/proc/roundend_report() + var/list/report = list() + + if(!owner) + CRASH("antagonist datum without owner") + + report += printplayer(owner) + + var/objectives_complete = TRUE + if(owner.objectives.len) + report += printobjectives(owner) + for(var/datum/objective/objective in owner.objectives) + if(!objective.check_completion()) + objectives_complete = FALSE + break + + if(owner.objectives.len == 0 || objectives_complete) + report += "The [name] was successful!" + else + report += "The [name] has failed!" + + return report.Join("
") + +//Displayed at the start of roundend_category section, default to roundend_category header +/datum/antagonist/proc/roundend_report_header() + return "The [roundend_category] were:
" + +//Displayed at the end of roundend_category section +/datum/antagonist/proc/roundend_report_footer() + return + //Should probably be on ticker or job ss ? /proc/get_antagonists(antag_type,specific = FALSE) . = list() for(var/datum/antagonist/A in GLOB.antagonists) if(!specific && istype(A,antag_type) || specific && A.type == antag_type) - . += A.owner \ No newline at end of file + . += A.owner + + + +//This datum will autofill the name with special_role +//Used as placeholder for minor antagonists, please create proper datums for these +/datum/antagonist/auto_custom + +/datum/antagonist/auto_custom/on_gain() + ..() + name = owner.special_role + //Add all objectives not already owned by other datums to this one. + var/list/already_registered_objectives = list() + for(var/datum/antagonist/A in owner.antag_datums) + if(A == src) + continue + else + already_registered_objectives |= A.objectives + objectives = owner.objectives - already_registered_objectives + +//This one is created by admin tools for custom objectives +/datum/antagonist/custom \ No newline at end of file diff --git a/code/datums/antagonists/brother.dm b/code/datums/antagonists/brother.dm index 6458e6da09..dd3bdef9d2 100644 --- a/code/datums/antagonists/brother.dm +++ b/code/datums/antagonists/brother.dm @@ -55,3 +55,71 @@ /datum/antagonist/brother/proc/finalize_brother() SSticker.mode.update_brother_icons_added(owner) + + +/datum/objective_team/brother_team + name = "brotherhood" + member_name = "blood brother" + var/meeting_area + +/datum/objective_team/brother_team/is_solo() + return FALSE + +/datum/objective_team/brother_team/proc/update_name() + var/list/last_names = list() + for(var/datum/mind/M in members) + var/list/split_name = splittext(M.name," ") + last_names += split_name[split_name.len] + + name = last_names.Join(" & ") + +/datum/objective_team/brother_team/roundend_report() + var/list/parts = list() + + parts += "The blood brothers of [name] were:" + for(var/datum/mind/M in members) + parts += printplayer(M) + var/win = TRUE + var/objective_count = 1 + for(var/datum/objective/objective in objectives) + if(objective.check_completion()) + parts += "Objective #[objective_count]: [objective.explanation_text] Success!" + else + parts += "Objective #[objective_count]: [objective.explanation_text] Fail." + win = FALSE + objective_count++ + if(win) + parts += "The blood brothers were successful!" + else + parts += "The blood brothers have failed!" + + return "
[parts.Join("
")]
" + +/datum/objective_team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE) + O.team = src + if(needs_target) + O.find_target() + O.update_explanation_text() + objectives += O + +/datum/objective_team/brother_team/proc/forge_brother_objectives() + objectives = list() + var/is_hijacker = prob(10) + for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker)) + forge_single_objective() + if(is_hijacker) + if(!locate(/datum/objective/hijack) in objectives) + add_objective(new/datum/objective/hijack) + else if(!locate(/datum/objective/escape) in objectives) + add_objective(new/datum/objective/escape) + +/datum/objective_team/brother_team/proc/forge_single_objective() + if(prob(50)) + if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len)) + add_objective(new/datum/objective/destroy, TRUE) + else if(prob(30)) + add_objective(new/datum/objective/maroon, TRUE) + else + add_objective(new/datum/objective/assassinate, TRUE) + else + add_objective(new/datum/objective/steal, TRUE) \ No newline at end of file diff --git a/code/datums/antagonists/changeling.dm b/code/datums/antagonists/changeling.dm index e98bfed782..4f8af2dc8a 100644 --- a/code/datums/antagonists/changeling.dm +++ b/code/datums/antagonists/changeling.dm @@ -4,11 +4,11 @@ /datum/antagonist/changeling name = "Changeling" + roundend_category = "changelings" job_rank = ROLE_CHANGELING var/you_are_greet = TRUE var/give_objectives = TRUE - var/list/objectives = list() var/team_mode = FALSE //Should assign team objectives ? //Changeling Stuff @@ -478,4 +478,35 @@ /datum/antagonist/changeling/xenobio name = "Xenobio Changeling" give_objectives = FALSE + show_in_roundend = FALSE //These are here for admin tracking purposes only you_are_greet = FALSE + +/datum/antagonist/changeling/roundend_report() + var/list/parts = list() + + var/changelingwin = 1 + if(!owner.current) + changelingwin = 0 + + parts += printplayer(owner) + + //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed. + parts += "Changeling ID: [changelingID]." + parts += "Genomes Extracted: [absorbedcount]" + parts += " " + if(objectives.len) + var/count = 1 + for(var/datum/objective/objective in objectives) + if(objective.check_completion()) + parts += "Objective #[count]: [objective.explanation_text] Success!
" + else + parts += "Objective #[count]: [objective.explanation_text] Fail." + changelingwin = 0 + count++ + + if(changelingwin) + parts += "The changeling was successful!" + else + parts += "The changeling has failed." + + return parts.Join("
") \ No newline at end of file diff --git a/code/datums/antagonists/clockcult.dm b/code/datums/antagonists/clockcult.dm index 8cc1c9e9a7..5f99ccc5dd 100644 --- a/code/datums/antagonists/clockcult.dm +++ b/code/datums/antagonists/clockcult.dm @@ -1,8 +1,11 @@ //CLOCKCULT PROOF OF CONCEPT /datum/antagonist/clockcult name = "Clock Cultist" - var/datum/action/innate/hierophant/hierophant_network = new() + roundend_category = "clock cultists" job_rank = ROLE_SERVANT_OF_RATVAR + var/datum/action/innate/hierophant/hierophant_network = new() + var/datum/objective_team/clockcult/clock_team + var/make_team = TRUE //This should be only false for tutorial scarabs /datum/antagonist/clockcult/silent silent = TRUE @@ -11,6 +14,22 @@ qdel(hierophant_network) return ..() +/datum/antagonist/clockcult/get_team() + return clock_team + +/datum/antagonist/clockcult/create_team(datum/objective_team/clockcult/new_team) + if(!new_team && make_team) + //TODO blah blah same as the others, allow multiple + for(var/datum/antagonist/clockcult/H in GLOB.antagonists) + if(H.clock_team) + clock_team = H.clock_team + return + clock_team = new /datum/objective_team/clockcult + return + if(make_team && !istype(new_team)) + stack_trace("Wrong team type passed to [type] initialization.") + clock_team = new_team + /datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner) . = ..() if(.) @@ -164,3 +183,35 @@ if(iscyborg(owner.current)) to_chat(owner.current, "Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.") . = ..() + + +/datum/objective_team/clockcult + name = "Clockcult" + var/list/objective + var/datum/mind/eminence + +/datum/objective_team/clockcult/proc/check_clockwork_victory() + if(GLOB.clockwork_gateway_activated) + return TRUE + return FALSE + +/datum/objective_team/clockcult/roundend_report() + var/list/parts = list() + + if(check_clockwork_victory()) + parts += "Ratvar's servants defended the Ark until its activation!" + else + parts += "The Ark was destroyed! Ratvar will rust away for all eternity!" + parts += " " + parts += "The servants' objective was: [CLOCKCULT_OBJECTIVE]." + parts += "Construction Value(CV) was: [GLOB.clockwork_construction_value]" + for(var/i in SSticker.scripture_states) + if(i != SCRIPTURE_DRIVER) + parts += "[i] scripture was: [SSticker.scripture_states[i] ? "UN":""]LOCKED" + if(eminence) + parts += "The Eminence was: [printplayer(eminence)]" + if(members.len) + parts += "Ratvar's servants were:" + parts += printplayerlist(members - eminence) + + return "
[parts.Join("
")]
" \ No newline at end of file diff --git a/code/datums/antagonists/cult.dm b/code/datums/antagonists/cult.dm index c26b0f8108..bce9123fb3 100644 --- a/code/datums/antagonists/cult.dm +++ b/code/datums/antagonists/cult.dm @@ -2,84 +2,103 @@ /datum/antagonist/cult name = "Cultist" + roundend_category = "cultists" var/datum/action/innate/cult/comm/communion = new var/datum/action/innate/cult/mastervote/vote = new job_rank = ROLE_CULTIST var/ignore_implant = FALSE + var/give_equipment = FALSE + + var/datum/objective_team/cult/cult_team + +/datum/antagonist/cult/get_team() + return cult_team + +/datum/antagonist/cult/create_team(datum/objective_team/cult/new_team) + if(!new_team) + //todo remove this and allow admin buttons to create more than one cult + for(var/datum/antagonist/cult/H in GLOB.antagonists) + if(H.cult_team) + cult_team = H.cult_team + return + cult_team = new /datum/objective_team/cult + cult_team.setup_objectives() + return + if(!istype(new_team)) + stack_trace("Wrong team type passed to [type] initialization.") + cult_team = new_team + +/datum/antagonist/cult/proc/add_objectives() + objectives |= cult_team.objectives + owner.objectives |= objectives + +/datum/antagonist/cult/proc/remove_objectives() + owner.objectives -= objectives /datum/antagonist/cult/Destroy() QDEL_NULL(communion) QDEL_NULL(vote) return ..() -/datum/antagonist/cult/proc/add_objectives() - var/list/target_candidates = list() - for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && (player != owner) && player.stat != DEAD) - target_candidates += player.mind - if(target_candidates.len == 0) - message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") - for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && (player != owner) && player.stat != DEAD) - target_candidates += player.mind - listclearnulls(target_candidates) - if(LAZYLEN(target_candidates)) - GLOB.sac_mind = pick(target_candidates) - if(!GLOB.sac_mind) - message_admins("Cult Sacrifice: ERROR - Null target chosen!") - else - var/datum/job/sacjob = SSjob.GetJob(GLOB.sac_mind.assigned_role) - var/datum/preferences/sacface = GLOB.sac_mind.current.client.prefs - var/icon/reshape = get_flat_human_icon(null, sacjob, sacface) - reshape.Shift(SOUTH, 4) - reshape.Shift(EAST, 1) - reshape.Crop(7,4,26,31) - reshape.Crop(-5,-3,26,30) - GLOB.sac_image = reshape - else - message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!") - GLOB.sac_complete = TRUE - SSticker.mode.cult_objectives += "sacrifice" - if(!GLOB.summon_spots.len) - while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES) - var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots) - if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory) - GLOB.summon_spots += summon - SSticker.mode.cult_objectives += "eldergod" - -/datum/antagonist/cult/proc/cult_memorization(datum/mind/cult_mind) - var/mob/living/current = cult_mind.current - for(var/obj_count = 1,obj_count <= SSticker.mode.cult_objectives.len,obj_count++) - var/explanation - switch(SSticker.mode.cult_objectives[obj_count]) - if("sacrifice") - if(GLOB.sac_mind) - explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it." - else - explanation = "The veil has already been weakened here, proceed to the final objective." - GLOB.sac_complete = TRUE - if("eldergod") - explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. The summoning can only be accomplished in [english_list(GLOB.summon_spots)] - where the veil is weak enough for the ritual to begin." - if(!silent) - to_chat(current, "Objective #[obj_count]: [explanation]") - cult_mind.memory += "Objective #[obj_count]: [explanation]
" - /datum/antagonist/cult/can_be_owned(datum/mind/new_owner) . = ..() if(. && !ignore_implant) - . = is_convertable_to_cult(new_owner.current) + . = is_convertable_to_cult(new_owner.current,cult_team) + +/datum/antagonist/cult/greet() + to_chat(owner, "You are a member of the cult!") + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/bloodcult.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change + owner.announce_objectives() /datum/antagonist/cult/on_gain() . = ..() var/mob/living/current = owner.current - if(!LAZYLEN(SSticker.mode.cult_objectives)) - add_objectives() + add_objectives() + if(give_equipment) + equip_cultist() SSticker.mode.cult += owner // Only add after they've been given objectives - cult_memorization(owner) SSticker.mode.update_cult_icons_added(owner) current.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) - if(GLOB.blood_target && GLOB.blood_target_image && current.client) - current.client.images += GLOB.blood_target_image + + if(cult_team.blood_target && cult_team.blood_target_image && current.client) + current.client.images += cult_team.blood_target_image + + +/datum/antagonist/cult/proc/equip_cultist(tome=FALSE) + var/mob/living/carbon/H = owner.current + if(!istype(H)) + return + if (owner.assigned_role == "Clown") + to_chat(owner, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") + H.dna.remove_mutation(CLOWNMUT) + + if(tome) + . += cult_give_item(/obj/item/tome, H) + else + . += cult_give_item(/obj/item/paper/talisman/supply, H) + to_chat(owner, "These will help you start the cult on this station. Use them well, and remember - you are not the only one.") + + +/datum/antagonist/cult/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/mob) + var/list/slots = list( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store + ) + + var/T = new item_path(mob) + var/item_name = initial(item_path.name) + var/where = mob.equip_in_one_of_slots(T, slots) + if(!where) + to_chat(mob, "Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).") + return 0 + else + to_chat(mob, "You have a [item_name] in your [where].") + if(where == "backpack") + var/obj/item/storage/B = mob.back + B.orient2hud(mob) + B.show_to(mob) + return 1 /datum/antagonist/cult/apply_innate_effects(mob/living/mob_override) . = ..() @@ -89,7 +108,7 @@ current.faction |= "cult" current.grant_language(/datum/language/narsie) current.verbs += /mob/living/proc/cult_help - if(!GLOB.cult_mastered) + if(!cult_team.cult_mastered) vote.Grant(current) communion.Grant(current) current.throw_alert("bloodsense", /obj/screen/alert/bloodsense) @@ -107,6 +126,7 @@ current.clear_alert("bloodsense") /datum/antagonist/cult/on_removal() + remove_objectives() owner.wipe_memory() SSticker.mode.cult -= owner SSticker.mode.update_cult_icons_removed(owner) @@ -114,8 +134,8 @@ owner.current.visible_message("[owner.current] looks like [owner.current.p_they()] just reverted to their old faith!", ignored_mob = owner.current) to_chat(owner.current, "An unfamiliar white light flashes through your mind, cleansing the taint of the Geometer and all your memories as her servant.") owner.current.log_message("Has renounced the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) - if(GLOB.blood_target && GLOB.blood_target_image && owner.current.client) - owner.current.client.images -= GLOB.blood_target_image + if(cult_team.blood_target && cult_team.blood_target_image && owner.current.client) + owner.current.client.images -= cult_team.blood_target_image . = ..() /datum/antagonist/cult/master @@ -145,7 +165,7 @@ var/mob/living/current = owner.current if(mob_override) current = mob_override - if(!GLOB.reckoning_complete) + if(!cult_team.reckoning_complete) reckoning.Grant(current) bloodmark.Grant(current) throwing.Grant(current) @@ -162,3 +182,118 @@ throwing.Remove(current) current.update_action_buttons_icon() current.remove_status_effect(/datum/status_effect/cult_master) + +/datum/objective_team/cult + name = "Cult" + + var/blood_target + var/image/blood_target_image + var/blood_target_reset_timer + + var/cult_vote_called = FALSE + var/cult_mastered = FALSE + var/reckoning_complete = FALSE + + +/datum/objective_team/cult/proc/setup_objectives() + //SAC OBJECTIVE , todo: move this to objective internals + var/list/target_candidates = list() + var/datum/objective/sacrifice/sac_objective = new + sac_objective.team = src + + for(var/mob/living/carbon/human/player in GLOB.player_list) + if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && player.stat != DEAD) + target_candidates += player.mind + + if(target_candidates.len == 0) + message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") + for(var/mob/living/carbon/human/player in GLOB.player_list) + if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && player.stat != DEAD) + target_candidates += player.mind + listclearnulls(target_candidates) + if(LAZYLEN(target_candidates)) + sac_objective.target = pick(target_candidates) + sac_objective.update_explanation_text() + + var/datum/job/sacjob = SSjob.GetJob(sac_objective.target.assigned_role) + var/datum/preferences/sacface = sac_objective.target.current.client.prefs + var/icon/reshape = get_flat_human_icon(null, sacjob, sacface) + reshape.Shift(SOUTH, 4) + reshape.Shift(EAST, 1) + reshape.Crop(7,4,26,31) + reshape.Crop(-5,-3,26,30) + sac_objective.sac_image = reshape + + objectives += sac_objective + else + message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!") + + + //SUMMON OBJECTIVE + + var/datum/objective/eldergod/summon_objective = new() + summon_objective.team = src + objectives += summon_objective + +/datum/objective/sacrifice + var/sacced = FALSE + var/sac_image + +/datum/objective/sacrifice/check_completion() + return sacced || completed + +/datum/objective/sacrifice/update_explanation_text() + if(target && !sacced) + explanation_text = "Sacrifice [target], the [target.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it." + else + explanation_text = "The veil has already been weakened here, proceed to the final objective." + +/datum/objective/eldergod + var/summoned = FALSE + var/list/summon_spots = list() + +/datum/objective/eldergod/New() + ..() + var/sanity = 0 + while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100) + var/area/summon = pick(GLOB.sortedAreas - summon_spots) + if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory) + summon_spots += summon + sanity++ + update_explanation_text() + +/datum/objective/eldergod/update_explanation_text() + explanation_text = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin." + +/datum/objective/eldergod/check_completion() + return summoned || completed + +/datum/objective_team/cult/proc/check_cult_victory() + for(var/datum/objective/O in objectives) + if(!O.check_completion()) + return FALSE + return TRUE + +/datum/objective_team/cult/roundend_report() + var/list/parts = list() + + if(check_cult_victory()) + parts += "The cult has succeeded! Nar-sie has snuffed out another torch in the void!" + else + parts += "The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!" + + if(objectives.len) + parts += "The cultists' objectives were:" + var/count = 1 + for(var/datum/objective/objective in objectives) + if(objective.check_completion()) + parts += "Objective #[count]: [objective.explanation_text] Success!" + else + parts += "Objective #[count]: [objective.explanation_text] Fail." + count++ + + if(members.len) + parts += "The cultists were:" + parts += printplayerlist(members) + + return "
[parts.Join("
")]
" \ No newline at end of file diff --git a/code/datums/antagonists/datum_traitor.dm b/code/datums/antagonists/datum_traitor.dm index d386c79c25..3ccdc7ddfb 100644 --- a/code/datums/antagonists/datum_traitor.dm +++ b/code/datums/antagonists/datum_traitor.dm @@ -1,5 +1,6 @@ /datum/antagonist/traitor name = "Traitor" + roundend_category = "traitors" job_rank = ROLE_TRAITOR var/should_specialise = FALSE //do we split into AI and human, set to true on inital assignment only var/ai_datum = ANTAG_DATUM_TRAITOR_AI @@ -8,7 +9,6 @@ var/employer = "The Syndicate" var/give_objectives = TRUE var/should_give_codewords = TRUE - var/list/objectives_given = list() /datum/antagonist/traitor/human var/should_equip = TRUE @@ -52,9 +52,9 @@ if(should_specialise) return ..()//we never did any of this anyway SSticker.mode.traitors -= owner - for(var/O in objectives_given) + for(var/O in objectives) owner.objectives -= O - objectives_given = list() + objectives = list() if(!silent && owner.current) to_chat(owner.current," You are no longer the [special_role]! ") owner.special_role = null @@ -71,11 +71,11 @@ /datum/antagonist/traitor/proc/add_objective(var/datum/objective/O) owner.objectives += O - objectives_given += O + objectives += O /datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O) owner.objectives -= O - objectives_given -= O + objectives -= O /datum/antagonist/traitor/proc/forge_traitor_objectives() return @@ -294,3 +294,53 @@ 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.
") +//TODO Collate +/datum/antagonist/traitor/roundend_report() + var/list/result = list() + + var/traitorwin = TRUE + + result += printplayer(owner) + + var/TC_uses = 0 + var/uplink_true = FALSE + var/purchases = "" + for(var/datum/component/uplink/H in GLOB.uplinks) + if(H && H.owner && H.owner == owner.key) + TC_uses += H.spent_telecrystals + uplink_true = TRUE + purchases += H.purchase_log.generate_render(FALSE) + + var/objectives_text = "" + if(objectives.len)//If the traitor had no objectives, don't need to process this. + var/count = 1 + for(var/datum/objective/objective in objectives) + if(objective.check_completion()) + objectives_text += "
Objective #[count]: [objective.explanation_text] Success!" + else + objectives_text += "
Objective #[count]: [objective.explanation_text] Fail." + traitorwin = FALSE + count++ + + if(uplink_true) + var/uplink_text = "(used [TC_uses] TC) [purchases]" + if(TC_uses==0 && traitorwin) + var/static/icon/badass = icon('icons/badass.dmi', "badass") + uplink_text += "[icon2html(badass, world)]" + result += uplink_text + + result += objectives_text + + var/special_role_text = lowertext(name) + + if(traitorwin) + result += "The [special_role_text] was successful!" + else + result += "The [special_role_text] has failed!" + SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg') + + return result.Join("
") + +/datum/antagonist/traitor/roundend_report_footer() + return "
The code phrases were: [GLOB.syndicate_code_phrase]
\ + The code responses were: [GLOB.syndicate_code_response]
" \ No newline at end of file diff --git a/code/datums/antagonists/devil.dm b/code/datums/antagonists/devil.dm index 416a8f3752..97e0d8c18a 100644 --- a/code/datums/antagonists/devil.dm +++ b/code/datums/antagonists/devil.dm @@ -86,6 +86,7 @@ GLOBAL_LIST_INIT(devil_syllable, list("hal", "ve", "odr", "neit", "ci", "quon", GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", ", the Lord of all things", ", Jr.")) /datum/antagonist/devil name = "Devil" + roundend_category = "devils" job_rank = ROLE_DEVIL //Don't delete upon mind destruction, otherwise soul re-selling will break. delete_on_mind_deletion = FALSE @@ -508,6 +509,35 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", owner.RemoveSpell(S) .=..() +/datum/antagonist/devil/proc/printdevilinfo() + var/list/parts = list() + parts += "The devil's true name is: [truename]" + parts += "The devil's bans were:" + parts += "[GLOB.TAB][GLOB.lawlorify[LORE][ban]]" + parts += "[GLOB.TAB][GLOB.lawlorify[LORE][bane]]" + parts += "[GLOB.TAB][GLOB.lawlorify[LORE][obligation]]" + parts += "[GLOB.TAB][GLOB.lawlorify[LORE][banish]]" + return parts.Join("
") + +/datum/antagonist/devil/roundend_report() + var/list/parts = list() + parts += printplayer(owner) + parts += printdevilinfo() + parts += printobjectives(owner) + return parts.Join("
") + +/datum/antagonist/devil/roundend_report_footer() + //sintouched go here for now as a hack , TODO proper antag datum for these + var/list/parts = list() + if(SSticker.mode.sintouched.len) + parts += "The sintouched were:" + var/list/sintouchedUnique = uniqueList(SSticker.mode.sintouched) + for(var/S in sintouchedUnique) + var/datum/mind/sintouched_mind = S + parts += printplayer(sintouched_mind) + parts += printobjectives(sintouched_mind) + return parts.Join("
") + //A simple super light weight datum for the codex gigas. /datum/fakeDevil var/truename diff --git a/code/datums/antagonists/ninja.dm b/code/datums/antagonists/ninja.dm index ab4822dd79..8201cd879d 100644 --- a/code/datums/antagonists/ninja.dm +++ b/code/datums/antagonists/ninja.dm @@ -37,19 +37,20 @@ else if(M.assigned_role in GLOB.command_positions) possible_targets[M] = 1 //good-guy - var/list/objectives = list(1,2,3,4) - while(owner.objectives.len < quantity) - switch(pick_n_take(objectives)) + var/list/possible_objectives = list(1,2,3,4) + + while(objectives.len < quantity) + switch(pick_n_take(possible_objectives)) if(1) //research var/datum/objective/download/O = new /datum/objective/download() O.owner = owner O.gen_amount_goal() - owner.objectives += O + objectives += O if(2) //steal var/datum/objective/steal/special/O = new /datum/objective/steal/special() O.owner = owner - owner.objectives += O + objectives += O if(3) //protect/kill if(!possible_targets.len) continue @@ -63,13 +64,13 @@ O.owner = owner O.target = M O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]." - owner.objectives += O + objectives += O else //protect var/datum/objective/protect/O = new /datum/objective/protect() O.owner = owner O.target = M O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm." - owner.objectives += O + objectives += O if(4) //debrain/capture if(!possible_targets.len) continue var/selected = rand(1,possible_targets.len) @@ -82,17 +83,17 @@ O.owner = owner O.target = M O.explanation_text = "Steal the brain of [M.current.real_name]." - owner.objectives += O + objectives += O else //capture var/datum/objective/capture/O = new /datum/objective/capture() O.owner = owner O.gen_amount_goal() - owner.objectives += O + objectives += O else break var/datum/objective/O = new /datum/objective/survive() O.owner = owner - owner.objectives += O + owner.objectives |= objectives /proc/remove_ninja(mob/living/L) diff --git a/code/datums/antagonists/nukeop.dm b/code/datums/antagonists/nukeop.dm new file mode 100644 index 0000000000..d0f24e7d7b --- /dev/null +++ b/code/datums/antagonists/nukeop.dm @@ -0,0 +1,322 @@ +#define NUKE_RESULT_FLUKE 0 +#define NUKE_RESULT_NUKE_WIN 1 +#define NUKE_RESULT_CREW_WIN 2 +#define NUKE_RESULT_CREW_WIN_SYNDIES_DEAD 3 +#define NUKE_RESULT_DISK_LOST 4 +#define NUKE_RESULT_DISK_STOLEN 5 +#define NUKE_RESULT_NOSURVIVORS 6 +#define NUKE_RESULT_WRONG_STATION 7 +#define NUKE_RESULT_WRONG_STATION_DEAD 8 + +/datum/antagonist/nukeop + name = "Nuclear Operative" + roundend_category = "syndicate operatives" //just in case + job_rank = ROLE_OPERATIVE + var/datum/objective_team/nuclear/nuke_team + var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team. + var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint. + var/nukeop_outfit = /datum/outfit/syndicate + +/datum/antagonist/nukeop/proc/update_synd_icons_added(mob/living/M) + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] + opshud.join_hud(M) + set_antag_hud(M, "synd") + +/datum/antagonist/nukeop/proc/update_synd_icons_removed(mob/living/M) + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] + opshud.leave_hud(M) + set_antag_hud(M, null) + +/datum/antagonist/nukeop/apply_innate_effects(mob/living/mob_override) + var/mob/living/M = mob_override || owner.current + update_synd_icons_added(M) + +/datum/antagonist/nukeop/remove_innate_effects(mob/living/mob_override) + var/mob/living/M = mob_override || owner.current + update_synd_icons_removed(M) + +/datum/antagonist/nukeop/proc/equip_op() + if(!ishuman(owner.current)) + return + var/mob/living/carbon/human/H = owner.current + + H.set_species(/datum/species/human) //Plasamen burn up otherwise, and lizards are vulnerable to asimov AIs + + H.equipOutfit(nukeop_outfit) + return TRUE + +/datum/antagonist/nukeop/greet() + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0) + to_chat(owner, "You are a [nuke_team ? nuke_team.syndicate_name : "syndicate"] agent!") + owner.announce_objectives() + return + +/datum/antagonist/nukeop/on_gain() + give_alias() + forge_objectives() + . = ..() + equip_op() + memorize_code() + if(send_to_spawnpoint) + move_to_spawnpoint() + +/datum/antagonist/nukeop/get_team() + return nuke_team + +/datum/antagonist/nukeop/proc/assign_nuke() + if(nuke_team && !nuke_team.tracked_nuke) + nuke_team.memorized_code = random_nukecode() + var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list + if(nuke) + nuke_team.tracked_nuke = nuke + if(nuke.r_code == "ADMIN") + nuke.r_code = nuke_team.memorized_code + else //Already set by admins/something else? + nuke_team.memorized_code = nuke.r_code + else + stack_trace("Syndicate nuke not found during nuke team creation.") + nuke_team.memorized_code = null + +/datum/antagonist/nukeop/proc/give_alias() + if(nuke_team && nuke_team.syndicate_name) + var/number = 1 + number = nuke_team.members.Find(owner) + owner.current.real_name = "[nuke_team.syndicate_name] Operative #[number]" + +/datum/antagonist/nukeop/proc/memorize_code() + if(nuke_team && nuke_team.tracked_nuke && nuke_team.memorized_code) + owner.store_memory("[nuke_team.tracked_nuke] Code: [nuke_team.memorized_code]", 0, 0) + to_chat(owner, "The nuclear authorization code is: [nuke_team.memorized_code]") + else + to_chat(owner, "Unfortunately the syndicate was unable to provide you with nuclear authorization code.") + +/datum/antagonist/nukeop/proc/forge_objectives() + if(nuke_team) + owner.objectives |= nuke_team.objectives + +/datum/antagonist/nukeop/proc/move_to_spawnpoint() + var/team_number = 1 + if(nuke_team) + team_number = nuke_team.members.Find(owner) + owner.current.forceMove(GLOB.nukeop_start[((team_number - 1) % GLOB.nukeop_start.len) + 1]) + +/datum/antagonist/nukeop/leader/move_to_spawnpoint() + owner.current.forceMove(pick(GLOB.nukeop_leader_start)) + +/datum/antagonist/nukeop/create_team(datum/objective_team/nuclear/new_team) + if(!new_team) + if(!always_new_team) + for(var/datum/antagonist/nukeop/N in GLOB.antagonists) + if(N.nuke_team) + nuke_team = N.nuke_team + return + nuke_team = new /datum/objective_team/nuclear + nuke_team.update_objectives() + assign_nuke() //This is bit ugly + return + if(!istype(new_team)) + stack_trace("Wrong team type passed to [type] initialization.") + nuke_team = new_team + +/datum/antagonist/nukeop/leader + name = "Nuclear Operative Leader" + nukeop_outfit = /datum/outfit/syndicate/leader + always_new_team = TRUE + var/title + +/datum/antagonist/nukeop/leader/memorize_code() + ..() + if(nuke_team && nuke_team.memorized_code) + var/obj/item/paper/P = new + P.info = "The nuclear authorization code is: [nuke_team.memorized_code]" + P.name = "nuclear bomb code" + var/mob/living/carbon/human/H = owner.current + if(!istype(H)) + P.forceMove(get_turf(H)) + else + H.put_in_hands(P, TRUE) + H.update_icons() + +/datum/antagonist/nukeop/leader/give_alias() + title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord") + if(nuke_team && nuke_team.syndicate_name) + owner.current.real_name = "[nuke_team.syndicate_name] [title]" + else + owner.current.real_name = "Syndicate [title]" + +/datum/antagonist/nukeop/leader/greet() + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0) + to_chat(owner, "You are the Syndicate [title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.") + to_chat(owner, "If you feel you are not up to this task, give your ID to another operative.") + to_chat(owner, "In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.") + owner.announce_objectives() + addtimer(CALLBACK(src, .proc/nuketeam_name_assign), 1) + + +/datum/antagonist/nukeop/leader/proc/nuketeam_name_assign() + if(!nuke_team) + return + nuke_team.rename_team(ask_name()) + +/datum/objective_team/nuclear/proc/rename_team(new_name) + syndicate_name = new_name + name = "[syndicate_name] Team" + for(var/I in members) + var/datum/mind/synd_mind = I + var/mob/living/carbon/human/H = synd_mind.current + if(!istype(H)) + continue + var/chosen_name = H.dna.species.random_name(H.gender,0,syndicate_name) + H.fully_replace_character_name(H.real_name,chosen_name) + +/datum/antagonist/nukeop/leader/proc/ask_name() + var/randomname = pick(GLOB.last_names) + var/newname = stripped_input(owner.current,"You are the nuke operative [title]. Please choose a last name for your family.", "Name change",randomname) + if (!newname) + newname = randomname + else + newname = reject_bad_name(newname) + if(!newname) + newname = randomname + + return capitalize(newname) + +/datum/antagonist/nukeop/lone + name = "Lone Operative" + always_new_team = TRUE + send_to_spawnpoint = FALSE //Handled by event + nukeop_outfit = /datum/outfit/syndicate/full + +/datum/antagonist/nukeop/lone/assign_nuke() + if(nuke_team && !nuke_team.tracked_nuke) + nuke_team.memorized_code = random_nukecode() + var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in GLOB.nuke_list + if(nuke) + nuke_team.tracked_nuke = nuke + if(nuke.r_code == "ADMIN") + nuke.r_code = nuke_team.memorized_code + else //Already set by admins/something else? + nuke_team.memorized_code = nuke.r_code + else + stack_trace("Station self destruct ot found during lone op team creation.") + nuke_team.memorized_code = null + +/datum/objective_team/nuclear + var/syndicate_name + var/obj/machinery/nuclearbomb/tracked_nuke + var/core_objective = /datum/objective/nuclear + var/memorized_code + +/datum/objective_team/nuclear/New() + ..() + syndicate_name = syndicate_name() + +/datum/objective_team/nuclear/proc/update_objectives() + if(core_objective) + var/datum/objective/O = new core_objective + O.team = src + objectives += O + +/datum/objective_team/nuclear/proc/disk_rescued() + for(var/obj/item/disk/nuclear/D in GLOB.poi_list) + if(!D.onCentCom()) + return FALSE + return TRUE + +/datum/objective_team/nuclear/proc/operatives_dead() + for(var/I in members) + var/datum/mind/operative_mind = I + if(ishuman(operative_mind.current) && (operative_mind.current.stat != DEAD)) + return FALSE + return TRUE + +/datum/objective_team/nuclear/proc/syndies_escaped() + var/obj/docking_port/mobile/S = SSshuttle.getShuttle("syndicate") + return (S && (S.z == ZLEVEL_CENTCOM || S.z == ZLEVEL_TRANSIT)) + +/datum/objective_team/nuclear/proc/get_result() + var/evacuation = SSshuttle.emergency.mode == SHUTTLE_ENDGAME + var/disk_rescued = disk_rescued() + var/syndies_didnt_escape = !syndies_escaped() + var/station_was_nuked = SSticker.mode.station_was_nuked + var/nuke_off_station = SSticker.mode.nuke_off_station + + if(nuke_off_station == NUKE_SYNDICATE_BASE) + return NUKE_RESULT_FLUKE + else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape) + return NUKE_RESULT_NUKE_WIN + else if (!disk_rescued && station_was_nuked && syndies_didnt_escape) + return NUKE_RESULT_NOSURVIVORS + else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape) + return NUKE_RESULT_WRONG_STATION + else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape) + return NUKE_RESULT_WRONG_STATION_DEAD + else if ((disk_rescued || evacuation) && operatives_dead()) + return NUKE_RESULT_CREW_WIN_SYNDIES_DEAD + else if (disk_rescued) + return NUKE_RESULT_CREW_WIN + else if (!disk_rescued && operatives_dead()) + return NUKE_RESULT_DISK_LOST + else if (!disk_rescued && evacuation) + return NUKE_RESULT_DISK_STOLEN + else + return //Undefined result + +/datum/objective_team/nuclear/roundend_report() + var/list/parts = list() + parts += "[syndicate_name] Operatives:" + + switch(get_result()) + if(NUKE_RESULT_FLUKE) + parts += "Humiliating Syndicate Defeat" + parts += "The crew of [station_name()] gave [syndicate_name] operatives back their bomb! The syndicate base was destroyed! Next time, don't lose the nuke!" + if(NUKE_RESULT_NUKE_WIN) + parts += "Syndicate Major Victory!" + parts += "[syndicate_name] operatives have destroyed [station_name()]!" + if(NUKE_RESULT_NOSURVIVORS) + parts += "Total Annihilation" + parts += "[syndicate_name] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!" + if(NUKE_RESULT_WRONG_STATION) + parts += "Crew Minor Victory" + parts += "[syndicate_name] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't do that!" + if(NUKE_RESULT_WRONG_STATION_DEAD) + parts += "[syndicate_name] operatives have earned Darwin Award!" + parts += "[syndicate_name] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't do that!" + if(NUKE_RESULT_CREW_WIN_SYNDIES_DEAD) + parts += "Crew Major Victory!" + parts += "The Research Staff has saved the disk and killed the [syndicate_name] Operatives" + if(NUKE_RESULT_CREW_WIN) + parts += "Crew Major Victory" + parts += "The Research Staff has saved the disk and stopped the [syndicate_name] Operatives!" + if(NUKE_RESULT_DISK_LOST) + parts += "Neutral Victory!" + parts += "The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name] Operatives!" + if(NUKE_RESULT_DISK_STOLEN) + parts += "Syndicate Minor Victory!" + parts += "[syndicate_name] operatives survived the assault but did not achieve the destruction of [station_name()]. Next time, don't lose the disk!" + else + parts += "Neutral Victory" + parts += "Mission aborted!" + + var/text = "
The syndicate operatives were:" + var/purchases = "" + var/TC_uses = 0 + for(var/I in members) + var/datum/mind/syndicate = I + for(var/U in GLOB.uplinks) + var/datum/component/uplink/H = U + if(H.owner == syndicate.key) + TC_uses += H.spent_telecrystals + if(H.purchase_log) + purchases += H.purchase_log.generate_render(show_key = FALSE) + else + stack_trace("WARNING: Nuke Op uplink with no purchase_log Owner: [H.owner]") + text += printplayerlist(members) + text += "
" + text += "(Syndicates used [TC_uses] TC) [purchases]" + if(TC_uses == 0 && SSticker.mode.station_was_nuked && !operatives_dead()) + text += "[icon2html('icons/badass.dmi', world, "badass")]" + + parts += text + + return "
[parts.Join("
")]
" diff --git a/code/datums/antagonists/pirate.dm b/code/datums/antagonists/pirate.dm index ad32e09151..e0ce38c1e4 100644 --- a/code/datums/antagonists/pirate.dm +++ b/code/datums/antagonists/pirate.dm @@ -1,6 +1,7 @@ /datum/antagonist/pirate name = "Space Pirate" job_rank = ROLE_TRAITOR + roundend_category = "space pirates" var/datum/objective_team/pirate/crew /datum/antagonist/pirate/greet() @@ -36,7 +37,6 @@ /datum/objective_team/pirate name = "Pirate crew" - var/list/objectives = list() /datum/objective_team/pirate/proc/forge_objectives() var/datum/objective/loot/getbooty = new() @@ -84,11 +84,11 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list( loot_table[lootname] = count else loot_table[lootname] += count - var/text = "" + var/list/loot_texts = list() for(var/key in loot_table) var/amount = loot_table[key] - text += "[amount] [key][amount > 1 ? "s":""], " - return text + loot_texts += "[amount] [key][amount > 1 ? "s":""]" + return loot_texts.Join(", ") /datum/objective/loot/proc/get_loot_value() if(!storage_area) @@ -105,31 +105,26 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list( return ..() || get_loot_value() >= target_value -//These need removal ASAP as everything is converted to datum antags. -/datum/game_mode/proc/auto_declare_completion_pirates() - var/list/datum/mind/pirates = get_antagonists(/datum/antagonist/pirate) - var/datum/objective_team/pirate/crew - var/text = "" - if(pirates.len) - text += "
Space Pirates were:" - for(var/datum/mind/M in pirates) - text += printplayer(M) - if(!crew) - var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate) - crew = P.crew - if(crew) - text += "
Loot stolen: " - var/datum/objective/loot/L = locate() in crew.objectives - text += L.loot_listing() - text += "
Total loot value : [L.get_loot_value()]/[L.target_value] credits" - var/all_dead = TRUE - for(var/datum/mind/M in crew.members) - if(considered_alive(M)) - all_dead = FALSE - break - if(L.check_completion() && !all_dead) - text += "
The pirate crew was successful!" - else - text += "
The pirate crew has failed." - to_chat(world, text) \ No newline at end of file +/datum/objective_team/pirate/roundend_report() + var/list/parts = list() + + parts += "Space Pirates were:" + + var/all_dead = TRUE + for(var/datum/mind/M in members) + if(considered_alive(M)) + all_dead = FALSE + parts += printplayerlist(members) + + parts += "Loot stolen: " + var/datum/objective/loot/L = locate() in objectives + parts += L.loot_listing() + parts += "Total loot value : [L.get_loot_value()]/[L.target_value] credits" + + if(L.check_completion() && !all_dead) + parts += "The pirate crew was successful!" + else + parts += "The pirate crew has failed." + + return parts.Join("
") \ No newline at end of file diff --git a/code/datums/antagonists/revolution.dm b/code/datums/antagonists/revolution.dm index 9db86bdf08..14c6d1ab0e 100644 --- a/code/datums/antagonists/revolution.dm +++ b/code/datums/antagonists/revolution.dm @@ -3,6 +3,7 @@ /datum/antagonist/rev name = "Revolutionary" + roundend_category = "revolutionaries" // if by some miracle revolutionaries without revolution happen job_rank = ROLE_REV var/hud_type = "rev" var/datum/objective_team/revolution/rev_team @@ -184,7 +185,6 @@ /datum/objective_team/revolution name = "Revolution" - var/list/objectives = list() var/max_headrevs = 3 /datum/objective_team/revolution/proc/update_objectives(initial = FALSE) @@ -227,3 +227,56 @@ rev.promote() addtimer(CALLBACK(src,.proc/update_heads),HEAD_UPDATE_PERIOD,TIMER_UNIQUE) + + +/datum/objective_team/revolution/roundend_report() + if(!members.len) + return + + var/list/result = list() + + result += "
" + + var/num_revs = 0 + var/num_survivors = 0 + for(var/mob/living/carbon/survivor in GLOB.alive_mob_list) + if(survivor.ckey) + num_survivors++ + if(survivor.mind) + if(is_revolutionary(survivor)) + num_revs++ + if(num_survivors) + result += "Command's Approval Rating: [100 - round((num_revs/num_survivors)*100, 0.1)]%
" + + + var/list/targets = list() + var/list/datum/mind/headrevs = get_antagonists(/datum/antagonist/rev/head) + var/list/datum/mind/revs = get_antagonists(/datum/antagonist/rev,TRUE) + if(headrevs.len) + var/list/headrev_part = list() + headrev_part += "The head revolutionaries were:" + headrev_part += printplayerlist(headrevs,TRUE) + result += headrev_part.Join("
") + + if(revs.len) + var/list/rev_part = list() + rev_part += "The revolutionaries were:" + rev_part += printplayerlist(revs,TRUE) + result += rev_part.Join("
") + + var/list/heads = SSjob.get_all_heads() + if(heads.len) + var/head_text = "The heads of staff were:" + head_text += "
    " + for(var/datum/mind/head in heads) + var/target = (head in targets) + head_text += "
  • " + if(target) + head_text += "Target" + head_text += "[printplayer(head, 1)]
  • " + head_text += "

" + result += head_text + + result += "
" + + return result.Join() \ No newline at end of file diff --git a/code/datums/antagonists/wizard.dm b/code/datums/antagonists/wizard.dm index e1e6dc09c8..7f23215d6c 100644 --- a/code/datums/antagonists/wizard.dm +++ b/code/datums/antagonists/wizard.dm @@ -5,13 +5,13 @@ /datum/antagonist/wizard name = "Space Wizard" + roundend_category = "wizards/witches" job_rank = ROLE_WIZARD var/give_objectives = TRUE var/strip = TRUE //strip before equipping var/allow_rename = TRUE var/hud_version = "wizard" var/datum/objective_team/wizard/wiz_team //Only created if wizard summons apprentices - var/list/objectives = list() //this should be base datum antag proc and list, todo make lazy var/move_to_lair = TRUE var/outfit_type = /datum/outfit/wizard var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */ @@ -45,10 +45,12 @@ /datum/objective_team/wizard name = "wizard team" + var/datum/antagonist/wizard/master_wizard /datum/antagonist/wizard/proc/create_wiz_team() wiz_team = new(owner) wiz_team.name = "[owner.current.real_name] team" + wiz_team.master_wizard = src update_wiz_icons_added(owner.current) /datum/antagonist/wizard/proc/send_to_lair() @@ -283,4 +285,46 @@ var/datum/objective/new_objective = new("Protect Wizard Academy from the intruders") new_objective.owner = owner owner.objectives += new_objective - objectives += new_objective \ No newline at end of file + objectives += new_objective + +//Solo wizard report +/datum/antagonist/wizard/roundend_report() + var/list/parts = list() + + parts += printplayer(owner) + + var/count = 1 + var/wizardwin = 1 + for(var/datum/objective/objective in objectives) + if(objective.check_completion()) + parts += "Objective #[count]: [objective.explanation_text] Success!" + else + parts += "Objective #[count]: [objective.explanation_text] Fail." + wizardwin = 0 + count++ + + if(wizardwin) + parts += "The wizard was successful!" + else + parts += "The wizard has failed!" + + if(owner.spell_list.len>0) + parts += "[owner.name] used the following spells: " + var/list/spell_names = list() + for(var/obj/effect/proc_holder/spell/S in owner.spell_list) + spell_names += S.name + parts += spell_names.Join(", ") + + return parts.Join("
") + +//Wizard with apprentices report +/datum/objective_team/wizard/roundend_report() + var/list/parts = list() + + parts += "Wizards/witches of [master_wizard.owner.name] team were:" + parts += master_wizard.roundend_report() + parts += " " + parts += "[master_wizard.owner.name] apprentices were:" + parts += printplayerlist(members - master_wizard.owner) + + return "
[parts.Join("
")]
" \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index c0ab1dc015..14d619c917 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -185,12 +185,6 @@ objectives, uplinks, powers etc are all handled. */ -/datum/mind/proc/remove_objectives() - if(objectives.len) - for(var/datum/objective/O in objectives) - objectives -= O - qdel(O) - /datum/mind/proc/remove_changeling() var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) if(C) @@ -223,7 +217,6 @@ if(src in SSticker.mode.cult) SSticker.mode.remove_cultist(src, 0, 0) special_role = null - remove_objectives() remove_antag_equip() /datum/mind/proc/remove_rev() @@ -769,17 +762,44 @@ var/objective_pos var/def_value + + + var/datum/antagonist/target_antag + if (href_list["obj_edit"]) objective = locate(href_list["obj_edit"]) if (!objective) return - objective_pos = objectives.Find(objective) + + for(var/datum/antagonist/A in antag_datums) + if(objective in A.objectives) + target_antag = A + objective_pos = A.objectives.Find(objective) + break + + if(!target_antag) //Shouldn't happen + stack_trace("objective without antagonist found") + objective_pos = objectives.Find(objective) //Text strings are easy to manipulate. Revised for simplicity. var/temp_obj_type = "[objective.type]"//Convert path into a text string. def_value = copytext(temp_obj_type, 19)//Convert last part of path into an objective keyword. if(!def_value)//If it's a custom objective, it will be an empty string. def_value = "custom" + else + switch(antag_datums.len) + if(0) + target_antag = add_antag_datum(/datum/antagonist/custom) + if(1) + target_antag = antag_datums[1] + else + var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", def_value) as null|anything in antag_datums + "(new custom antag)" + if (QDELETED(target)) + return + else if(target == "(new custom antag)") + target_antag = add_antag_datum(/datum/antagonist/custom) + else + target_antag = target var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "late-assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom") if (!new_obj_type) @@ -901,11 +921,15 @@ return if (objective) + if(target_antag) + target_antag.objectives -= objective objectives -= objective - objectives.Insert(objective_pos, new_objective) + target_antag.objectives.Insert(objective_pos, new_objective) message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]") log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]") else + if(target_antag) + target_antag.objectives += new_objective objectives += new_objective message_admins("[key_name_admin(usr)] added a new objective for [current]: [new_objective.explanation_text]") log_admin("[key_name(usr)] added a new objective for [current]: [new_objective.explanation_text]") @@ -914,6 +938,11 @@ var/datum/objective/objective = locate(href_list["obj_delete"]) if(!istype(objective)) return + + for(var/datum/antagonist/A in antag_datums) + if(objective in A.objectives) + A.objectives -= objective + break objectives -= objective message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]") log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]") @@ -996,11 +1025,13 @@ message_admins("[key_name_admin(usr)] has cult'ed [current].") log_admin("[key_name(usr)] has cult'ed [current].") if("tome") - if (!SSticker.mode.equip_cultist(current,1)) + var/datum/antagonist/cult/C = has_antag_datum(/datum/antagonist/cult,TRUE) + if (C.equip_cultist(current,1)) to_chat(usr, "Spawning tome failed!") if("amulet") - if (!SSticker.mode.equip_cultist(current)) + var/datum/antagonist/cult/C = has_antag_datum(/datum/antagonist/cult,TRUE) + if (C.equip_cultist(current)) to_chat(usr, "Spawning amulet failed!") else if(href_list["clockcult"]) @@ -1407,16 +1438,11 @@ /datum/mind/proc/make_Cultist() - if(!(src in SSticker.mode.cult)) - SSticker.mode.add_cultist(src,FALSE) + if(!has_antag_datum(/datum/antagonist/cult,TRUE)) + SSticker.mode.add_cultist(src,FALSE,equip=TRUE) special_role = "Cultist" to_chat(current, "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy your world is, you see that it should be open to the knowledge of Nar-Sie.") to_chat(current, "Assist your new bretheren in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") - var/datum/antagonist/cult/C - C.cult_memorization(src) - var/mob/living/carbon/human/H = current - if (!SSticker.mode.equip_cultist(current)) - to_chat(H, "Spawning an amulet from your Master failed.") /datum/mind/proc/make_Rev() var/datum/antagonist/rev/head/head = new(src) diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index 7456b8f5eb..d0ab4347ff 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -242,6 +242,7 @@ new_objective2.owner = S.mind new_objective2.explanation_text = "[objective_verb] everyone[usr ? " else while you're at it":""]." S.mind.objectives += new_objective2 + S.mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(S, S.playstyle_string) to_chat(S, "You are currently not currently in the same plane of existence as the station. \ Ctrl+Click a blood pool to manifest.") diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index c1af1601ce..34373da5c8 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -1,41 +1,3 @@ -/datum/objective_team/brother_team - name = "brotherhood" - member_name = "blood brother" - var/list/objectives = list() - var/meeting_area - -/datum/objective_team/brother_team/is_solo() - return FALSE - -/datum/objective_team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE) - O.team = src - if(needs_target) - O.find_target() - O.update_explanation_text() - objectives += O - -/datum/objective_team/brother_team/proc/forge_brother_objectives() - objectives = list() - var/is_hijacker = prob(10) - for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker)) - forge_single_objective() - if(is_hijacker) - if(!locate(/datum/objective/hijack) in objectives) - add_objective(new/datum/objective/hijack) - else if(!locate(/datum/objective/escape) in objectives) - add_objective(new/datum/objective/escape) - -/datum/objective_team/brother_team/proc/forge_single_objective() - if(prob(50)) - if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len)) - add_objective(new/datum/objective/destroy, TRUE) - else if(prob(30)) - add_objective(new/datum/objective/maroon, TRUE) - else - add_objective(new/datum/objective/assassinate, TRUE) - else - add_objective(new/datum/objective/steal, TRUE) - /datum/game_mode var/list/datum/mind/brothers = list() var/list/datum/objective_team/brother_team/brother_teams = list() @@ -54,6 +16,7 @@ var/list/datum/objective_team/brother_team/pre_brother_teams = list() var/const/team_amount = 2 //hard limit on brother teams if scaling is turned off var/const/min_team_size = 2 + traitors_required = FALSE //Only teams are possible var/meeting_areas = list("The Bar", "Dorms", "Escape Dock", "Arrivals", "Holodeck", "Primary Tool Storage", "Recreation Area", "Chapel", "Library") @@ -92,12 +55,14 @@ team.forge_brother_objectives() for(var/datum/mind/M in team.members) M.add_antag_datum(ANTAG_DATUM_BROTHER, team) + team.update_name() brother_teams += pre_brother_teams return ..() /datum/game_mode/traitor/bros/generate_report() return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust." +<<<<<<< HEAD /datum/game_mode/proc/auto_declare_completion_brother() if(!LAZYLEN(brother_teams)) return @@ -130,6 +95,8 @@ text += "
" to_chat(world, text) +======= +>>>>>>> 3d81385... Roundend report refactor (#33246) /datum/game_mode/proc/update_brother_icons_added(datum/mind/brother_mind) var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER] brotherhud.join_hud(brother_mind.current) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index a70f392d4f..6fc06f7bca 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -94,6 +94,7 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th of the Thing being sent to a station in this sector is highly likely. It may be in the guise of any crew member. Trust nobody - suspect everybody. Do not announce this to the crew, \ as paranoia may spread and inhibit workplace efficiency." +<<<<<<< HEAD /datum/game_mode/proc/auto_declare_completion_changeling() var/list/changelings = get_antagonists(/datum/antagonist/changeling,TRUE) //Only real lings get a mention if(changelings.len) @@ -135,6 +136,8 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th return 1 +======= +>>>>>>> 3d81385... Roundend report refactor (#33246) /proc/changeling_transform(mob/living/carbon/human/user, datum/changelingprofile/chosen_prof) var/datum/dna/chosen_dna = chosen_prof.dna user.real_name = chosen_prof.name diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 61bd9bb496..778cf41022 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -65,13 +65,16 @@ Credit where due: return TRUE return FALSE -/proc/add_servant_of_ratvar(mob/L, silent = FALSE) +/proc/add_servant_of_ratvar(mob/L, silent = FALSE, create_team = TRUE) if(!L || !L.mind) return var/update_type = ANTAG_DATUM_CLOCKCULT if(silent) update_type = ANTAG_DATUM_CLOCKCULT_SILENT - . = L.mind.add_antag_datum(update_type) + var/datum/antagonist/clockcult/C = new update_type(L.mind) + C.make_team = create_team + C.show_in_roundend = create_team //tutorial scarabs begone + . = L.mind.add_antag_datum(C) /proc/remove_servant_of_ratvar(mob/L, silent = FALSE) if(!L || !L.mind) @@ -88,7 +91,6 @@ Credit where due: /////////////// /datum/game_mode - var/datum/mind/eminence //The clockwork Eminence var/list/servants_of_ratvar = list() //The Enlightened servants of Ratvar var/clockwork_explanation = "Defend the Ark of the Clockwork Justiciar and free Ratvar." //The description of the current objective @@ -110,6 +112,8 @@ Credit where due: var/servants_to_serve = list() var/roundstart_player_count var/ark_time //In minutes, how long the Ark waits before activation; this is equal to 30 + (number of players / 5) (max 40 mins.) + + var/datum/objective_team/clockcult/main_clockcult /datum/game_mode/clockwork_cult/pre_setup() if(CONFIG_GET(flag/protect_roles_from_antagonist)) @@ -191,16 +195,16 @@ Credit where due: . = ..() /datum/game_mode/clockwork_cult/proc/check_clockwork_victory() + return main_clockcult.check_clockwork_victory() + +/datum/game_mode/clock_cult/set_round_result() + ..() if(GLOB.clockwork_gateway_activated) SSticker.news_report = CLOCK_SUMMON - return TRUE + SSticker.mode_result = "win - servants completed their objective (summon ratvar)" else SSticker.news_report = CULT_FAILURE - return FALSE - -/datum/game_mode/clockwork_cult/declare_completion() - ..() - return //Doesn't end until the round does + SSticker.mode_result = "loss - servants failed their objective (summon ratvar)" /datum/game_mode/clockwork_cult/generate_report() return "Bluespace monitors near your sector have detected a continuous stream of patterned fluctuations since the station was completed. It is most probable that a powerful entity \ @@ -210,30 +214,6 @@ Credit where due: working for this entity and utilizing highly-advanced technology to cross the great distance at will. If they should turn out to be a credible threat, the task falls on you and \ your crew to dispatch it in a timely manner." -/datum/game_mode/proc/auto_declare_completion_clockwork_cult() - var/text = "" - if(istype(SSticker.mode, /datum/game_mode/clockwork_cult)) //Possibly hacky? - var/datum/game_mode/clockwork_cult/C = SSticker.mode - if(C.check_clockwork_victory()) - text += "Ratvar's servants defended the Ark until its activation!" - SSticker.mode_result = "win - servants completed their objective (summon ratvar)" - else - text += "The Ark was destroyed! Ratvar will rust away for all eternity!" - SSticker.mode_result = "loss - servants failed their objective (summon ratvar)" - text += "
The servants' objective was: [CLOCKCULT_OBJECTIVE]." - text += "
Ratvar's servants had [GLOB.clockwork_caches] Tinkerer's Caches." - text += "
Construction Value(CV) was: [GLOB.clockwork_construction_value]" - for(var/i in SSticker.scripture_states) - if(i != SCRIPTURE_DRIVER) - text += "
[i] scripture was: [SSticker.scripture_states[i] ? "UN":""]LOCKED" - if(SSticker.mode.eminence) - text += "
The Eminence was: [printplayer(SSticker.mode.eminence)]" - if(servants_of_ratvar.len) - text += "
Ratvar's servants were:" - for(var/datum/mind/M in servants_of_ratvar - SSticker.mode.eminence) - text += printplayer(M) - to_chat(world, text) - /datum/game_mode/proc/update_servant_icons_added(datum/mind/M) var/datum/atom_hud/antag/A = GLOB.huds[ANTAG_HUD_CLOCKWORK] A.join_hud(M.current) diff --git a/code/game/gamemodes/clock_cult/clock_items/construct_chassis.dm b/code/game/gamemodes/clock_cult/clock_items/construct_chassis.dm index acf6e43974..1b2b867aa5 100644 --- a/code/game/gamemodes/clock_cult/clock_items/construct_chassis.dm +++ b/code/game/gamemodes/clock_cult/clock_items/construct_chassis.dm @@ -91,7 +91,8 @@ /obj/item/clockwork/construct_chassis/cogscarab/pre_spawn() if(infinite_resources) - construct_type = /mob/living/simple_animal/drone/cogscarab/ratvar //During rounds where they can't interact with the station, let them experiment with builds + //During rounds where they can't interact with the station, let them experiment with builds + construct_type = /mob/living/simple_animal/drone/cogscarab/ratvar /obj/item/clockwork/construct_chassis/cogscarab/post_spawn(mob/living/construct) if(infinite_resources) //Allow them to build stuff and recite scripture diff --git a/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm b/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm index cc91feeb98..8416e4651d 100644 --- a/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm +++ b/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm @@ -14,16 +14,6 @@ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE var/static/superheated_walls = 0 -/mob/camera/eminence/Initialize() - if(SSticker.mode.eminence) - return INITIALIZE_HINT_QDEL - . = ..() - -/mob/camera/eminence/Destroy(force) - if(!force && mind && SSticker.mode.eminence == mind) - return QDEL_HINT_LETMELIVE - return ..() - /mob/camera/eminence/CanPass(atom/movable/mover, turf/target) return TRUE @@ -39,12 +29,20 @@ /mob/camera/eminence/Login() ..() - add_servant_of_ratvar(src, TRUE) + var/datum/antagonist/clockcult/C = mind.has_antag_datum(/datum/antagonist/clockcult,TRUE) + if(!C) + add_servant_of_ratvar(src, TRUE) + C = mind.has_antag_datum(/datum/antagonist/clockcult,TRUE) + if(C && C.clock_team) + if(C.clock_team.eminence) + remove_servant_of_ratvar(src,TRUE) + qdel(src) + else + C.clock_team.eminence = src to_chat(src, "You have been selected as the Eminence!") to_chat(src, "As the Eminence, you lead the servants. Anything you say will be heard by the entire cult.") to_chat(src, "Though you can move through walls, you're also incorporeal, and largely can't interact with the world except for a few ways.") to_chat(src, "Additionally, unless the herald's beacon is activated, you can't understand any speech while away from Reebe.") - SSticker.mode.eminence = mind eminence_help() for(var/V in actions) var/datum/action/A = V diff --git a/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm index 8d4e936658..495bfaeaa8 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm @@ -17,7 +17,11 @@ return if(kingmaking) return - if(SSticker.mode.eminence) + + var/datum/antagonist/clockcult/C = user.mind.has_antag_datum(/datum/antagonist/clockcult) + if(!C || !C.clock_team) + return + if(C.clock_team.eminence) to_chat(user, "There's already an Eminence!") return if(!GLOB.servants_active) @@ -34,7 +38,9 @@ /obj/structure/destructible/clockwork/eminence_spire/attack_ghost(mob/user) if(!IsAdminGhost(user)) return - if(SSticker.mode.eminence) + + var/datum/antagonist/clockcult/random_cultist = locate() in GLOB.antagonists //if theres no cultists new team without eminence will be created anyway. + if(random_cultist && random_cultist.clock_team && random_cultist.clock_team.eminence) to_chat(user, "There's already an Eminence - too late!") return if(!GLOB.servants_active) diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index f20dd25802..67e2225772 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -2,24 +2,23 @@ /datum/game_mode var/list/datum/mind/cult = list() - var/list/cult_objectives = list() - var/eldergod = 1 //for the summon god objective /proc/iscultist(mob/living/M) return istype(M) && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_CULT) -/proc/is_sacrifice_target(datum/mind/mind) - if(mind == GLOB.sac_mind) - return TRUE +/datum/objective_team/cult/proc/is_sacrifice_target(datum/mind/mind) + for(var/datum/objective/sacrifice/sac_objective in objectives) + if(mind == sac_objective.target) + return TRUE return FALSE - -/proc/is_convertable_to_cult(mob/living/M) + +/proc/is_convertable_to_cult(mob/living/M,datum/objective_team/cult/specific_cult) if(!istype(M)) return FALSE if(M.mind) if(ishuman(M) && (M.mind.assigned_role in list("Captain", "Chaplain"))) return FALSE - if(is_sacrifice_target(M.mind)) + if(specific_cult && specific_cult.is_sacrifice_target(M.mind)) return FALSE if(M.mind.enslaved_to && !iscultist(M.mind.enslaved_to)) return FALSE @@ -55,10 +54,10 @@ var/list/cultists_to_cult = list() //the cultists we'll convert + var/datum/objective_team/cult/main_cult + /datum/game_mode/cult/pre_setup() - cult_objectives += "sacrifice" - if(CONFIG_GET(flag/protect_roles_from_antagonist)) restricted_jobs += protected_jobs @@ -86,82 +85,19 @@ /datum/game_mode/cult/post_setup() - if("sacrifice" in cult_objectives) - var/list/possible_targets = get_unconvertables() - if(!possible_targets.len) - message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") - for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && !(player.mind in cultists_to_cult)) - possible_targets += player.mind - if(possible_targets.len > 0) - GLOB.sac_mind = pick(possible_targets) - if(!GLOB.sac_mind) - message_admins("Cult Sacrifice: ERROR - Null target chosen!") - else - var/datum/job/sacjob = SSjob.GetJob(GLOB.sac_mind.assigned_role) - var/datum/preferences/sacface = GLOB.sac_mind.current.client.prefs - var/icon/reshape = get_flat_human_icon(null, sacjob, sacface) - reshape.Shift(SOUTH, 4) - reshape.Shift(EAST, 1) - reshape.Crop(7,4,26,31) - reshape.Crop(-5,-3,26,30) - GLOB.sac_image = reshape - else - message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!") - if(!GLOB.summon_spots.len) - while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES) - var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots) - if((summon.z in GLOB.station_z_levels) && summon.valid_territory) - GLOB.summon_spots += summon - cult_objectives += "eldergod" - for(var/datum/mind/cult_mind in cultists_to_cult) - 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(get_turf(cult_mind.current), 'sound/ambience/antag/bloodcult.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change - add_cultist(cult_mind, 0) + add_cultist(cult_mind, 0, equip=TRUE) ..() -/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob,tome = 0) - if(!istype(mob)) - return - if (mob.mind) - if (mob.mind.assigned_role == "Clown") - to_chat(mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - mob.dna.remove_mutation(CLOWNMUT) - if(tome) - . += cult_give_item(/obj/item/tome, mob) - else - . += cult_give_item(/obj/item/paper/talisman/supply, mob) - to_chat(mob, "These will help you start the cult on this station. Use them well, and remember - you are not the only one.") - -/datum/game_mode/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/mob) - var/list/slots = list( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store - ) - - var/T = new item_path(mob) - var/item_name = initial(item_path.name) - var/where = mob.equip_in_one_of_slots(T, slots) - if(!where) - to_chat(mob, "Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).") - return 0 - else - to_chat(mob, "You have a [item_name] in your [where].") - if(where == "backpack") - var/obj/item/storage/B = mob.back - B.orient2hud(mob) - B.show_to(mob) - return 1 - -/datum/game_mode/proc/add_cultist(datum/mind/cult_mind, stun) //BASE +/datum/game_mode/proc/add_cultist(datum/mind/cult_mind, stun , equip = FALSE) //BASE if (!istype(cult_mind)) return 0 - if(cult_mind.add_antag_datum(ANTAG_DATUM_CULT)) + + var/datum/antagonist/cult/new_cultist = new(cult_mind) + new_cultist.give_equipment = equip + + if(cult_mind.add_antag_datum(new_cultist)) if(stun) cult_mind.current.Unconscious(100) return 1 @@ -187,25 +123,19 @@ culthud.leave_hud(cult_mind.current) set_antag_hud(cult_mind.current, null) -/datum/game_mode/cult/proc/get_unconvertables() - var/list/ucs = list() - for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && !is_convertable_to_cult(player) && !(player.mind in cultists_to_cult)) - ucs += player.mind - return ucs - /datum/game_mode/cult/proc/check_cult_victory() - var/cult_fail = 0 - if(cult_objectives.Find("survive")) - cult_fail += check_survive() //the proc returns 1 if there are not enough cultists on the shuttle, 0 otherwise - if(cult_objectives.Find("eldergod")) - cult_fail += eldergod //1 by default, 0 if the elder god has been summoned at least once - if(cult_objectives.Find("sacrifice")) - if(GLOB.sac_mind && !GLOB.sac_complete) //if the target has been GLOB.sacrificed, ignore this step. otherwise, add 1 to cult_fail - cult_fail++ - return cult_fail //if any objectives aren't met, failure + return main_cult.check_cult_victory() +/datum/game_mode/cult/set_round_result() + ..() + if(check_cult_victory()) + SSticker.mode_result = "win - cult win" + SSticker.news_report = CULT_SUMMON + else + SSticker.mode_result = "loss - staff stopped the cult" + SSticker.news_report = CULT_FAILURE + /datum/game_mode/cult/proc/check_survive() var/acolytes_survived = 0 for(var/datum/mind/cult_mind in cult) @@ -218,57 +148,6 @@ return 1 -/datum/game_mode/cult/declare_completion() - - if(!check_cult_victory()) - SSticker.mode_result = "win - cult win" - to_chat(world, "The cult has succeeded! Nar-sie has snuffed out another torch in the void!") - else - SSticker.mode_result = "loss - staff stopped the cult" - to_chat(world, "The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!") - - var/text = "" - - if(cult_objectives.len) - text += "
The cultists' objectives were:" - for(var/obj_count=1, obj_count <= cult_objectives.len, obj_count++) - var/explanation - switch(cult_objectives[obj_count]) - if("survive") - if(!check_survive()) - explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Success!" - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_survive", "SUCCESS")) - SSticker.news_report = CULT_ESCAPE - else - explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Fail." - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_survive", "FAIL")) - SSticker.news_report = CULT_FAILURE - if("sacrifice") - if(GLOB.sac_complete) - explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. Success!" - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "SUCCESS")) - else - explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. Fail." - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "FAIL")) - if("eldergod") - if(!eldergod) - explanation = "Summon Nar-Sie. The summoning can only be accomplished in [english_list(GLOB.summon_spots)].Success!" - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "SUCCESS")) - SSticker.news_report = CULT_SUMMON - else - explanation = "Summon Nar-Sie. The summoning can only be accomplished in [english_list(GLOB.summon_spots)]Fail." - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "FAIL")) - SSticker.news_report = CULT_FAILURE - - text += "
Objective #[obj_count]: [explanation]" - if(cult.len) - text += "
The cultists were:" - for(var/datum/mind/M in cult) - text += printplayer(M) - to_chat(world, text) - ..() - return 1 - /datum/game_mode/cult/generate_report() return "Some stations in your sector have reported evidence of blood sacrifice and strange magic. Ties to the Wizards' Federation have been proven not to exist, and many employees \ have disappeared; even Central Command employees light-years away have felt strange presences and at times hysterical compulsions. Interrogations point towards this being the work of \ @@ -276,41 +155,4 @@ devoted to stopping this cult. Note that holy water seems to weaken and eventually return the minds of cultists that ingest it, and mindshield implants will prevent conversion \ altogether." -/datum/game_mode/proc/datum_cult_completion() - var/text = "" - var/cult_fail = 0 - cult_fail += eldergod - if(!GLOB.sac_complete) - cult_fail++ - if(!cult_fail) - SSticker.mode_result = "win - cult win" - to_chat(world, "The cult has succeeded! Nar-sie has snuffed out another torch in the void!") - else - SSticker.mode_result = "loss - staff stopped the cult" - to_chat(world, "The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!") - if(cult_objectives.len) - text += "
The cultists' objectives were:" - for(var/obj_count in 1 to 2) - var/explanation - switch(cult_objectives[obj_count]) - if("sacrifice") - if(GLOB.sac_mind) - if(GLOB.sac_complete) - explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. Success!" - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "SUCCESS")) - else - explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. Fail." - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "FAIL")) - if("eldergod") - if(!eldergod) - explanation = "Summon Nar-Sie. Success!" - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "SUCCESS")) - SSticker.news_report = CULT_SUMMON - else - explanation = "Summon Nar-Sie. Fail." - SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "FAIL")) - SSticker.news_report = CULT_FAILURE - text += "
Objective #[obj_count]: [explanation]" - to_chat(world, text) - #undef CULT_SCALING_COEFFICIENT diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm index 530b6ebb20..2938f5abf4 100644 --- a/code/game/gamemodes/cult/cult_comms.dm +++ b/code/game/gamemodes/cult/cult_comms.dm @@ -88,19 +88,21 @@ button_icon_state = "cultvote" /datum/action/innate/cult/mastervote/IsAvailable() - if(GLOB.cult_vote_called || !ishuman(owner)) + var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(!C || C.cult_team.cult_vote_called || !ishuman(owner)) return FALSE return ..() /datum/action/innate/cult/mastervote/Activate() - pollCultists(owner) + var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + pollCultists(owner,C.cult_team) -/proc/pollCultists(var/mob/living/Nominee) //Cult Master Poll +/proc/pollCultists(var/mob/living/Nominee,datum/objective_team/cult/team) //Cult Master Poll if(world.time < CULT_POLL_WAIT) to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [DisplayTimeText(CULT_POLL_WAIT-world.time)].") return - GLOB.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try - for(var/datum/mind/B in SSticker.mode.cult) + team.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try + for(var/datum/mind/B in team.members) if(B.current) B.current.update_action_buttons_icon() if(!B.current.incapacitated()) @@ -108,39 +110,39 @@ to_chat(B.current, "Acolyte [Nominee] has asserted that they are worthy of leading the cult. A vote will be called shortly.") sleep(100) var/list/asked_cultists = list() - for(var/datum/mind/B in SSticker.mode.cult) + for(var/datum/mind/B in team.members) if(B.current && B.current != Nominee && !B.current.incapacitated()) SEND_SOUND(B.current, 'sound/magic/exit_blood.ogg') asked_cultists += B.current var/list/yes_voters = pollCandidates("[Nominee] seeks to lead your cult, do you support [Nominee.p_them()]?", poll_time = 300, group = asked_cultists) if(QDELETED(Nominee) || Nominee.incapacitated()) - GLOB.cult_vote_called = FALSE - for(var/datum/mind/B in SSticker.mode.cult) + team.cult_vote_called = FALSE + for(var/datum/mind/B in team.members) if(B.current) B.current.update_action_buttons_icon() if(!B.current.incapacitated()) to_chat(B.current,"[Nominee] has died in the process of attempting to win the cult's support!") return FALSE if(!Nominee.mind) - GLOB.cult_vote_called = FALSE - for(var/datum/mind/B in SSticker.mode.cult) + team.cult_vote_called = FALSE + for(var/datum/mind/B in team.members) if(B.current) B.current.update_action_buttons_icon() if(!B.current.incapacitated()) to_chat(B.current,"[Nominee] has gone catatonic in the process of attempting to win the cult's support!") return FALSE if(LAZYLEN(yes_voters) <= LAZYLEN(asked_cultists) * 0.5) - GLOB.cult_vote_called = FALSE - for(var/datum/mind/B in SSticker.mode.cult) + team.cult_vote_called = FALSE + for(var/datum/mind/B in team.members) if(B.current) B.current.update_action_buttons_icon() if(!B.current.incapacitated()) to_chat(B.current, "[Nominee] could not win the cult's support and shall continue to serve as an acolyte.") return FALSE - GLOB.cult_mastered = TRUE + team.cult_mastered = TRUE SSticker.mode.remove_cultist(Nominee.mind, TRUE) Nominee.mind.add_antag_datum(ANTAG_DATUM_CULT_MASTER) - for(var/datum/mind/B in SSticker.mode.cult) + for(var/datum/mind/B in team.members) if(B.current) for(var/datum/action/innate/cult/mastervote/vote in B.current.actions) vote.Remove(B.current) @@ -159,6 +161,9 @@ button_icon_state = "sintouch" /datum/action/innate/cult/master/finalreck/Activate() + var/datum/antagonist/cult/antag = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(!antag) + return for(var/i in 1 to 4) chant(i) var/list/destinations = list() @@ -169,7 +174,7 @@ to_chat(owner, "You need more space to summon the cult!") return if(do_after(owner, 30, target = owner)) - for(var/datum/mind/B in SSticker.mode.cult) + for(var/datum/mind/B in antag.cult_team.members) if(B.current && B.current.stat != DEAD) var/turf/mobloc = get_turf(B.current) switch(i) @@ -194,7 +199,7 @@ addtimer(CALLBACK(B.current, /mob/.proc/reckon, final), 10) else return - GLOB.reckoning_complete = TRUE + antag.cult_team.reckoning_complete = TRUE Remove(owner) /mob/proc/reckon(turf/final) @@ -269,34 +274,37 @@ var/turf/T = get_turf(ranged_ability_user) if(!isturf(T)) return FALSE + + var/datum/antagonist/cult/C = caller.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(target in view(7, get_turf(ranged_ability_user))) - GLOB.blood_target = target + C.cult_team.blood_target = target var/area/A = get_area(target) attached_action.cooldown = world.time + attached_action.base_cooldown addtimer(CALLBACK(attached_action.owner, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown) - GLOB.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) - GLOB.blood_target_image.appearance_flags = RESET_COLOR - GLOB.blood_target_image.pixel_x = -target.pixel_x - GLOB.blood_target_image.pixel_y = -target.pixel_y + C.cult_team.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) + C.cult_team.blood_target_image.appearance_flags = RESET_COLOR + C.cult_team.blood_target_image.pixel_x = -target.pixel_x + C.cult_team.blood_target_image.pixel_y = -target.pixel_y for(var/datum/mind/B in SSticker.mode.cult) if(B.current && B.current.stat != DEAD && B.current.client) - to_chat(B.current, "Master [ranged_ability_user] has marked [GLOB.blood_target] in the [A.name] as the cult's top priority, get there immediately!") + to_chat(B.current, "Master [ranged_ability_user] has marked [C.cult_team.blood_target] in the [A.name] as the cult's top priority, get there immediately!") SEND_SOUND(B.current, sound(pick('sound/hallucinations/over_here2.ogg','sound/hallucinations/over_here3.ogg'),0,1,75)) - B.current.client.images += GLOB.blood_target_image + B.current.client.images += C.cult_team.blood_target_image attached_action.owner.update_action_buttons_icon() remove_ranged_ability("The marking rite is complete! It will last for 90 seconds.") - GLOB.blood_target_reset_timer = addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_blood_target), 900, TIMER_STOPPABLE) + C.cult_team.blood_target_reset_timer = addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_blood_target,C.cult_team), 900, TIMER_STOPPABLE) return TRUE return FALSE -/proc/reset_blood_target() - for(var/datum/mind/B in SSticker.mode.cult) +/proc/reset_blood_target(datum/objective_team/cult/team) + for(var/datum/mind/B in team.members) if(B.current && B.current.stat != DEAD && B.current.client) - if(GLOB.blood_target) + if(team.blood_target) to_chat(B.current,"The blood mark has expired!") - B.current.client.images -= GLOB.blood_target_image - QDEL_NULL(GLOB.blood_target_image) - GLOB.blood_target = null + B.current.client.images -= team.blood_target_image + QDEL_NULL(team.blood_target_image) + team.blood_target = null diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 2adaa57a2f..f0934b524f 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -179,6 +179,13 @@ This file contains the arcane tome files. var/list/shields = list() var/area/A = get_area(src) + var/datum/antagonist/cult/user_antag = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(!user_antag) + return + + var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team.objectives + var/datum/objective/sacrifice/sac_objective = locate() in user_antag.cult_team.objectives + if(!check_rune_turf(Turf, user)) return entered_rune_name = input(user, "Choose a rite to scribe.", "Sigils of Power") as null|anything in GLOB.rune_types @@ -196,18 +203,20 @@ This file contains the arcane tome files. A = get_area(src) if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated() || !check_rune_turf(Turf, user)) return + + //AAAAAAAAAAAAAAAH, i'm rewriting enough for now so TODO: remove this shit if(ispath(rune_to_scribe, /obj/effect/rune/narsie)) - if(!("eldergod" in SSticker.mode.cult_objectives)) + if(!summon_objective) to_chat(user, "Nar-Sie does not wish to be summoned!") return - if(!GLOB.sac_complete) + if(sac_objective && !sac_objective.check_completion()) to_chat(user, "The sacrifice is not complete. The portal would lack the power to open if you tried!") return - if(!SSticker.mode.eldergod) + if(summon_objective.check_completion()) to_chat(user, "\"I am already here. There is no need to try to summon me now.\"") return - if(!(A in GLOB.summon_spots)) - to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!") + if(!(A in summon_objective.summon_spots)) + to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!") return var/confirm_final = alert(user, "This is the FINAL step to summon Nar-Sie; it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for Nar-Sie!", "No") if(confirm_final == "No") @@ -215,8 +224,8 @@ This file contains the arcane tome files. return Turf = get_turf(user) A = get_area(src) - if(!(A in GLOB.summon_spots)) // Check again to make sure they didn't move - to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!") + if(!(A in summon_objective.summon_spots)) // Check again to make sure they didn't move + to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!") return priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/ai/spanomalies.ogg') for(var/B in spiral_range_turfs(1, user, 1)) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index be1c2ccaff..1bab1d90f4 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -349,7 +349,11 @@ structure_check() searches for nearby cultist structures required for the invoca color = RUNE_COLOR_DARKRED var/mob/living/L = pick(myriad_targets) var/is_clock = is_servant_of_ratvar(L) - var/is_convertable = is_convertable_to_cult(L) + + var/mob/living/F = invokers[1] + var/datum/antagonist/cult/C = F.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + + var/is_convertable = is_convertable_to_cult(L,C.cult_team) if(L.stat != DEAD && (is_clock || is_convertable)) invocation = "Mah'weyh pleggh at e'ntrath!" ..() @@ -397,17 +401,27 @@ structure_check() searches for nearby cultist structures required for the invoca return 1 /obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers) + var/mob/living/first_invoker = invokers[1] + if(!first_invoker) + return FALSE + var/datum/antagonist/cult/C = first_invoker.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(!C) + return + + var/big_sac = FALSE - if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || is_sacrifice_target(sacrificial.mind)) && invokers.len < 3) + if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3) for(var/M in invokers) to_chat(M, "[sacrificial] is too greatly linked to the world! You need three acolytes!") log_game("Offer rune failed - not enough acolytes and target is living or sac target") return FALSE if(sacrificial.mind) GLOB.sacrificed += sacrificial.mind - if(is_sacrifice_target(sacrificial.mind)) - GLOB.sac_complete = TRUE - big_sac = TRUE + for(var/datum/objective/sacrifice/sac_objective in C.cult_team.objectives) + if(sac_objective.target == sacrificial.mind) + sac_objective.sacced = TRUE + sac_objective.update_explanation_text() + big_sac = TRUE else GLOB.sacrificed += sacrificial @@ -481,7 +495,6 @@ structure_check() searches for nearby cultist structures required for the invoca sleep(40) if(src) color = RUNE_COLOR_RED - SSticker.mode.eldergod = FALSE new /obj/singularity/narsie/large/cult(T) //Causes Nar-Sie to spawn even if the rune has been removed /obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal. diff --git a/code/game/gamemodes/devil/game_mode.dm b/code/game/gamemodes/devil/game_mode.dm index 957e261933..44f3368feb 100644 --- a/code/game/gamemodes/devil/game_mode.dm +++ b/code/game/gamemodes/devil/game_mode.dm @@ -3,32 +3,6 @@ var/list/datum/mind/devils = list() var/devil_ascended = 0 // Number of arch devils on station -/datum/game_mode/proc/auto_declare_completion_sintouched() - var/text = "" - if(sintouched.len) - text += "
The sintouched were:" - var/list/sintouchedUnique = uniqueList(sintouched) - for(var/S in sintouchedUnique) - var/datum/mind/sintouched_mind = S - text += printplayer(sintouched_mind) - text += printobjectives(sintouched_mind) - text += "
" - text += "
" - to_chat(world, text) - -/datum/game_mode/proc/auto_declare_completion_devils() - /var/text = "" - if(devils.len) - text += "
The devils were:" - for(var/D in devils) - var/datum/mind/devil = D - text += printplayer(devil) - text += printdevilinfo(devil.current) - text += printobjectives(devil) - text += "
" - text += "
" - to_chat(world, text) - /datum/game_mode/proc/add_devil_objectives(datum/mind/devil_mind, quantity) var/list/validtypes = list(/datum/objective/devil/soulquantity, /datum/objective/devil/soulquality, /datum/objective/devil/sintouch, /datum/objective/devil/buy_target) for(var/i = 1 to quantity) @@ -41,18 +15,6 @@ else objective.find_target() -/datum/game_mode/proc/printdevilinfo(mob/living/ply) - var/datum/antagonist/devil/devilinfo = is_devil(ply) - if(!devilinfo) - return "Target is not a devil." - var/text = "
The devil's true name is: [devilinfo.truename]
" - text += "The devil's bans were:
" - text += " [GLOB.lawlorify[LORE][devilinfo.ban]]
" - text += " [GLOB.lawlorify[LORE][devilinfo.bane]]
" - text += " [GLOB.lawlorify[LORE][devilinfo.obligation]]
" - text += " [GLOB.lawlorify[LORE][devilinfo.banish]]

" - return text - /datum/game_mode/proc/update_devil_icons_added(datum/mind/devil_mind) var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_DEVIL] hud.join_hud(devil_mind.current) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 803e73b9e0..0c6a8fd1e0 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -73,7 +73,6 @@ /datum/game_mode/proc/pre_setup() return 1 - ///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things /datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report. if(!report) @@ -241,55 +240,9 @@ return 0 -/datum/game_mode/proc/declare_completion() - var/clients = 0 - var/surviving_humans = 0 - var/surviving_total = 0 - var/ghosts = 0 - var/escaped_humans = 0 - var/escaped_total = 0 - - for(var/mob/M in GLOB.player_list) - if(M.client) - clients++ - if(ishuman(M)) - if(!M.stat) - surviving_humans++ - if(M.z == ZLEVEL_CENTCOM) - escaped_humans++ - if(!M.stat) - surviving_total++ - if(M.z == ZLEVEL_CENTCOM) - escaped_total++ - - - if(isobserver(M)) - ghosts++ - - if(clients) - SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients")) - if(ghosts) - SSblackbox.record_feedback("nested tally", "round_end_stats", ghosts, list("ghosts")) - if(surviving_humans) - SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_humans, list("survivors", "human")) - if(surviving_total) - SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_total, list("survivors", "total")) - if(escaped_humans) - SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_humans, list("escapees", "human")) - if(escaped_total) - SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_total, list("escapees", "total")) - - send2irc("Server", "Round just ended.") - if(cult.len && !istype(SSticker.mode, /datum/game_mode/cult)) - datum_cult_completion() - - return 0 - - /datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. return 0 - /datum/game_mode/proc/send_intercept() var/intercepttext = "Central Command Status Summary
" intercepttext += "Central Command has intercepted and partially decoded a Syndicate transmission with vital information regarding their movements. The following report outlines the most \ @@ -451,34 +404,6 @@ for (var/C in GLOB.admins) to_chat(C, msg) -/datum/game_mode/proc/printplayer(datum/mind/ply, fleecheck) - var/text = "
[ply.key] was [ply.name] the [ply.assigned_role] and" - if(ply.current) - if(ply.current.stat == DEAD) - text += " died" - else - text += " survived" - if(fleecheck) - var/turf/T = get_turf(ply.current) - if(!T || !(T.z in GLOB.station_z_levels)) - text += " while fleeing the station" - if(ply.current.real_name != ply.name) - text += " as [ply.current.real_name]" - else - text += " had their body destroyed" - return text - -/datum/game_mode/proc/printobjectives(datum/mind/ply) - var/text = "" - var/count = 1 - for(var/datum/objective/objective in ply.objectives) - if(objective.check_completion()) - text += "
Objective #[count]: [objective.explanation_text] Success!" - else - text += "
Objective #[count]: [objective.explanation_text] Fail." - count++ - return text - //If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1 /datum/game_mode/proc/age_check(client/C) if(get_remaining_days(C) == 0) @@ -518,11 +443,6 @@ station_goals += new picked -/datum/game_mode/proc/declare_station_goal_completion() - for(var/V in station_goals) - var/datum/station_goal/G = V - G.print_result() - /datum/game_mode/proc/generate_report() //Generates a small text blurb for the gamemode in centcom report return "Gamemode report for [name] not set. Contact a coder." @@ -530,3 +450,20 @@ /datum/game_mode/proc/OnNukeExplosion(off_station) if(off_station < 2) station_was_nuked = TRUE //Will end the round on next check. +<<<<<<< HEAD +======= + +//Additional report section in roundend report +/datum/game_mode/proc/special_report() + return + +//Set result and news report here +/datum/game_mode/proc/set_round_result() + SSticker.mode_result = "undefined" + if(station_was_nuked) + SSticker.news_report = STATION_DESTROYED_NUKE + if(EMERGENCY_ESCAPED_OR_ENDGAMED) + SSticker.news_report = STATION_EVACUATED + if(SSshuttle.emergency.is_hijacked()) + SSticker.news_report = SHUTTLE_HIJACK +>>>>>>> 3d81385... Roundend report refactor (#33246) diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index b7a6580570..f8e0666015 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -30,30 +30,29 @@ spawn_meteors(ramp_up_final, wavetype) -/datum/game_mode/meteor/declare_completion() - var/text +/datum/game_mode/meteor/special_report() var/survivors = 0 + var/list/survivor_list = list() for(var/mob/living/player in GLOB.player_list) if(player.stat != DEAD) ++survivors if(player.onCentCom()) - text += "
[player.real_name] escaped to the safety of CentCom." + survivor_list += "[player.real_name] escaped to the safety of CentCom." else if(player.onSyndieBase()) - text += "
[player.real_name] escaped to the (relative) safety of Syndicate Space." + survivor_list += "[player.real_name] escaped to the (relative) safety of Syndicate Space." else - text += "
[player.real_name] survived but is stranded without any hope of rescue." - + survivor_list += "[player.real_name] survived but is stranded without any hope of rescue." if(survivors) - to_chat(world, "The following survived the meteor storm:[text]") + return "The following survived the meteor storm:
[survivor_list.Join("
")]" else - to_chat(world, "Nobody survived the meteor storm!") + return "Nobody survived the meteor storm!" - SSticker.mode_result = "end - evacuation" +/datum/game_mode/meteor/set_round_result() ..() - return 1 + SSticker.mode_result = "end - evacuation" /datum/game_mode/meteor/generate_report() return "[pick("Asteroids have", "Meteors have", "Large rocks have", "Stellar minerals have", "Space hail has", "Debris has")] been detected near your station, and a collision is possible, \ diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm index 4eb8642c02..050cac443d 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction.dm @@ -1,19 +1,5 @@ -/datum/objective_team/abductor_team - member_name = "abductor" - var/list/objectives = list() - var/team_number - -/datum/objective_team/abductor_team/is_solo() - return FALSE - -/datum/objective_team/abductor_team/proc/add_objective(datum/objective/O) - O.team = src - O.update_explanation_text() - objectives += O - /datum/game_mode var/list/datum/mind/abductors = list() - var/list/datum/mind/abductees = list() /datum/game_mode/abduction name = "abduction" @@ -99,35 +85,6 @@ return ..() return ..() -/datum/game_mode/abduction/declare_completion() - for(var/datum/objective_team/abductor_team/team in abductor_teams) - var/won = TRUE - for(var/datum/objective/O in team.objectives) - if(!O.check_completion()) - won = FALSE - if(won) - to_chat(world, "[team.name] team fulfilled its mission!") - else - to_chat(world, "[team.name] team failed its mission.") - ..() - return TRUE - -/datum/game_mode/proc/auto_declare_completion_abduction() - var/text = "" - if(abductors.len) - text += "
The abductors were:" - for(var/datum/mind/abductor_mind in abductors) - text += printplayer(abductor_mind) - text += printobjectives(abductor_mind) - text += "
" - if(abductees.len) - text += "
The abductees were:" - for(var/datum/mind/abductee_mind in abductees) - text += printplayer(abductee_mind) - text += printobjectives(abductee_mind) - text += "
" - to_chat(world, text) - // LANDMARKS /obj/effect/landmark/abductor var/team_number = 1 diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index c3a591a278..cf1329aec9 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -151,13 +151,18 @@ var/mob/living/mob_occupant = occupant if(mob_occupant.stat != DEAD) if(href_list["experiment"]) - flash = Experiment(occupant,href_list["experiment"]) + flash = Experiment(occupant,href_list["experiment"],usr) updateUsrDialog() add_fingerprint(usr) -/obj/machinery/abductor/experiment/proc/Experiment(mob/occupant,type) +/obj/machinery/abductor/experiment/proc/Experiment(mob/occupant,type,mob/user) LAZYINITLIST(history) var/mob/living/carbon/human/H = occupant + + var/datum/antagonist/abductor/user_abductor = user.mind.has_antag_datum(/datum/antagonist/abductor) + if(!user_abductor) + return "Authorization failure. Contact mothership immidiately." + var/point_reward = 0 if(H in history) return "Specimen already in database." @@ -182,15 +187,8 @@ if(3) to_chat(H, "You feel intensely watched.") sleep(5) - to_chat(H, "Your mind snaps!") - H.gain_trauma_type(BRAIN_TRAUMA_MILD) - to_chat(H, "You can't remember how you got here...") - var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random)) - var/datum/objective/abductee/O = new objtype() - SSticker.mode.abductees += H.mind - H.mind.objectives += O - H.mind.announce_objectives() - SSticker.mode.update_abductor_icons_added(H.mind) + user_abductor.team.abductees += H.mind + H.mind.add_antag_datum(/datum/antagonist/abductee) for(var/obj/item/organ/heart/gland/G in H.internal_organs) G.Start() diff --git a/code/game/gamemodes/miniantags/monkey/monkey.dm b/code/game/gamemodes/miniantags/monkey/monkey.dm index 379031dce9..8e02d41441 100644 --- a/code/game/gamemodes/miniantags/monkey/monkey.dm +++ b/code/game/gamemodes/miniantags/monkey/monkey.dm @@ -105,13 +105,18 @@ monkey_mind.special_role = null -/datum/game_mode/monkey/declare_completion() +/datum/game_mode/monkey/set_round_result() + ..() if(check_monkey_victory()) SSticker.mode_result = "win - monkey win" - to_chat(world, "The monkeys have overthrown their captors! Eeek eeeek!!") else SSticker.mode_result = "loss - staff stopped the monkeys" - to_chat(world, "The staff managed to contain the monkey infestation!") + +/datum/game_mode/monkey/special_report() + if(check_monkey_victory()) + return "The monkeys have overthrown their captors! Eeek eeeek!!" + else + return "The staff managed to contain the monkey infestation!" /datum/game_mode/monkey/generate_report() return "Reports of an ancient [pick("retrovirus", "flesh eating bacteria", "disease", "magical curse blamed on viruses", "banana blight")] outbreak that turn humans into monkeys has been reported in your quadrant. Any such infections may be treated with banana juice. If an outbreak occurs, ensure the station is quarantined to prevent a largescale outbreak at CentCom." diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index 5e1a97675b..2ebc21adac 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -227,6 +227,7 @@ player_mind.assigned_role = "Morph" player_mind.special_role = "Morph" SSticker.mode.traitors |= player_mind + player_mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(S, S.playstyle_string) SEND_SOUND(S, sound('sound/magic/mutate.ogg')) message_admins("[key_name_admin(S)] has been made into a morph by an event.") diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index 727203b150..78d39673eb 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -87,6 +87,7 @@ mind.assigned_role = "revenant" mind.special_role = "Revenant" SSticker.mode.traitors |= mind //Necessary for announcing + mind.add_antag_datum(/datum/antagonist/auto_custom) AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null)) AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null)) AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null)) diff --git a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm index f1f9624380..e62665f21b 100644 --- a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm +++ b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm @@ -38,6 +38,7 @@ player_mind.assigned_role = "Slaughter Demon" player_mind.special_role = "Slaughter Demon" SSticker.mode.traitors |= player_mind + player_mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(S, S.playstyle_string) to_chat(S, "You are currently not currently in the same plane of existence as the station. Blood Crawl near a blood pool to manifest.") SEND_SOUND(S, 'sound/magic/demon_dies.ogg') diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 94c372ef23..c7fc1bfdc8 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -171,6 +171,7 @@ return FALSE //its a static var btw ..() +<<<<<<< HEAD /datum/game_mode/nuclear/declare_completion() var/disk_rescued = 1 for(var/obj/item/disk/nuclear/D in GLOB.poi_list) @@ -251,12 +252,49 @@ ..() return +======= +/datum/game_mode/nuclear/set_round_result() + var result = nuke_team.get_result() + switch(result) + if(NUKE_RESULT_FLUKE) + SSticker.mode_result = "loss - syndicate nuked - disk secured" + SSticker.news_report = NUKE_SYNDICATE_BASE + if(NUKE_RESULT_NUKE_WIN) + SSticker.mode_result = "win - syndicate nuke" + SSticker.news_report = STATION_NUKED + if(NUKE_RESULT_NOSURVIVORS) + SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time" + SSticker.news_report = STATION_NUKED + if(NUKE_RESULT_WRONG_STATION) + SSticker.mode_result = "halfwin - blew wrong station" + SSticker.news_report = NUKE_MISS + if(NUKE_RESULT_WRONG_STATION_DEAD) + SSticker.mode_result = "halfwin - blew wrong station - did not evacuate in time" + SSticker.news_report = NUKE_MISS + if(NUKE_RESULT_CREW_WIN_SYNDIES_DEAD) + SSticker.mode_result = "loss - evacuation - disk secured - syndi team dead" + SSticker.news_report = OPERATIVES_KILLED + if(NUKE_RESULT_CREW_WIN) + SSticker.mode_result = "loss - evacuation - disk secured" + SSticker.news_report = OPERATIVES_KILLED + if(NUKE_RESULT_DISK_LOST) + SSticker.mode_result = "halfwin - evacuation - disk not secured" + SSticker.news_report = OPERATIVE_SKIRMISH + if(NUKE_RESULT_DISK_STOLEN) + SSticker.mode_result = "halfwin - detonation averted" + SSticker.news_report = OPERATIVE_SKIRMISH + else + SSticker.mode_result = "halfwin - interrupted" + SSticker.news_report = OPERATIVE_SKIRMISH + return ..() +>>>>>>> 3d81385... Roundend report refactor (#33246) /datum/game_mode/nuclear/generate_report() return "One of Central Command's trading routes was recently disrupted by a raid carried out by the Gorlex Marauders. They seemed to only be after one ship - a highly-sensitive \ transport containing a nuclear fission explosive, although it is useless without the proper code and authorization disk. While the code was likely found in minutes, the only disk that \ can activate this explosive is on your station. Ensure that it is protected at all times, and remain alert for possible intruders." +<<<<<<< HEAD /datum/game_mode/proc/auto_declare_completion_nuclear() if( syndicates.len || (SSticker && istype(SSticker.mode, /datum/game_mode/nuclear)) ) var/text = "
The syndicate operatives were:" @@ -298,6 +336,8 @@ synd_mind.current.real_name = synd_mind.name return +======= +>>>>>>> 3d81385... Roundend report refactor (#33246) /proc/is_nuclear_operative(mob/M) return M && istype(M) && M.mind && SSticker && SSticker.mode && M.mind in SSticker.mode.syndicates diff --git a/code/game/gamemodes/objective_team.dm b/code/game/gamemodes/objective_team.dm index 7789a167c7..1483f356d2 100644 --- a/code/game/gamemodes/objective_team.dm +++ b/code/game/gamemodes/objective_team.dm @@ -3,6 +3,7 @@ var/list/datum/mind/members = list() var/name = "team" var/member_name = "member" + var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes. /datum/objective_team/New(starting_members) . = ..() @@ -12,7 +13,6 @@ add_member(M) else add_member(starting_members) - members += starting_members /datum/objective_team/proc/is_solo() return members.len == 1 @@ -21,4 +21,14 @@ members |= new_member /datum/objective_team/proc/remove_member(datum/mind/member) - members -= member \ No newline at end of file + members -= member + +//Display members/victory/failure/objectives for the team +/datum/objective_team/proc/roundend_report() + var/list/report = list() + + report += "[name]:" + report += "The [member_name]s were:" + report += printplayerlist(members) + + return report.Join("
") \ No newline at end of file diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 4fa9532b42..cbfdb98c69 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -169,62 +169,22 @@ return FALSE return TRUE -////////////////////////////////////////////////////////////////////// -//Announces the end of the game with all relavent information stated// -////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/declare_completion() + +/datum/game_mode/revolution/set_round_result() + ..() if(finished == 1) SSticker.mode_result = "win - heads killed" - to_chat(world, "The heads of staff were killed or exiled! The revolutionaries win!") - SSticker.news_report = REVS_WIN - else if(finished == 2) SSticker.mode_result = "loss - rev heads killed" - to_chat(world, "The heads of staff managed to stop the revolution!") - SSticker.news_report = REVS_LOSE - ..() - return TRUE -/datum/game_mode/proc/auto_declare_completion_revolution() - var/list/targets = list() - var/list/datum/mind/headrevs = get_antagonists(/datum/antagonist/rev/head) - var/list/datum/mind/revs = get_antagonists(/datum/antagonist/rev,TRUE) - if(headrevs.len) - var/num_revs = 0 - var/num_survivors = 0 - for(var/mob/living/carbon/survivor in GLOB.alive_mob_list) - if(survivor.ckey) - num_survivors++ - if(survivor.mind) - if(is_revolutionary(survivor)) - num_revs++ - if(num_survivors) - to_chat(world, "[GLOB.TAB]Command's Approval Rating: [100 - round((num_revs/num_survivors)*100, 0.1)]%" ) - var/text = "
The head revolutionaries were:" - for(var/datum/mind/headrev in headrevs) - text += printplayer(headrev, 1) - text += "
" - to_chat(world, text) - - if(revs.len) - var/text = "
The revolutionaries were:" - for(var/datum/mind/rev in revs) - text += printplayer(rev, 1) - text += "
" - to_chat(world, text) - - if(revs.len || headrevs.len) - var/text = "
The heads of staff were:" - var/list/heads = SSjob.get_all_heads() - for(var/datum/mind/head in heads) - var/target = (head in targets) - if(target) - text += "Target" - text += printplayer(head, 1) - text += "
" - to_chat(world, text) +//TODO What should be displayed for revs in non-rev rounds +/datum/game_mode/revolution/special_report() + if(finished == 1) + return "The heads of staff were killed or exiled! The revolutionaries win!" + else if(finished == 2) + return "The heads of staff managed to stop the revolution!" /datum/game_mode/revolution/generate_report() return "Employee unrest has spiked in recent weeks, with several attempted mutinies on heads of staff. Some crew have been observed using flashbulb devices to blind their colleagues, \ diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 7c93a89a36..468725074d 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -27,6 +27,7 @@ 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 + var/traitors_required = TRUE //Will allow no traitors /datum/game_mode/traitor/pre_setup() @@ -55,7 +56,7 @@ log_game("[traitor.key] (ckey) has been selected as a [traitor_name]") antag_candidates.Remove(traitor) - return pre_traitors.len > 0 + return !traitors_required || pre_traitors.len > 0 /datum/game_mode/traitor/post_setup() @@ -85,6 +86,7 @@ new_antag.should_specialise = TRUE character.add_antag_datum(new_antag) +<<<<<<< HEAD /datum/game_mode/traitor/declare_completion() @@ -154,11 +156,12 @@ return TRUE +======= +>>>>>>> 3d81385... Roundend report refactor (#33246) /datum/game_mode/traitor/generate_report() return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \ Nanotrasen employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions." - /datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR] traitorhud.join_hud(traitor_mind.current) diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 484961b6f8..e0b83f4d0a 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -143,7 +143,8 @@ if("VICTIM") var/mob/living/carbon/human/T = target - if(is_sacrifice_target(T.mind)) + var/datum/antagonist/cult/C = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(C && C.cult_team.is_sacrifice_target(T.mind)) if(iscultist(user)) to_chat(user, "\"This soul is mine. SACRIFICE THEM!\"") else diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 5302ebd39b..6dd38e9d58 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -58,20 +58,13 @@ return TRUE -/datum/game_mode/wizard/declare_completion() +/datum/game_mode/wizard/set_round_result() + ..() if(finished) SSticker.mode_result = "loss - wizard killed" - to_chat(world, "The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!") - SSticker.news_report = WIZARD_KILLED - ..() - return 1 - - -/datum/game_mode/proc/auto_declare_completion_wizard() - if(wizards.len) - var/text = "
the wizards/witches were:" +<<<<<<< HEAD for(var/datum/mind/wizard in wizards) text += "
[wizard.key] was [wizard.name] (" @@ -114,9 +107,12 @@ text += ", " i++ text += "
" +======= +/datum/game_mode/wizard/special_report() + if(finished) + return "The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!" +>>>>>>> 3d81385... Roundend report refactor (#33246) - to_chat(world, text) - return 1 //returns whether the mob is a wizard (or apprentice) /proc/iswizard(mob/living/M) return M.mind && M.mind.has_antag_datum(/datum/antagonist/wizard,TRUE) diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm index fdb481401e..59465cf5b2 100644 --- a/code/game/machinery/wishgranter.dm +++ b/code/game/machinery/wishgranter.dm @@ -45,6 +45,7 @@ var/datum/objective/hijack/hijack = new hijack.owner = user.mind user.mind.objectives += hijack + user.mind.add_antag_datum(/datum/antagonist/auto_custom) user.mind.announce_objectives() diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 22365c4584..c0859cc318 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -705,15 +705,17 @@ /datum/admins/proc/output_all_devil_info() var/devil_number = 0 - for(var/D in SSticker.mode.devils) + for(var/datum/mind/D in SSticker.mode.devils) devil_number++ - to_chat(usr, "Devil #[devil_number]:

" + SSticker.mode.printdevilinfo(D)) + var/datum/antagonist/devil/devil = D.has_antag_datum(/datum/antagonist/devil) + to_chat(usr, "Devil #[devil_number]:

" + devil.printdevilinfo()) if(!devil_number) to_chat(usr, "No Devils located" ) /datum/admins/proc/output_devil_info(mob/living/M) if(is_devil(M)) - to_chat(usr, SSticker.mode.printdevilinfo(M)) + var/datum/antagonist/devil/devil = M.mind.has_antag_datum(/datum/antagonist/devil) + to_chat(usr, devil.printdevilinfo()) else to_chat(usr, "[M] is not a devil.") diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 8a18dc9ac5..75e43adf51 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -317,11 +317,14 @@ //Assign antag status and the mission SSticker.mode.traitors += Commando.mind Commando.mind.special_role = "deathsquad" + var/datum/objective/missionobj = new missionobj.owner = Commando.mind missionobj.explanation_text = mission missionobj.completed = 1 Commando.mind.objectives += missionobj + + Commando.mind.add_antag_datum(/datum/antagonist/auto_custom) //Greet the commando to_chat(Commando, "You are the [numagents==1?"Deathsquad Officer":"Death Commando"].") @@ -369,11 +372,14 @@ //Assign antag status and the mission SSticker.mode.traitors += newmob.mind newmob.mind.special_role = "official" + var/datum/objective/missionobj = new missionobj.owner = newmob.mind missionobj.explanation_text = mission missionobj.completed = 1 newmob.mind.objectives += missionobj + + newmob.mind.add_antag_datum(/datum/antagonist/auto_custom) if(CONFIG_GET(flag/enforce_human_authority)) newmob.set_species(/datum/species/human) @@ -474,12 +480,15 @@ //Assign antag status and the mission SSticker.mode.traitors += ERTOperative.mind ERTOperative.mind.special_role = "ERT" + var/datum/objective/missionobj = new missionobj.owner = ERTOperative.mind missionobj.explanation_text = mission missionobj.completed = 1 ERTOperative.mind.objectives += missionobj + ERTOperative.mind.add_antag_datum(/datum/antagonist/auto_custom) + //Greet the commando to_chat(ERTOperative, "You are [numagents==1?"the Emergency Response Team Commander":"an Emergency Response Officer"].") var/missiondesc = "Your squad is being sent on a Code [alert] mission to [station_name()] by Nanotrasen's Security Division." diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm index b675815602..d09041aaf3 100644 --- a/code/modules/admin/verbs/onlyone.dm +++ b/code/modules/admin/verbs/onlyone.dm @@ -28,6 +28,7 @@ GLOBAL_VAR_INIT(highlander, FALSE) /mob/living/carbon/human/proc/make_scottish() SSticker.mode.traitors += mind mind.special_role = "highlander" + dna.species.species_traits |= NOGUNS //nice try jackass var/datum/objective/steal/steal_objective = new @@ -40,6 +41,8 @@ GLOBAL_VAR_INIT(highlander, FALSE) hijack_objective.owner = mind mind.objectives += hijack_objective + mind.add_antag_datum(/datum/antagonist/auto_custom) + mind.announce_objectives() for(var/obj/item/I in get_equipped_items()) diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm index 3031936d43..1fe8baba01 100644 --- a/code/modules/awaymissions/mission_code/wildwest.dm +++ b/code/modules/awaymissions/mission_code/wildwest.dm @@ -115,9 +115,11 @@ to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.") SSticker.mode.traitors += user.mind user.mind.special_role = "traitor" + var/datum/objective/hijack/hijack = new hijack.owner = user.mind user.mind.objectives += hijack + user.mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(user, "Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!") user.mind.announce_objectives() user.set_species(/datum/species/shadow) diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index dbbe6ea512..a7e3b20e7a 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -68,3 +68,9 @@ var/datum/chatOutput/chatOutput +<<<<<<< HEAD +======= + var/list/credits //lazy list of all credit object bound to this client + + var/datum/player_details/player_details //these persist between logins/logouts during the same round. +>>>>>>> 3d81385... Roundend report refactor (#33246) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 43ae694b84..fc00ae3828 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -222,6 +222,13 @@ GLOBAL_LIST(external_rsc_urls) message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(C)] (no longer logged in). ") log_access("Notice: [key_name(src)] has the same [matches] as [key_name(C)] (no longer logged in).") + if(GLOB.player_details[ckey]) + player_details = GLOB.player_details[ckey] + else + player_details = new + GLOB.player_details[ckey] = player_details + + . = ..() //calls mob.Login() chatOutput.start() // Starts the chat diff --git a/code/modules/client/player_details.dm b/code/modules/client/player_details.dm new file mode 100644 index 0000000000..a842607235 --- /dev/null +++ b/code/modules/client/player_details.dm @@ -0,0 +1,2 @@ +/datum/player_details + var/list/player_actions = list() \ No newline at end of file diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm index f983ca2563..7ec7d75bac 100644 --- a/code/modules/clothing/under/accessories.dm +++ b/code/modules/clothing/under/accessories.dm @@ -135,7 +135,7 @@ "You pin \the [src] on [M]'s chest.") if(input) SSblackbox.record_feedback("associative", "commendation", 1, list("commender" = "[user.real_name]", "commendee" = "[M.real_name]", "medal" = "[src]", "reason" = input)) - GLOB.commendations += "[user.real_name] awarded [M.real_name] the [name]! \n- [input]" + GLOB.commendations += "[user.real_name] awarded [M.real_name] the [name]! \n- [input]" commended = TRUE log_game("[key_name(M)] was given the following commendation by [key_name(user)]: [input]") message_admins("[key_name(M)] was given the following commendation by [key_name(user)]: [input]") diff --git a/code/modules/events/holiday/vday.dm b/code/modules/events/holiday/vday.dm index 41ff90407d..abb5a0639d 100644 --- a/code/modules/events/holiday/vday.dm +++ b/code/modules/events/holiday/vday.dm @@ -45,19 +45,26 @@ to_chat(L, "You didn't get a date! They're all having fun without you! you'll show them though...") var/datum/objective/martyr/normiesgetout = new normiesgetout.owner = L.mind + L.mind.special_role = "heartbreaker" SSticker.mode.traitors |= L.mind L.mind.objectives += normiesgetout + L.mind.add_antag_datum(/datum/antagonist/auto_custom) + /proc/forge_valentines_objective(mob/living/lover,mob/living/date) SSticker.mode.traitors |= lover.mind lover.mind.special_role = "valentine" + var/datum/objective/protect/protect_objective = new /datum/objective/protect protect_objective.owner = lover.mind protect_objective.target = date.mind protect_objective.explanation_text = "Protect [date.real_name], your date." lover.mind.objectives += protect_objective + + lover.mind.add_antag_datum(/datum/antagonist/auto_custom) + to_chat(lover, "You're on a date with [date]! Protect them at all costs. This takes priority over all other loyalties.") diff --git a/code/modules/events/nightmare.dm b/code/modules/events/nightmare.dm index 073ef8aea3..76188cb5b7 100644 --- a/code/modules/events/nightmare.dm +++ b/code/modules/events/nightmare.dm @@ -35,6 +35,7 @@ player_mind.assigned_role = "Nightmare" player_mind.special_role = "Nightmare" SSticker.mode.traitors += player_mind + player_mind.add_antag_datum(/datum/antagonist/auto_custom) S.set_species(/datum/species/shadow/nightmare) playsound(S, 'sound/magic/ethereal_exit.ogg', 50, 1, -1) message_admins("[key_name_admin(S)] has been made into a Nightmare by an event.") diff --git a/code/modules/events/wizard/departmentrevolt.dm b/code/modules/events/wizard/departmentrevolt.dm index 618c746a65..3227f81d58 100644 --- a/code/modules/events/wizard/departmentrevolt.dm +++ b/code/modules/events/wizard/departmentrevolt.dm @@ -44,6 +44,7 @@ citizens += H SSticker.mode.traitors += M M.special_role = "separatist" + M.add_antag_datum(/datum/antagonist/auto_custom) H.log_message("Was made into a separatist, long live [nation]!", INDIVIDUAL_ATTACK_LOG) to_chat(H, "You are a separatist! [nation] forever! Protect the sovereignty of your newfound land with your comrades in arms!") if(citizens.len) diff --git a/code/modules/events/wizard/greentext.dm b/code/modules/events/wizard/greentext.dm index 6ee000249b..1cf4858ce7 100644 --- a/code/modules/events/wizard/greentext.dm +++ b/code/modules/events/wizard/greentext.dm @@ -67,6 +67,7 @@ O.completed = 1 //YES! O.owner = new_holder.mind new_holder.mind.objectives += O + new_holder.mind.add_antag_datum(/datum/antagonist/auto_custom) new_holder.log_message("Won with greentext!!!", INDIVIDUAL_ATTACK_LOG) color_altered_mobs -= new_holder resistance_flags |= ON_FIRE diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index aab1f204f6..d09f8cd4a2 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -50,6 +50,7 @@ if(!mind.special_role) mind.special_role = "traitor" SSticker.mode.traitors += mind + mind.add_antag_datum(/datum/antagonist/auto_custom) // ???? /mob/living/silicon/robot/update_health_hud() diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 0e6ecf1672..8046daf55d 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -360,8 +360,14 @@ ..() /datum/action/innate/seek_master/Activate() - if(!SSticker.mode.eldergod) - the_construct.master = GLOB.blood_target + var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult) + if(!C) + return + var/datum/objective/eldergod/summon_objective = locate() in C.cult_team.objectives + + if(summon_objective.check_completion()) + the_construct.master = C.cult_team.blood_target + if(!the_construct.master) to_chat(the_construct, "You have no master to seek!") the_construct.seeking = FALSE diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm index 3aa1153133..65ef28baee 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm @@ -153,7 +153,7 @@ /mob/living/simple_animal/drone/cogscarab/Login() ..() - add_servant_of_ratvar(src, TRUE) + add_servant_of_ratvar(src, TRUE, GLOB.servants_active) to_chat(src,"You yourself are one of these servants, and will be able to utilize almost anything they can[GLOB.ratvar_awakens ? "":", excluding a clockwork slab"].") // this can't go with flavortext because i'm assuming it requires them to be ratvar'd /mob/living/simple_animal/drone/cogscarab/binarycheck() diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index e7608f524b..5a10b3183b 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -48,6 +48,10 @@ client.change_view(CONFIG_GET(string/default_view)) // Resets the client.view in case it was changed. + if(client.player_details.player_actions.len) + for(var/datum/action/A in client.player_details.player_actions) + A.Grant(src) + if(!GLOB.individual_log_list[ckey]) GLOB.individual_log_list[ckey] = logging else diff --git a/code/modules/ninja/ninja_event.dm b/code/modules/ninja/ninja_event.dm index 1656a43505..b26d01d880 100644 --- a/code/modules/ninja/ninja_event.dm +++ b/code/modules/ninja/ninja_event.dm @@ -95,7 +95,7 @@ Contents: var/datum/mind/Mind = new /datum/mind(key) Mind.assigned_role = "Space Ninja" Mind.special_role = "Space Ninja" - SSticker.mode.traitors |= Mind //Adds them to current traitor list. Which is really the extra antagonist list. + SSticker.mode.traitors |= Mind //Adds them to current traitor list. TODO : Remove this in admin tools refeactor. return Mind diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 22712e970d..9801e98614 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -47,8 +47,15 @@ /obj/singularity/narsie/large/cult/Initialize() . = ..() GLOB.cult_narsie = src - deltimer(GLOB.blood_target_reset_timer) - GLOB.blood_target = src + var/list/all_cults = list() + for(var/datum/antagonist/cult/C in GLOB.antagonists) + all_cults |= C.cult_team + for(var/datum/objective_team/cult/T in all_cults) + deltimer(T.blood_target_reset_timer) + T.blood_target = src + var/datum/objective/eldergod/summon_objective = locate() in T.objectives + if(summon_objective) + summon_objective.summoned = TRUE for(var/datum/mind/cult_mind in SSticker.mode.cult) if(isliving(cult_mind.current)) var/mob/living/L = cult_mind.current diff --git a/code/modules/spells/spell_types/rightandwrong.dm b/code/modules/spells/spell_types/rightandwrong.dm index b992871004..7ab3121a3a 100644 --- a/code/modules/spells/spell_types/rightandwrong.dm +++ b/code/modules/spells/spell_types/rightandwrong.dm @@ -22,12 +22,14 @@ guns.owner = H.mind H.mind.objectives += guns H.mind.special_role = "survivalist" + H.mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(H, "You are the survivalist! Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, by any means necessary. Kill anyone who gets in your way.") else var/datum/objective/steal_five_of_type/summon_magic/magic = new magic.owner = H.mind H.mind.objectives += magic H.mind.special_role = "amateur magician" + H.mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(H, "You are the amateur magician! Grow your newfound talent! Grab as many magical artefacts as possible, by any means necessary. Kill anyone who gets in your way.") var/datum/objective/survive/survive = new survive.owner = H.mind diff --git a/code/modules/station_goals/station_goal.dm b/code/modules/station_goals/station_goal.dm index 98ec01f641..88377455c6 100644 --- a/code/modules/station_goals/station_goal.dm +++ b/code/modules/station_goals/station_goal.dm @@ -26,11 +26,11 @@ /datum/station_goal/proc/check_completion() return completed -/datum/station_goal/proc/print_result() +/datum/station_goal/proc/get_result() if(check_completion()) - to_chat(world, "Station Goal : [name] : Completed!") + return "
  • [name] : Completed!
  • " else - to_chat(world, "Station Goal : [name] : Failed!") + return "
  • [name] : Failed!
  • " /datum/station_goal/Destroy() SSticker.mode.station_goals -= src diff --git a/html/browser/roundend.css b/html/browser/roundend.css new file mode 100644 index 0000000000..82235f1273 --- /dev/null +++ b/html/browser/roundend.css @@ -0,0 +1,67 @@ +.greentext { + color: #90ee90; + font-weight: bold; +} + +.greentext_alt { + color: green; +} +.redtext { + color: #ef2f3c; + font-weight: bold; +} +.neutraltext { + font-weight: bold; /* If you feel these should have some color feel free to change */ +} + +.marooned { + color: rgb(109, 109, 255); font-weight: bold; +} + +.header { + font-size: 24px; font-weight: bold; +} + +.big { + font-size: 24px; +} + +.medaltext { + color: #add8e6; +} + +.codephrase { + color : #ef2f3c; +} + +.redborder { + border-bottom: 2px solid #ef2f3c; +} + +.greenborder { + border-bottom: 2px solid #90ee90; +} + +.clockborder { + border-bottom: 2px solid #B18B25; +} + +.stationborder { + border-bottom: 2px solid #add8e6; +} + +li { + margin-bottom: 0.2rem; +} + +.panel { + background-color: #313131; + padding: 10px; + border-radius: 10px; + margin-bottom: 5px; +} + +body { + background-color: #272727; + color: #efefef; +} \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index 79e277a91b..44c5e2dd93 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -107,6 +107,7 @@ #include "code\__HELPERS\pronouns.dm" #include "code\__HELPERS\radiation.dm" #include "code\__HELPERS\radio.dm" +#include "code\__HELPERS\roundend.dm" #include "code\__HELPERS\sanitize_values.dm" #include "code\__HELPERS\shell.dm" #include "code\__HELPERS\stat_tracking.dm" @@ -1301,6 +1302,7 @@ #include "code\modules\client\client_colour.dm" #include "code\modules\client\client_defines.dm" #include "code\modules\client\client_procs.dm" +#include "code\modules\client\player_details.dm" #include "code\modules\client\message.dm" #include "code\modules\client\preferences.dm" #include "code\modules\client\preferences_savefile.dm" From 4727d8f73ca7743750b8f2573a99336ef91d394d Mon Sep 17 00:00:00 2001 From: Jordie Date: Sat, 16 Dec 2017 03:00:35 +1100 Subject: [PATCH 04/96] Fixes LoadEntries return value --- .../configuration/configuration.dm | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index e9c0aa71b8..095e60132c 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -22,8 +22,16 @@ GLOBAL_PROTECT(config_dir) config = src var/list/config_files = InitEntries() LoadModes() +<<<<<<< HEAD for(var/I in config_files) LoadEntries(I) +======= + if(LoadEntries("config.txt") <= 1) + log_config("No $include directives found in config.txt! Loading legacy game_options/dbconfig/comms files...") + LoadEntries("game_options.txt") + LoadEntries("dbconfig.txt") + LoadEntries("comms.txt") +>>>>>>> 5cf2c42... Merge pull request #33562 from tgstation/Cyberboss-patch-1 loadmaplist(CONFIG_MAPS_FILE) /datum/controller/configuration/Destroy() @@ -91,6 +99,17 @@ GLOBAL_PROTECT(config_dir) if(!entry) continue +<<<<<<< HEAD +======= + if(entry == "$include") + if(!value) + log_config("Warning: Invalid $include directive: [value]") + else + LoadEntries(value, stack) + ++. + continue + +>>>>>>> 5cf2c42... Merge pull request #33562 from tgstation/Cyberboss-patch-1 var/datum/config_entry/E = _entries[entry] if(!E) log_config("Unknown setting in configuration: '[entry]'") @@ -111,6 +130,11 @@ GLOBAL_PROTECT(config_dir) if(validated) E.modified = TRUE +<<<<<<< HEAD +======= + + ++. +>>>>>>> 5cf2c42... Merge pull request #33562 from tgstation/Cyberboss-patch-1 /datum/controller/configuration/can_vv_get(var_name) return (var_name != "entries_by_type" || !hiding_entries_by_type) && ..() From 0a4c557336dd41e79565c600949c2b633eaedee5 Mon Sep 17 00:00:00 2001 From: Jordie Date: Sun, 17 Dec 2017 15:23:23 +1100 Subject: [PATCH 05/96] Db schema version check by simplification (#33582) * db schema version check by concatenation * lets just use actual floats * simplifies schema check and some more logging --- code/game/world.dm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/game/world.dm b/code/game/world.dm index 2853bb2ef6..6c49e37456 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -62,15 +62,15 @@ GLOBAL_PROTECT(security_mode) var/db_major = text2num(query_db_version.item[1]) var/db_minor = text2num(query_db_version.item[2]) if(db_major != DB_MAJOR_VERSION || db_minor != DB_MINOR_VERSION) - var/which = "behind" - if(db_major < DB_MAJOR_VERSION || db_minor < DB_MINOR_VERSION) - which = "ahead of" - message_admins("Database schema ([db_major].[db_minor]) is [which] the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") - log_sql("Database schema ([db_major].[db_minor]) is [which] the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") + message_admins("Database schema ([db_major].[db_minor]) doesn't match the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") + log_sql("Database schema ([db_major].[db_minor]) doesn't match the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") else message_admins("Could not get schema version from database") + log_sql("Could not get schema version from database") else - log_world("Your server failed to establish a connection with the database.") + log_sql("Your server failed to establish a connection with the database.") + else + log_sql("Database is not enabled in configuration.") /world/proc/SetRoundID() if(CONFIG_GET(flag/sql_enabled)) From d919eae075322679439c6c68245b7a41933bb658 Mon Sep 17 00:00:00 2001 From: oranges Date: Sun, 17 Dec 2017 17:09:13 +1300 Subject: [PATCH 07/96] add view range respects widescreen (#33581) It will simply increment the x and y independently This prevents a runtime of trying to add a number to a string --- code/modules/client/client_procs.dm | 7 +++++++ code/modules/mob/dead/observer/observer.dm | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index cb1712dff5..6c11a6d10a 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -673,6 +673,13 @@ GLOBAL_LIST(external_rsc_urls) return TRUE . = ..() +/client/proc/rescale_view(change, min, max) + var/viewscale = getviewsize(view) + var/x = viewscale[1] + var/y = viewscale[2] + x = Clamp(x+change, min, max) + y = Clamp(y+change, min,max) + change_view("[x]x[y]") /client/proc/change_view(new_size) if (isnull(new_size)) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index d19f3d4bf8..4ae841cfa5 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -471,7 +471,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set hidden = TRUE var/max_view = client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT if(input) - client.change_view(Clamp(client.view + input, 7, max_view)) + client.rescale_view(input, 7, max_view) /mob/dead/observer/verb/boo() set category = "Ghost" From cde0266c992eae2da24f2e35961e42f51332177a Mon Sep 17 00:00:00 2001 From: Ashe Higgs Date: Sat, 16 Dec 2017 12:35:13 -0500 Subject: [PATCH 09/96] Removes the visible messages from vitality matrices (#33549) --- code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm index e5a8c9b6f3..920f69cbd5 100644 --- a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm +++ b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm @@ -275,7 +275,6 @@ /obj/effect/clockwork/sigil/vitality/sigil_effects(mob/living/L) if((is_servant_of_ratvar(L) && L.suiciding) || sigil_active) return - visible_message("[src] begins to glow bright blue!") animate(src, alpha = 255, time = 10, flags = ANIMATION_END_NOW) //we may have a previous animation going. finish it first, then do this one without delay. sleep(10) //as long as they're still on the sigil and are either not a servant or they're a servant AND it has remaining vitality @@ -355,5 +354,4 @@ if(sigil_active) animation_number = initial(animation_number) sigil_active = FALSE - visible_message("[src] slowly stops glowing!") animate(src, alpha = initial(alpha), time = 10, flags = ANIMATION_END_NOW) From 3b1c537bb42dd5287a6dca81ee2a88a9d4608454 Mon Sep 17 00:00:00 2001 From: Evsey Antonovich Date: Sun, 17 Dec 2017 22:30:06 +0500 Subject: [PATCH 11/96] changes one letter (#33591) --- code/game/objects/structures/mirror.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 711f9baf0b..44c12a21a1 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -89,7 +89,7 @@ name = "magic mirror" desc = "Turn and face the strange... face." icon_state = "magic_mirror" - var/list/races_blacklist = list("skeleton", "agent", "angel", "military_synth", "memezombie") + var/list/races_blacklist = list("skeleton", "agent", "angel", "military_synth", "memezombies") var/list/choosable_races = list() /obj/structure/mirror/magic/New() From 26543ea97f601c5d9b531be300ef4ddb473207dd Mon Sep 17 00:00:00 2001 From: LetterJay Date: Sun, 17 Dec 2017 17:50:43 -0600 Subject: [PATCH 13/96] Update configuration.dm --- code/controllers/configuration/configuration.dm | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 095e60132c..ef855c854a 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -22,16 +22,11 @@ GLOBAL_PROTECT(config_dir) config = src var/list/config_files = InitEntries() LoadModes() -<<<<<<< HEAD - for(var/I in config_files) - LoadEntries(I) -======= if(LoadEntries("config.txt") <= 1) log_config("No $include directives found in config.txt! Loading legacy game_options/dbconfig/comms files...") LoadEntries("game_options.txt") LoadEntries("dbconfig.txt") LoadEntries("comms.txt") ->>>>>>> 5cf2c42... Merge pull request #33562 from tgstation/Cyberboss-patch-1 loadmaplist(CONFIG_MAPS_FILE) /datum/controller/configuration/Destroy() @@ -98,9 +93,6 @@ GLOBAL_PROTECT(config_dir) if(!entry) continue - -<<<<<<< HEAD -======= if(entry == "$include") if(!value) log_config("Warning: Invalid $include directive: [value]") @@ -109,7 +101,6 @@ GLOBAL_PROTECT(config_dir) ++. continue ->>>>>>> 5cf2c42... Merge pull request #33562 from tgstation/Cyberboss-patch-1 var/datum/config_entry/E = _entries[entry] if(!E) log_config("Unknown setting in configuration: '[entry]'") @@ -130,11 +121,8 @@ GLOBAL_PROTECT(config_dir) if(validated) E.modified = TRUE -<<<<<<< HEAD -======= ++. ->>>>>>> 5cf2c42... Merge pull request #33562 from tgstation/Cyberboss-patch-1 /datum/controller/configuration/can_vv_get(var_name) return (var_name != "entries_by_type" || !hiding_entries_by_type) && ..() From e02611504547fd03b97a19f52edda59cfcac3730 Mon Sep 17 00:00:00 2001 From: Emmett Gaines Date: Sun, 17 Dec 2017 21:49:15 -0500 Subject: [PATCH 14/96] Decal rotation fix --- code/datums/components/decal.dm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm index a28213b0b5..4a4087d37e 100644 --- a/code/datums/components/decal.dm +++ b/code/datums/components/decal.dm @@ -48,8 +48,12 @@ if(old_dir == new_dir) return remove() +<<<<<<< HEAD var/rotation = SimplifyDegrees(dir2angle(new_dir)-dir2angle(old_dir)) pic.dir = turn(pic.dir, rotation) +======= + pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir)) +>>>>>>> 3ce9bd7... decal rotation fix (#33614) apply() /datum/component/decal/proc/clean_react(strength) From ed91ccdeff967d7cd948a630bd942fbdd98c3551 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 18 Dec 2017 15:14:55 -0600 Subject: [PATCH 15/96] Update decal.dm --- code/datums/components/decal.dm | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm index 4a4087d37e..a79de32898 100644 --- a/code/datums/components/decal.dm +++ b/code/datums/components/decal.dm @@ -48,12 +48,7 @@ if(old_dir == new_dir) return remove() -<<<<<<< HEAD - var/rotation = SimplifyDegrees(dir2angle(new_dir)-dir2angle(old_dir)) - pic.dir = turn(pic.dir, rotation) -======= pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir)) ->>>>>>> 3ce9bd7... decal rotation fix (#33614) apply() /datum/component/decal/proc/clean_react(strength) @@ -61,4 +56,4 @@ qdel(src) /datum/component/decal/proc/examine(mob/user) - to_chat(user, description) \ No newline at end of file + to_chat(user, description) From 4840a9c4189ea1e64e615a4a6ba6672e28f1af04 Mon Sep 17 00:00:00 2001 From: coiax Date: Tue, 19 Dec 2017 03:18:01 +0000 Subject: [PATCH 16/96] Codespeak manual rebalance/recost (#33638) :cl: coiax balance: The codespeak manual now has unlimited uses and costs 3 TC. fix: Nuke ops can now purchase the codespeak manual, as was intended. /:cl: It's an item that's just used for communication security, and also light memeing, so I'll make it cheaper. Also fixes a bug where I didn't specify the item path for the nuke ops version, so they couldn't buy it. --- code/modules/uplink/uplink_items.dm | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index d28adebe4b..ebff0fdbeb 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -1096,16 +1096,9 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. /datum/uplink_item/device_tools/codespeak_manual name = "Codespeak Manual" - desc = "Syndicate agents can be trained to use a series of codewords to convey 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/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 convey 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) + desc = "Syndicate agents can be trained to use a series of codewords to convey 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 used." + item = /obj/item/codespeak_manual/unlimited + cost = 3 // Implants /datum/uplink_item/implants From 6e50713dba56a277940579051de23cd61968c25a Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Mon, 18 Dec 2017 22:25:08 -0500 Subject: [PATCH 18/96] Fixes config entries in the changelog having no icon --- html/changelog.css | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/html/changelog.css b/html/changelog.css index 031c1e42c0..ab993f8364 100644 --- a/html/changelog.css +++ b/html/changelog.css @@ -1,3 +1,4 @@ +<<<<<<< HEAD .top{font-family:Tahoma,sans-serif;font-size:12px;} h2{font-family:Tahoma,sans-serif;} a img {border:none;} @@ -38,4 +39,47 @@ a img {border:none;} .indrop img {margin-right:5px;vertical-align:middle;} .closed {background:url(chevron-expand.png) right center no-repeat;} .open {background:url(chevron.png) right center no-repeat;} -.lic {font-size:9px;} \ No newline at end of file +.lic {font-size:9px;} +======= +.top{font-family:Tahoma,sans-serif;font-size:12px;} +h2{font-family:Tahoma,sans-serif;} +a img {border:none;} +.bgimages16 li { + padding:2px 10px 2px 30px; + background-position:6px center; + background-repeat:no-repeat; + border:1px solid #ddd; + border-left:4px solid #999; + margin-bottom:2px; +} +.bugfix {background-image:url(bug-minus.png)} +.wip {background-image:url(hard-hat-exclamation.png)} +.tweak {background-image:url(wrench-screwdriver.png)} +.soundadd {background-image:url(music-plus.png)} +.sounddel {background-image:url(music-minus.png)} +.rscdel {background-image:url(cross-circle.png)} +.rscadd {background-image:url(tick-circle.png)} +.imageadd {background-image:url(image-plus.png)} +.imagedel {background-image:url(image-minus.png)} +.spellcheck {background-image:url(spell-check.png)} +.experiment {background-image:url(burn-exclamation.png)} +.refactor {background-image:url(burn-exclamation.png)} +.code_imp {background-image:url(coding.png)} +.config {background-image:url(chrome-wrench.png)} +.admin {background-image:url(ban.png)} +.server {background-image:url(hard-hat-exclamation.png)} +.balance {background-image:url(scales.png)} +.sansserif {font-family:Tahoma,sans-serif;font-size:12px;} +.commit {margin-bottom:20px;font-size:100%;font-weight:normal;} +.changes {list-style:none;margin:5px 0;padding:0 0 0 25px;font-size:0.8em;} +.date {margin:10px 0;color:blue;border-bottom:2px solid #00f;width:60%;padding:2px 0;font-size:1em;font-weight:bold;} +.author {padding-left:10px;margin:0;font-weight:bold;font-size:0.9em;} +.drop {cursor:pointer;border:1px solid #999;display:inline;font-size:0.9em;padding:1px 20px 1px 5px;line-height:16px;} +.hidden {display:none;} +.indrop {margin:2px 0 0 0;clear:both;background:#fff;border:1px solid #ddd;padding:5px 10px;} +.indrop p {margin:0;font-size:0.8em;line-height:16px;margin:1px 0;} +.indrop img {margin-right:5px;vertical-align:middle;} +.closed {background:url(chevron-expand.png) right center no-repeat;} +.open {background:url(chevron.png) right center no-repeat;} +.lic {font-size:9px;} +>>>>>>> 2c96cc9... Fixes config entries in the changelog having no icon (#33625) From 522b8383d8addd4f1503768b7d0ad92f1fe4a53b Mon Sep 17 00:00:00 2001 From: ACCount Date: Tue, 19 Dec 2017 07:55:01 +0300 Subject: [PATCH 19/96] [READY]Refactors reagent container types --- code/__DEFINES/reagents.dm | 41 ++- code/game/atoms.dm | 60 +-- code/game/machinery/limbgrower.dm | 2 +- code/game/objects/items/cigs_lighters.dm | 4 +- code/game/objects/items/extinguisher.dm | 7 +- .../objects/items/implants/implant_chem.dm | 2 +- code/game/objects/items/tanks/watertank.dm | 4 +- code/game/objects/items/tools/weldingtool.dm | 347 ++++++++++++++++++ code/game/objects/structures/janicart.dm | 2 +- code/game/objects/structures/mop_bucket.dm | 20 + code/game/objects/structures/watercloset.dm | 6 +- code/modules/crafting/craft.dm | 2 +- .../detectivework/footprints_and_rag.dm | 2 +- code/modules/food_and_drinks/drinks/drinks.dm | 51 +-- code/modules/food_and_drinks/food.dm | 2 +- .../modules/food_and_drinks/food/condiment.dm | 6 +- .../food_and_drinks/food/customizables.dm | 2 +- code/modules/food_and_drinks/food/snacks.dm | 2 +- .../kitchen_machinery/deep_fryer.dm | 2 +- .../kitchen_machinery/food_cart.dm | 4 +- .../kitchen_machinery/icecream_vat.dm | 4 +- .../kitchen_machinery/microwave.dm | 6 +- code/modules/hydroponics/hydroitemdefines.dm | 12 - code/modules/hydroponics/hydroponics.dm | 4 +- .../integrated_electronics/passive/power.dm | 2 +- .../subtypes/reagents.dm | 23 +- code/modules/mob/living/living.dm | 9 +- code/modules/paperwork/pen.dm | 2 +- .../projectiles/ammunition/ammo_casings.dm | 6 + .../projectiles/guns/energy/special.dm | 1 - code/modules/reagents/chemistry/holder.dm | 13 + .../chemistry/machinery/chem_dispenser.dm | 2 +- .../chemistry/machinery/chem_heater.dm | 2 +- .../chemistry/machinery/chem_master.dm | 2 +- .../reagents/chemistry/machinery/pandemic.dm | 2 +- .../chemistry/machinery/reagentgrinder.dm | 2 +- code/modules/reagents/reagent_containers.dm | 13 +- .../reagents/reagent_containers/borghydro.dm | 2 +- .../reagents/reagent_containers/dropper.dm | 2 +- .../reagents/reagent_containers/glass.dm | 40 +- .../reagents/reagent_containers/hypospray.dm | 4 +- .../reagents/reagent_containers/pill.dm | 11 +- .../reagents/reagent_containers/spray.dm | 16 +- .../reagents/reagent_containers/syringes.dm | 9 +- code/modules/reagents/reagent_dispenser.dm | 12 +- code/modules/research/circuitprinter.dm | 2 +- .../departmental_circuit_imprinter.dm | 2 +- code/modules/research/departmental_lathe.dm | 2 +- code/modules/research/protolathe.dm | 2 +- code/modules/research/rdmachines.dm | 2 +- .../research/xenobiology/xenobiology.dm | 2 +- 51 files changed, 577 insertions(+), 204 deletions(-) diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index c85365db90..d9e6225eb7 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -1,19 +1,30 @@ -#define SOLID 1 -#define LIQUID 2 -#define GAS 3 +#define SOLID 1 +#define LIQUID 2 +#define GAS 3 -#define INJECTABLE_1 1024 //Makes reagents addable through droppers and syringes -#define DRAWABLE_1 2048 //If a syringe can draw from it -#define OPENCONTAINER_1 4096 //Is an open container for chemistry purposes -#define TRANSPARENT_1 8192 //Used for non-open containers which you still want to be able to see the reagents off. -#define TOUCH 1 //splashing -#define INGEST 2 //ingestion -#define VAPOR 3 //foam, spray, blob attack -#define PATCH 4 //patches -#define INJECT 5 //injection +// container_type defines +#define INJECTABLE 1 // Makes it possible to add reagents through droppers and syringes. +#define DRAWABLE 2 // Makes it possible to remove reagents through syringes. + +#define REFILLABLE 4 // Makes it possible to add reagents through any reagent container. +#define DRAINABLE 8 // Makes it possible to remove reagents through any reagent container. + +#define TRANSPARENT 16 // Used on containers which you want to be able to see the reagents off. +#define AMOUNT_VISIBLE 32 // For non-transparent containers that still have the general amount of reagents in them visible. + +// Is an open container for all intents and purposes. +#define OPENCONTAINER REFILLABLE | DRAINABLE | TRANSPARENT + + +#define TOUCH 1 // splashing +#define INGEST 2 // ingestion +#define VAPOR 3 // foam, spray, blob attack +#define PATCH 4 // patches +#define INJECT 5 // injection + //defines passed through to the on_reagent_change proc -#define DEL_REAGENT 1 //reagent deleted (fully cleared) -#define ADD_REAGENT 2 // reagent added -#define REM_REAGENT 3 // reagent removed (may still exist) +#define DEL_REAGENT 1 // reagent deleted (fully cleared) +#define ADD_REAGENT 2 // reagent added +#define REM_REAGENT 3 // reagent removed (may still exist) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index b7d377fb61..211f9dea59 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -194,27 +194,22 @@ set waitfor = FALSE return -// Convenience proc to see if a container is open for chemistry handling -// returns true if open -// false if closed +// Convenience procs to see if a container is open for chemistry handling /atom/proc/is_open_container() - return container_type & OPENCONTAINER_1 - -/atom/proc/is_transparent() - return container_type & TRANSPARENT_1 + return is_refillable() && is_drainable() /atom/proc/is_injectable(allowmobs = TRUE) - if(isliving(src) && allowmobs) - var/mob/living/L = src - return L.can_inject() - if(container_type & OPENCONTAINER_1) - return TRUE - return container_type & INJECTABLE_1 + return reagents && (container_type & (INJECTABLE | REFILLABLE)) /atom/proc/is_drawable(allowmobs = TRUE) - if(is_injectable(allowmobs)) //Everything that can be injected can also be drawn from, but not vice versa - return TRUE - return container_type & DRAWABLE_1 + return reagents && (container_type & (DRAWABLE | DRAINABLE)) + +/atom/proc/is_refillable() + return reagents && (container_type & REFILLABLE) + +/atom/proc/is_drainable() + return reagents && (container_type & DRAINABLE) + /atom/proc/AllowDrop() return FALSE @@ -256,19 +251,26 @@ if(desc) to_chat(user, desc) - if(reagents && (is_open_container() || is_transparent())) //is_open_container() isn't really the right proc for this, but w/e - to_chat(user, "It contains:") - if(reagents.reagent_list.len) - if(user.can_see_reagents()) //Show each individual reagent - for(var/datum/reagent/R in reagents.reagent_list) - to_chat(user, "[R.volume] units of [R.name]") - else //Otherwise, just show the total volume - var/total_volume = 0 - for(var/datum/reagent/R in reagents.reagent_list) - total_volume += R.volume - to_chat(user, "[total_volume] units of various reagents") - else - to_chat(user, "Nothing.") + if(reagents) + if(container_type & TRANSPARENT) + to_chat(user, "It contains:") + if(reagents.reagent_list.len) + if(user.can_see_reagents()) //Show each individual reagent + for(var/datum/reagent/R in reagents.reagent_list) + to_chat(user, "[R.volume] units of [R.name]") + else //Otherwise, just show the total volume + var/total_volume = 0 + for(var/datum/reagent/R in reagents.reagent_list) + total_volume += R.volume + to_chat(user, "[total_volume] units of various reagents") + else + to_chat(user, "Nothing.") + else if(container_type & AMOUNT_VISIBLE) + if(reagents.total_volume) + to_chat(user, "It has [reagents.total_volume] unit\s left.") + else + to_chat(user, "It's empty.") + SendSignal(COMSIG_PARENT_EXAMINE, user) /atom/proc/relaymove(mob/user) diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm index 47fee66b9e..e661bc24c5 100644 --- a/code/game/machinery/limbgrower.dm +++ b/code/game/machinery/limbgrower.dm @@ -10,7 +10,7 @@ icon = 'icons/obj/machines/limbgrower.dmi' icon_state = "limbgrower_idleoff" density = TRUE - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER anchored = TRUE use_power = IDLE_POWER_USE idle_power_usage = 10 diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 9c7c34510c..ee0aa2c63c 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -102,7 +102,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM icon_state = "cigoff" throw_speed = 0.5 item_state = "cigoff" - container_type = INJECTABLE_1 + container_type = INJECTABLE w_class = WEIGHT_CLASS_TINY body_parts_covered = null grind_results = list() @@ -659,7 +659,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM item_state = "[param_color]_vape" /obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params) - if(istype(O, /obj/item/reagent_containers) && (O.container_type & OPENCONTAINER_1)) + if(O.is_drainable()) if(reagents.total_volume < chem_volume) if(O.reagents.total_volume > 0) O.reagents.trans_to(src,25) diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index d334d12193..5f582b9e15 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -16,6 +16,7 @@ attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed") dog_fashion = /datum/dog_fashion/back resistance_flags = FIRE_PROOF + container_type = AMOUNT_VISIBLE var/max_water = 50 var/last_use = 1 var/safety = TRUE @@ -48,7 +49,6 @@ /obj/item/extinguisher/attack_self(mob/user) safety = !safety src.icon_state = "[sprite_name][!safety]" - src.desc = "The safety is [safety ? "on" : "off"]." to_chat(user, "The safety is [safety ? "on" : "off"].") return @@ -67,11 +67,10 @@ /obj/item/extinguisher/examine(mob/user) ..() + to_chat(user, "The safety is [safety ? "on" : "off"].") + if(reagents.total_volume) - to_chat(user, "It contains [round(reagents.total_volume)] unit\s.") to_chat(user, "Alt-click to empty it.") - else - to_chat(user, "It is empty.") /obj/item/extinguisher/proc/AttemptRefill(atom/target, mob/user) if(istype(target, /obj/structure/reagent_dispensers/watertank) && target.Adjacent(user)) diff --git a/code/game/objects/items/implants/implant_chem.dm b/code/game/objects/items/implants/implant_chem.dm index 509784a699..e266f3ab09 100644 --- a/code/game/objects/items/implants/implant_chem.dm +++ b/code/game/objects/items/implants/implant_chem.dm @@ -2,7 +2,7 @@ name = "chem implant" desc = "Injects things." icon_state = "reagents" - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER /obj/item/implant/chem/get_data() var/dat = {"Implant Specifications:
    diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index fa7d14d572..8a3dc21dbe 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -114,7 +114,7 @@ possible_transfer_amounts = list(25,50,100) volume = 500 flags_1 = NOBLUDGEON_1 - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER slot_flags = 0 var/obj/item/watertank/tank @@ -351,7 +351,7 @@ var/usage_ratio = 5 //5 unit added per 1 removed var/injection_amount = 1 amount_per_transfer_from_this = 5 - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER spillable = FALSE possible_transfer_amounts = list(5,10,15) diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 1c20c95e93..a09f0d2a1a 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD #define WELDER_FUEL_BURN_INTERVAL 13 /obj/item/weldingtool name = "welding tool" @@ -336,4 +337,350 @@ if(get_fuel() < max_fuel && nextrefueltick < world.time) nextrefueltick = world.time + 10 reagents.add_reagent("welding_fuel", 1) +======= +#define WELDER_FUEL_BURN_INTERVAL 13 +/obj/item/weldingtool + name = "welding tool" + desc = "A standard edition welder provided by Nanotrasen." + icon = 'icons/obj/tools.dmi' + icon_state = "welder" + item_state = "welder" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 3 + throwforce = 5 + hitsound = "swing_hit" + usesound = 'sound/items/welder.ogg' + var/acti_sound = 'sound/items/welderactivate.ogg' + var/deac_sound = 'sound/items/welderdeactivate.ogg' + throw_speed = 3 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) + resistance_flags = FIRE_PROOF + + materials = list(MAT_METAL=70, MAT_GLASS=30) + var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) + var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) + var/max_fuel = 20 //The max amount of fuel the welder can hold + var/change_icons = 1 + var/can_off_process = 0 + var/light_intensity = 2 //how powerful the emitted light is when used. + var/burned_fuel_for = 0 //when fuel was last removed + heat = 3800 + toolspeed = 1 + +/obj/item/weldingtool/Initialize() + . = ..() + create_reagents(max_fuel) + reagents.add_reagent("welding_fuel", max_fuel) + update_icon() + + +/obj/item/weldingtool/proc/update_torch() + if(welding) + add_overlay("[initial(icon_state)]-on") + item_state = "[initial(item_state)]1" + else + item_state = "[initial(item_state)]" + + +/obj/item/weldingtool/update_icon() + cut_overlays() + if(change_icons) + var/ratio = get_fuel() / max_fuel + ratio = CEILING(ratio*4, 1) * 25 + add_overlay("[initial(icon_state)][ratio]") + update_torch() + return + + +/obj/item/weldingtool/process() + switch(welding) + if(0) + force = 3 + damtype = "brute" + update_icon() + if(!can_off_process) + STOP_PROCESSING(SSobj, src) + return + //Welders left on now use up fuel, but lets not have them run out quite that fast + if(1) + force = 15 + damtype = "fire" + ++burned_fuel_for + if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) + remove_fuel(1) + update_icon() + + //This is to start fires. process() is only called if the welder is on. + open_flame() + + +/obj/item/weldingtool/suicide_act(mob/user) + user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") + return (FIRELOSS) + + +/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/screwdriver)) + flamethrower_screwdriver(I, user) + else if(istype(I, /obj/item/stack/rods)) + flamethrower_rods(I, user) + else + . = ..() + update_icon() + +/obj/item/weldingtool/proc/explode() + var/turf/T = get_turf(loc) + var/plasmaAmount = reagents.get_reagent_amount("plasma") + dyn_explosion(T, plasmaAmount/5)//20 plasma in a standard welder has a 4 power explosion. no breaches, but enough to kill/dismember holder + qdel(src) + +/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) + if(!istype(H)) + return ..() + + var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) + + if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) + if(src.remove_fuel(1)) + playsound(loc, usesound, 50, 1) + if(user == H) + user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") + if(!do_mob(user, H, 50)) + return + item_heal_robotic(H, user, 15, 0) + else + return ..() + + +/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) + if(!proximity) + return + if(!status && O.is_refillable()) + reagents.trans_to(O, reagents.total_volume) + to_chat(user, "You empty [src]'s fuel tank into [O].") + update_icon() + if(welding) + remove_fuel(1) + var/turf/location = get_turf(user) + location.hotspot_expose(700, 50, 1) + if(get_fuel() <= 0) + set_light(0) + + if(isliving(O)) + var/mob/living/L = O + if(L.IgniteMob()) + message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") + log_game("[key_name(user)] set [key_name(L)] on fire") + + +/obj/item/weldingtool/attack_self(mob/user) + if(src.reagents.has_reagent("plasma")) + message_admins("[key_name_admin(user)] activated a rigged welder.") + explode() + switched_on(user) + if(welding) + set_light(light_intensity) + + update_icon() + + +//Returns the amount of fuel in the welder +/obj/item/weldingtool/proc/get_fuel() + return reagents.get_reagent_amount("welding_fuel") + + +//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() +/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) + if(!welding || !check_fuel()) + return 0 + if(amount) + burned_fuel_for = 0 + if(get_fuel() >= amount) + reagents.remove_reagent("welding_fuel", amount) + check_fuel() + if(M) + M.flash_act(light_intensity) + return TRUE + else + if(M) + to_chat(M, "You need more welding fuel to complete this task!") + return FALSE + + +//Turns off the welder if there is no more fuel (does this really need to be its own proc?) +/obj/item/weldingtool/proc/check_fuel(mob/user) + if(get_fuel() <= 0 && welding) + switched_on(user) + update_icon() + //mob icon update + if(ismob(loc)) + var/mob/M = loc + M.update_inv_hands(0) + + return 0 + return 1 + +//Switches the welder on +/obj/item/weldingtool/proc/switched_on(mob/user) + if(!status) + to_chat(user, "[src] can't be turned on while unsecured!") + return + welding = !welding + if(welding) + if(get_fuel() >= 1) + to_chat(user, "You switch [src] on.") + playsound(loc, acti_sound, 50, 1) + force = 15 + damtype = "fire" + hitsound = 'sound/items/welder.ogg' + update_icon() + START_PROCESSING(SSobj, src) + else + to_chat(user, "You need more fuel!") + switched_off(user) + else + to_chat(user, "You switch [src] off.") + playsound(loc, deac_sound, 50, 1) + switched_off(user) + +//Switches the welder off +/obj/item/weldingtool/proc/switched_off(mob/user) + welding = 0 + set_light(0) + + force = 3 + damtype = "brute" + hitsound = "swing_hit" + update_icon() + + +/obj/item/weldingtool/examine(mob/user) + ..() + to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") + +/obj/item/weldingtool/is_hot() + return welding * heat + +//Returns whether or not the welding tool is currently on. +/obj/item/weldingtool/proc/isOn() + return welding + + +/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) + if(welding) + to_chat(user, "Turn it off first!") + return + status = !status + if(status) + to_chat(user, "You resecure [src] and close the fuel tank.") + container_type = NONE + else + to_chat(user, "[src] can now be attached, modified, and refuelled.") + container_type = OPENCONTAINER + add_fingerprint(user) + +/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) + if(!status) + var/obj/item/stack/rods/R = I + if (R.use(1)) + var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) + if(!remove_item_from_storage(F)) + user.transferItemToLoc(src, F, TRUE) + F.weldtool = src + add_fingerprint(user) + to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") + user.put_in_hands(F) + else + to_chat(user, "You need one rod to start building a flamethrower!") + +/obj/item/weldingtool/ignition_effect(atom/A, mob/user) + if(welding && remove_fuel(1, user)) + . = "[user] casually lights [A] with [src], what a badass." + else + . = "" + +/obj/item/weldingtool/largetank + name = "industrial welding tool" + desc = "A slightly larger welder with a larger tank." + icon_state = "indwelder" + max_fuel = 40 + materials = list(MAT_GLASS=60) + +/obj/item/weldingtool/largetank/cyborg + name = "integrated welding tool" + desc = "An advanced welder designed to be used in robotic systems." + toolspeed = 0.5 + +/obj/item/weldingtool/largetank/flamethrower_screwdriver() + return + + +/obj/item/weldingtool/mini + name = "emergency welding tool" + desc = "A miniature welder used during emergencies." + icon_state = "miniwelder" + max_fuel = 10 + w_class = WEIGHT_CLASS_TINY + materials = list(MAT_METAL=30, MAT_GLASS=10) + change_icons = 0 + +/obj/item/weldingtool/mini/flamethrower_screwdriver() + return + +/obj/item/weldingtool/abductor + name = "alien welding tool" + desc = "An alien welding tool. Whatever fuel it uses, it never runs out." + icon = 'icons/obj/abductor.dmi' + icon_state = "welder" + toolspeed = 0.1 + light_intensity = 0 + change_icons = 0 + +/obj/item/weldingtool/abductor/process() + if(get_fuel() <= max_fuel) + reagents.add_reagent("welding_fuel", 1) + ..() + +/obj/item/weldingtool/hugetank + name = "upgraded industrial welding tool" + desc = "An upgraded welder based of the industrial welder." + icon_state = "upindwelder" + item_state = "upindwelder" + max_fuel = 80 + materials = list(MAT_METAL=70, MAT_GLASS=120) + +/obj/item/weldingtool/experimental + name = "experimental welding tool" + desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." + icon_state = "exwelder" + item_state = "exwelder" + max_fuel = 40 + materials = list(MAT_METAL=70, MAT_GLASS=120) + var/last_gen = 0 + change_icons = 0 + can_off_process = 1 + light_intensity = 1 + toolspeed = 0.5 + var/nextrefueltick = 0 + +/obj/item/weldingtool/experimental/brass + name = "brass welding tool" + desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "brasswelder" + item_state = "brasswelder" + + +/obj/item/weldingtool/experimental/process() + ..() + if(get_fuel() < max_fuel && nextrefueltick < world.time) + nextrefueltick = world.time + 10 + reagents.add_reagent("welding_fuel", 1) + +>>>>>>> 40699a8... [READY]Refactors reagent container types (#33470) #undef WELDER_FUEL_BURN_INTERVAL \ No newline at end of file diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index b6332492dd..0f12f847d7 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -5,7 +5,7 @@ icon_state = "cart" anchored = FALSE density = TRUE - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER //copypaste sorry var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite var/obj/item/storage/bag/trash/mybag = null diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm index b2dc64fec7..43da5073ed 100644 --- a/code/game/objects/structures/mop_bucket.dm +++ b/code/game/objects/structures/mop_bucket.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/janitor.dmi' icon_state = "mopbucket" density = TRUE +<<<<<<< HEAD container_type = OPENCONTAINER_1 var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite @@ -21,4 +22,23 @@ to_chat(user, "You wet [I] in [src].") playsound(loc, 'sound/effects/slosh.ogg', 25, 1) else +======= + container_type = OPENCONTAINER + var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite + + +/obj/structure/mopbucket/New() + create_reagents(100) + ..() + +/obj/structure/mopbucket/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/mop)) + if(reagents.total_volume < 1) + to_chat(user, "[src] is out of water!") + else + reagents.trans_to(I, 5) + to_chat(user, "You wet [I] in [src].") + playsound(loc, 'sound/effects/slosh.ogg', 25, 1) + else +>>>>>>> 40699a8... [READY]Refactors reagent container types (#33470) return ..() \ No newline at end of file diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 9009a7171d..77b992704a 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -483,9 +483,9 @@ if(istype(O, /obj/item/reagent_containers)) var/obj/item/reagent_containers/RG = O - if(RG.container_type & OPENCONTAINER_1) + if(RG.is_refillable()) if(!RG.reagents.holder_full()) - RG.reagents.add_reagent("[dispensedreagent]", min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this)) + RG.reagents.add_reagent(dispensedreagent, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this)) to_chat(user, "You fill [RG] from [src].") return TRUE to_chat(user, "\The [RG] is full.") @@ -533,7 +533,7 @@ O.clean_blood() O.acid_level = 0 create_reagents(5) - reagents.add_reagent("[dispensedreagent]", 5) + reagents.add_reagent(dispensedreagent, 5) reagents.reaction(O, TOUCH) user.visible_message("[user] washes [O] using [src].", \ "You wash [O] using [src].") diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm index 3e4e93ca4c..85ae7c3b18 100644 --- a/code/modules/crafting/craft.dm +++ b/code/modules/crafting/craft.dm @@ -98,7 +98,7 @@ else if(istype(I, /obj/item/reagent_containers)) var/obj/item/reagent_containers/RC = I - if(RC.container_type & OPENCONTAINER_1) + if(RC.is_drainable()) for(var/datum/reagent/A in RC.reagents.reagent_list) .[A.type] += A.volume .[I.type] += 1 diff --git a/code/modules/detectivework/footprints_and_rag.dm b/code/modules/detectivework/footprints_and_rag.dm index 9415bef33d..793805977c 100644 --- a/code/modules/detectivework/footprints_and_rag.dm +++ b/code/modules/detectivework/footprints_and_rag.dm @@ -13,7 +13,7 @@ icon = 'icons/obj/toy.dmi' icon_state = "rag" flags_1 = NOBLUDGEON_1 - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER amount_per_transfer_from_this = 5 possible_transfer_amounts = list() volume = 5 diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index 6fb712ea41..c03b183ecc 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -8,7 +8,7 @@ icon_state = null lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi' - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER var/gulp_size = 5 //This is now officially broken ... need to think of a nice way to fix it. possible_transfer_amounts = list(5,10,15,20,25,30,50) volume = 50 @@ -30,7 +30,7 @@ if(!canconsume(M, user)) return 0 - if (!is_open_container()) + if (!is_drainable()) to_chat(user, "[src]'s lid hasn't been opened!") return 0 @@ -44,7 +44,7 @@ if(!reagents || !reagents.total_volume) return // The drink might be empty after the delay, such as by spam-feeding M.visible_message("[user] feeds the contents of [src] to [M].", "[user] feeds the contents of [src] to [M].") - add_logs(user, M, "fed", reagentlist(src)) + add_logs(user, M, "fed", reagents.log_list()) var/fraction = min(gulp_size/reagents.total_volume, 1) checkLiked(fraction, M) @@ -56,31 +56,16 @@ /obj/item/reagent_containers/food/drinks/afterattack(obj/target, mob/user , proximity) if(!proximity) return - if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us. - if (!is_open_container()) - to_chat(user, "[target]'s tab isn't open!") - return - - if(!target.reagents.total_volume) - to_chat(user, "[target] is empty.") - return - - if(reagents.total_volume >= reagents.maximum_volume) - to_chat(user, "[src] is full.") - return - - var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this) - to_chat(user, "You fill [src] with [trans] units of the contents of [target].") - - else if(target.is_open_container()) //Something like a glass. Player probably wants to transfer TO it. + if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it. if(!reagents.total_volume) to_chat(user, "[src] is empty.") return - if(target.reagents.total_volume >= target.reagents.maximum_volume) + if(target.reagents.holder_full()) to_chat(user, "[target] is full.") return + var/refill = reagents.get_master_reagent_id() var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this) to_chat(user, "You transfer [trans] units of the solution to [target].") @@ -90,6 +75,24 @@ bro.cell.use(30) addtimer(CALLBACK(reagents, /datum/reagents.proc/add_reagent, refill, trans), 600) + else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us. + if (!is_refillable()) + to_chat(user, "[src]'s tab isn't open!") + return + + if(!target.reagents.total_volume) + to_chat(user, "[target] is empty.") + return + + if(reagents.holder_full()) + to_chat(user, "[src] is full.") + return + + var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this) + to_chat(user, "You fill [src] with [trans] units of the contents of [target].") + + else + /obj/item/reagent_containers/food/drinks/attackby(obj/item/I, mob/user, params) if(I.is_hot()) var/added_heat = (I.is_hot() / 100) //ishot returns a temperature @@ -142,7 +145,7 @@ possible_transfer_amounts = list() volume = 5 flags_1 = CONDUCT_1 - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER spillable = TRUE resistance_flags = FIRE_PROOF isGlass = FALSE @@ -406,9 +409,9 @@ /obj/item/reagent_containers/food/drinks/soda_cans/attack_self(mob/user) - if(!is_open_container()) + if(!is_drainable()) to_chat(user, "You pull back the tab of \the [src] with a satisfying pop.") //Ahhhhhhhh - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER playsound(src, "can_open", 50, 1) spillable = TRUE return diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm index e23f6b98a9..765f118c5e 100644 --- a/code/modules/food_and_drinks/food.dm +++ b/code/modules/food_and_drinks/food.dm @@ -4,7 +4,7 @@ /obj/item/reagent_containers/food possible_transfer_amounts = list() volume = 50 //Sets the default container amount for all food items. - container_type = INJECTABLE_1 + container_type = INJECTABLE resistance_flags = FLAMMABLE var/foodtype = NONE var/last_check_time diff --git a/code/modules/food_and_drinks/food/condiment.dm b/code/modules/food_and_drinks/food/condiment.dm index 3e6e2e8450..445e8e6534 100644 --- a/code/modules/food_and_drinks/food/condiment.dm +++ b/code/modules/food_and_drinks/food/condiment.dm @@ -10,7 +10,7 @@ desc = "Just your average condiment container." icon = 'icons/obj/food/containers.dmi' icon_state = "emptycondiment" - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER possible_transfer_amounts = list(1, 5, 10, 15, 20, 25, 30, 50) volume = 50 //Possible_states has the reagent id as key and a list of, in order, the icon_state, the name and the desc as values. Used in the on_reagent_change(changetype) to change names, descs and sprites. @@ -45,7 +45,7 @@ if(!reagents || !reagents.total_volume) return // The condiment might be empty after the delay. user.visible_message("[user] feeds [M] from [src].") - add_logs(user, M, "fed", reagentlist(src)) + add_logs(user, M, "fed", reagents.log_list()) var/fraction = min(10/reagents.total_volume, 1) reagents.reaction(M, INGEST, fraction) @@ -70,7 +70,7 @@ to_chat(user, "You fill [src] with [trans] units of the contents of [target].") //Something like a glass or a food item. Player probably wants to transfer TO it. - else if(target.is_open_container() || istype(target, /obj/item/reagent_containers/food/snacks)) + else if(target.is_drainable() || istype(target, /obj/item/reagent_containers/food/snacks)) if(!reagents.total_volume) to_chat(user, "[src] is empty!") return diff --git a/code/modules/food_and_drinks/food/customizables.dm b/code/modules/food_and_drinks/food/customizables.dm index 3351a67d39..f3460edcaa 100644 --- a/code/modules/food_and_drinks/food/customizables.dm +++ b/code/modules/food_and_drinks/food/customizables.dm @@ -291,7 +291,7 @@ desc = "A simple bowl, used for soups and salads." icon = 'icons/obj/food/soupsalad.dmi' icon_state = "bowl" - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER materials = list(MAT_GLASS = 500) w_class = WEIGHT_CLASS_NORMAL diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index 7f574e0313..08b09124d5 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -94,7 +94,7 @@ if(!do_mob(user, M)) return - add_logs(user, M, "fed", reagentlist(src)) + add_logs(user, M, "fed", reagents.log_list()) M.visible_message("[user] forces [M] to eat [src].", \ "[user] forces [M] to eat [src].") diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index a336d77404..40eae1b570 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -29,7 +29,7 @@ God bless America. anchored = TRUE use_power = IDLE_POWER_USE idle_power_usage = 5 - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER var/obj/item/reagent_containers/food/snacks/deepfryholder/frying //What's being fried RIGHT NOW? var/cook_time = 0 var/oil_use = 0.05 //How much cooking oil is used per tick diff --git a/code/modules/food_and_drinks/kitchen_machinery/food_cart.dm b/code/modules/food_and_drinks/kitchen_machinery/food_cart.dm index 8573a84c9b..26a2bec76f 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/food_cart.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/food_cart.dm @@ -15,7 +15,7 @@ var/portion = 10 var/selected_drink var/list/stored_food = list() - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER var/obj/item/reagent_containers/mixer /obj/machinery/food_cart/Initialize() @@ -100,7 +100,7 @@ stored_food[sanitize(S.name)]++ else stored_food[sanitize(S.name)] = 1 - else if(O.is_open_container()) + else if(O.is_drainable()) return else . = ..() diff --git a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm index 1b00de1842..f2f288fe7a 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm @@ -14,7 +14,7 @@ anchored = FALSE use_power = NO_POWER_USE layer = BELOW_OBJ_LAYER - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER max_integrity = 300 var/list/product_types = list() var/dispense_flavour = ICECREAM_VANILLA @@ -112,7 +112,7 @@ else to_chat(user, "[O] already has ice cream in it.") return 1 - else if(O.is_open_container()) + else if(O.is_drainable()) return else return ..() diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm index dfa249c04d..52ee5ebd2b 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm @@ -81,7 +81,7 @@ src.icon_state = "mw" src.broken = 0 // Fix it! src.dirty = 0 // just to be sure - src.container_type = OPENCONTAINER_1 + src.container_type = OPENCONTAINER return 0 //to use some fuel else to_chat(user, "It's broken!") @@ -98,7 +98,7 @@ src.dirty = 0 // It's clean! src.broken = 0 // just to be sure src.icon_state = "mw" - src.container_type = OPENCONTAINER_1 + src.container_type = OPENCONTAINER src.updateUsrDialog() return 1 // Disables the after-attack so we don't spray the floor/user. else @@ -119,7 +119,7 @@ src.dirty = 0 // It's clean! src.broken = 0 // just to be sure src.icon_state = "mw" - src.container_type = OPENCONTAINER_1 + src.container_type = OPENCONTAINER else if(src.dirty==100) // The microwave is all dirty so can't be used! to_chat(user, "It's dirty!") diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm index 42a927f4e9..c72d9e5c28 100644 --- a/code/modules/hydroponics/hydroitemdefines.dm +++ b/code/modules/hydroponics/hydroitemdefines.dm @@ -24,12 +24,6 @@ lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi' volume = 100 - container_type = OPENCONTAINER_1 - slot_flags = SLOT_BELT - throwforce = 0 - w_class = WEIGHT_CLASS_SMALL - throw_speed = 3 - throw_range = 10 /obj/item/reagent_containers/spray/weedspray/Initialize() . = ..() @@ -48,12 +42,6 @@ lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi' volume = 100 - container_type = OPENCONTAINER_1 - slot_flags = SLOT_BELT - throwforce = 0 - w_class = WEIGHT_CLASS_SMALL - throw_speed = 3 - throw_range = 10 /obj/item/reagent_containers/spray/pestspray/Initialize() . = ..() diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 5c1fafc1c4..08cb712542 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -712,8 +712,8 @@ else if(transfer_amount) // Droppers, cans, beakers, what have you. visi_msg="[user] uses [reagent_source] on [target]" irrigate = 1 - // Beakers, bottles, buckets, etc. Can't use is_open_container though. - if(istype(reagent_source, /obj/item/reagent_containers/glass/)) + // Beakers, bottles, buckets, etc. + if(reagent_source.is_drainable()) playsound(loc, 'sound/effects/slosh.ogg', 25, 1) if(irrigate && transfer_amount > 30 && reagent_source.reagents.total_volume >= 30 && using_irrigation) diff --git a/code/modules/integrated_electronics/passive/power.dm b/code/modules/integrated_electronics/passive/power.dm index 0941c033f6..2acce3d450 100644 --- a/code/modules/integrated_electronics/passive/power.dm +++ b/code/modules/integrated_electronics/passive/power.dm @@ -90,7 +90,7 @@ icon_state = "chemical_cell" extended_desc = "This is effectively an internal beaker. It will consume and produce power from plasma, slime jelly, welding fuel, carbon,\ ethanol, nutriments and blood , in order of decreasing efficiency. It will consume fuel only if the battery can take more energy." - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER complexity = 4 inputs = list() outputs = list("volume used" = IC_PINTYPE_NUMBER, "self reference" = IC_PINTYPE_REF) diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index 564c3a4851..b6307471f4 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -17,7 +17,7 @@ extended_desc = "This smoke generator creates clouds of smoke on command. It can also hold liquids inside, which will go \ into the smoke clouds when activated. The reagents are consumed when smoke is made." - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER volume = 100 complexity = 20 @@ -66,7 +66,7 @@ extended_desc = "This autoinjector can push reagents into another container or someone else outside of the machine. The target \ must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing. Negative given amount makes injector suck out reagents." - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER volume = 30 complexity = 20 @@ -145,7 +145,7 @@ return if(direction_mode == SYRINGE_INJECT) - if(!reagents.total_volume || !AM.is_injectable() || AM.reagents.total_volume >= AM.reagents.maximum_volume) + if(!reagents.total_volume || !AM.is_injectable() || AM.reagents.holder_full()) activate_pin(3) return @@ -156,12 +156,8 @@ return //Always log attemped injections for admins - var/list/rinject = list() - for(var/datum/reagent/R in reagents.reagent_list) - rinject += R.name - var/contained = english_list(rinject) - - add_logs(src, L, "attemped to inject", addition="which had [contained]") //TODO: proper logging (maybe last touched and assembled) + var/contained = reagents.log_list() + add_logs(src, L, "attemped to inject", addition="which had [contained]") L.visible_message("[acting_object] is trying to inject [L]!", \ "[acting_object] is trying to inject you!") busy = TRUE @@ -169,6 +165,7 @@ var/fraction = min(transfer_amount/reagents.total_volume, 1) reagents.reaction(L, INJECT, fraction) reagents.trans_to(L, transfer_amount) + add_logs(src, L, "injected", addition="which had [contained]") L.visible_message("[acting_object] injects [L] with its needle!", \ "[acting_object] injects you with its needle!") else @@ -263,8 +260,7 @@ activate_pin(2) return - // FALSE in those procs makes mobs invalid targets. - if(!source.is_drawable(FALSE) || !target.is_injectable(FALSE)) + if(!source.is_drainable() || !target.is_refillable()) return source.reagents.trans_to(target, transfer_amount) @@ -276,7 +272,7 @@ icon_state = "reagent_storage" extended_desc = "This is effectively an internal beaker." - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER volume = 60 complexity = 4 @@ -398,8 +394,7 @@ if(!source.reagents || !target.reagents) return - // FALSE in those procs makes mobs invalid targets. - if(!source.is_drawable(FALSE) || !target.is_injectable(FALSE)) + if(!source.is_drainable() || !target.is_refillable()) return if(target.reagents.maximum_volume - target.reagents.total_volume <= 0) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index f589ecbb20..f07eecd998 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -343,8 +343,15 @@ return 1 return 0 +// Living mobs use can_inject() to make sure that the mob is not syringe-proof in general. /mob/living/proc/can_inject() - return 1 + return TRUE + +/mob/living/is_injectable(allowmobs = TRUE) + return (allowmobs && reagents && can_inject()) + +/mob/living/is_drawable(allowmobs = TRUE) + return (allowmobs && reagents && can_inject()) /mob/living/proc/get_organ_target() var/mob/shooter = src diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index fd52d8f0ac..cde600186f 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -162,7 +162,7 @@ * Sleepypens */ /obj/item/pen/sleepy - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER /obj/item/pen/sleepy/attack(mob/living/M, mob/user) diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm index d51ea36e15..d3ca08dc85 100644 --- a/code/modules/projectiles/ammunition/ammo_casings.dm +++ b/code/modules/projectiles/ammunition/ammo_casings.dm @@ -284,9 +284,15 @@ icon_state = "cshell" projectile_type = /obj/item/projectile/bullet/dart +<<<<<<< HEAD /obj/item/ammo_casing/shotgun/dart/New() ..() container_type |= OPENCONTAINER_1 +======= +/obj/item/ammo_casing/shotgun/dart/Initialize() + . = ..() + container_type |= OPENCONTAINER +>>>>>>> 40699a8... [READY]Refactors reagent container types (#33470) create_reagents(30) reagents.set_reacting(TRUE) diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 06bda36c66..a4ae8cae13 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -121,7 +121,6 @@ item_state = "plasmacutter" ammo_type = list(/obj/item/ammo_casing/energy/plasma) flags_1 = CONDUCT_1 - container_type = OPENCONTAINER_1 attack_verb = list("attacked", "slashed", "cut", "sliced") force = 12 sharpness = IS_SHARP diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 9c4bff72cb..5958dc0eab 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -59,6 +59,19 @@ if(my_atom && my_atom.reagents == src) my_atom.reagents = null + +// Used in attack logs for reagents in pills and such +/datum/reagents/proc/log_list() + if(!length(reagent_list)) + return "no reagents" + + var/list/data = list() + for(var/r in reagent_list) //no reagents will be left behind + var/datum/reagent/R = r + data += "[R.id] ([round(R.volume, 0.1)]u)" + //Using IDs because SOME chemicals (I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. + return english_list(data) + /datum/reagents/proc/remove_any(amount = 1) var/list/cached_reagents = reagent_list var/total_transfered = 0 diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 745843474e..a0e1e64207 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -184,7 +184,7 @@ if(default_unfasten_wrench(user, I)) return - if(istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER_1)) + if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) var/obj/item/reagent_containers/B = I . = 1 //no afterattack if(beaker) diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index a6d958220a..dc21eec6c0 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -64,7 +64,7 @@ if(default_deconstruction_crowbar(I)) return - if(istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER_1)) + if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) . = 1 //no afterattack if(beaker) to_chat(user, "A container is already loaded into [src]!") diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 3e06449e3a..e0c3b23c5a 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -88,7 +88,7 @@ if(default_unfasten_wrench(user, I)) return - if(istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER_1)) + if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) . = 1 // no afterattack if(panel_open) to_chat(user, "You can't use the [src.name] while its panel is opened!") diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index f6b0f464fd..ef186d8a79 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -225,7 +225,7 @@ /obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER_1)) + if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) . = TRUE //no afterattack if(stat & (NOPOWER|BROKEN)) return diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index 223259f6f3..b5d715f5ff 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -62,7 +62,7 @@ if(default_unfasten_wrench(user, I)) return - if (istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER_1) ) + if (istype(I, /obj/item/reagent_containers) && I.is_open_container()) if (!beaker) if(!user.transferItemToLoc(I, src)) to_chat(user, "[I] is stuck to your hand!") diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 8698c10b05..842d2dc2c3 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -48,15 +48,6 @@ /obj/item/reagent_containers/afterattack(obj/target, mob/user , flag) return -/obj/item/reagent_containers/proc/reagentlist(obj/item/reagent_containers/snack) //Attack logs for regents in pills - var/data - if(snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries - for (var/datum/reagent/R in snack.reagents.reagent_list) //no reagents will be left behind - data += "[R.id]([R.volume] units); " //Using IDs because SOME chemicals(I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. - return data - else - return "No reagents" - /obj/item/reagent_containers/proc/canconsume(mob/eater, mob/user) if(!iscarbon(eater)) return 0 @@ -127,7 +118,11 @@ reagents.clear_reagents() /obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M) +<<<<<<< HEAD if(is_open_container()) reagents.chem_temp = max(reagents.chem_temp, 1000) reagents.handle_reactions() +======= + reagents.expose_temperature(1000) +>>>>>>> 40699a8... [READY]Refactors reagent container types (#33470) ..() diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 28a07d5862..0a99d9da6e 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -173,7 +173,7 @@ Borg Shaker if(!proximity) return - else if(target.is_open_container() && target.reagents) + else if(target.is_refillable()) var/datum/reagents/R = reagent_list[mode] if(!R.total_volume) to_chat(user, "[src] is currently out of this ingredient! Please allow some time for the synthesizer to produce more.") diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index 30aa67e91a..144db32a6c 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -6,7 +6,7 @@ amount_per_transfer_from_this = 5 possible_transfer_amounts = list(1, 2, 3, 4, 5) volume = 5 - container_type = TRANSPARENT_1 + container_type = TRANSPARENT /obj/item/reagent_containers/dropper/afterattack(obj/target, mob/user , proximity) if(!proximity) diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index df2df7c171..33a45fd27b 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -3,7 +3,7 @@ amount_per_transfer_from_this = 10 possible_transfer_amounts = list(5, 10, 15, 20, 25, 30, 50) volume = 50 - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER spillable = TRUE resistance_flags = ACID_PROOF @@ -44,7 +44,7 @@ if(!reagents || !reagents.total_volume) return // The drink might be empty after the delay, such as by spam-feeding M.visible_message("[user] feeds something to [M].", "[user] feeds something to you.") - add_logs(user, M, "fed", reagentlist(src)) + add_logs(user, M, "fed", reagents.log_list()) else to_chat(user, "You swallow a gulp of [src].") var/fraction = min(5/reagents.total_volume, 1) @@ -56,32 +56,30 @@ if((!proximity) || !check_allowed_items(target,target_self=1)) return - else if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us. - - if(target.reagents && !target.reagents.total_volume) - to_chat(user, "[target] is empty and can't be refilled!") - return - - if(reagents.total_volume >= reagents.maximum_volume) - to_chat(user, "[src] is full.") - return - - var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this) - to_chat(user, "You fill [src] with [trans] unit\s of the contents of [target].") - - else if(target.is_open_container() && target.reagents) //Something like a glass. Player probably wants to transfer TO it. + if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it. if(!reagents.total_volume) to_chat(user, "[src] is empty!") return - if(target.reagents.total_volume >= target.reagents.maximum_volume) - to_chat(user, "[target] is full.") + if(target.reagents.holder_full()) + to_chat(user, "[target] is full.") return - var/trans = reagents.trans_to(target, amount_per_transfer_from_this) to_chat(user, "You transfer [trans] unit\s of the solution to [target].") + else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us. + if(!target.reagents.total_volume) + to_chat(user, "[target] is empty and can't be refilled!") + return + + if(reagents.holder_full()) + to_chat(user, "[src] is full.") + return + + var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this) + to_chat(user, "You fill [src] with [trans] unit\s of the contents of [target].") + else if(reagents.total_volume) if(user.a_intent == INTENT_HARM) user.visible_message("[user] splashes the contents of [src] onto [target]!", \ @@ -169,7 +167,6 @@ volume = 100 amount_per_transfer_from_this = 10 possible_transfer_amounts = list(5,10,15,20,25,30,50,100) - flags_1 = OPENCONTAINER_1 /obj/item/reagent_containers/glass/beaker/noreact name = "cryostasis beaker" @@ -179,7 +176,6 @@ materials = list(MAT_METAL=3000) volume = 50 amount_per_transfer_from_this = 10 - flags_1 = OPENCONTAINER_1 /obj/item/reagent_containers/glass/beaker/noreact/Initialize() . = ..() @@ -195,7 +191,6 @@ volume = 300 amount_per_transfer_from_this = 10 possible_transfer_amounts = list(5,10,15,20,25,30,50,100,300) - flags_1 = OPENCONTAINER_1 /obj/item/reagent_containers/glass/beaker/cryoxadone list_reagents = list("cryoxadone" = 30) @@ -238,7 +233,6 @@ amount_per_transfer_from_this = 20 possible_transfer_amounts = list(10,15,20,25,30,50,70) volume = 70 - flags_1 = OPENCONTAINER_1 flags_inv = HIDEHAIR slot_flags = SLOT_HEAD resistance_flags = NONE diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index dff0869322..53e0c9bfb6 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -10,7 +10,7 @@ volume = 30 possible_transfer_amounts = list() resistance_flags = ACID_PROOF - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER slot_flags = SLOT_BELT var/ignore_flags = 0 var/infinite = FALSE @@ -88,7 +88,7 @@ amount_per_transfer_from_this = 10 volume = 10 ignore_flags = 1 //so you can medipen through hardsuits - container_type = DRAWABLE_1 + container_type = DRAWABLE flags_1 = null list_reagents = list("epinephrine" = 10) diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index 5a2e888210..4908a55911 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -46,7 +46,7 @@ "[user] forces [M] to [apply_method] [src].") - add_logs(user, M, "fed", reagentlist(src)) + add_logs(user, M, "fed", reagents.log_list()) if(reagents.total_volume) reagents.reaction(M, apply_type) reagents.trans_to(M, reagents.total_volume) @@ -57,10 +57,15 @@ /obj/item/reagent_containers/pill/afterattack(obj/target, mob/user , proximity) if(!proximity) return - if(target.is_open_container() != 0 && target.reagents) - if(!target.reagents.total_volume) + if(target.is_refillable()) + if(target.is_drainable() && !target.reagents.total_volume) to_chat(user, "[target] is empty! There's nothing to dissolve [src] in.") return + + if(target.reagents.holder_full()) + to_chat(user, "[target] is full.") + return + to_chat(user, "You dissolve [src] in [target].") for(var/mob/O in viewers(2, user)) //viewers is necessary here because of the small radius to_chat(O, "[user] slips something into [target]!") diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 789345ca77..f8158ba948 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -7,7 +7,7 @@ lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi' flags_1 = NOBLUDGEON_1 - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER slot_flags = SLOT_BELT throwforce = 0 w_class = WEIGHT_CLASS_SMALL @@ -23,17 +23,17 @@ possible_transfer_amounts = list(5,10,15,20,25,30,50,100) -/obj/item/reagent_containers/spray/afterattack(atom/A as mob|obj, mob/user) +/obj/item/reagent_containers/spray/afterattack(atom/A, mob/user) if(istype(A, /obj/structure/sink) || istype(A, /obj/structure/janitorialcart) || istype(A, /obj/machinery/hydroponics)) return - if(istype(A, /obj/structure/reagent_dispensers) && get_dist(src,A) <= 1) //this block copypasted from reagent_containers/glass, for lack of a better solution - if(!A.reagents.total_volume && A.reagents) - to_chat(user, "\The [A] is empty.") + if((A.is_drainable() && !A.is_refillable()) && get_dist(src,A) <= 1) + if(!A.reagents.total_volume) + to_chat(user, "[A] is empty.") return - if(reagents.total_volume >= reagents.maximum_volume) - to_chat(user, "\The [src] is full.") + if(reagents.holder_full()) + to_chat(user, "[src] is full.") return var/trans = A.reagents.trans_to(src, 50) //transfer 50u , using the spray's transfer amount would take too long to refill @@ -41,7 +41,7 @@ return if(reagents.total_volume < amount_per_transfer_from_this) - to_chat(user, "\The [src] is empty!") + to_chat(user, "[src] is empty!") return spray(A) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 87fb2b8a9e..17a671569f 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -13,7 +13,7 @@ var/busy = FALSE // needed for delayed drawing of blood var/proj_piercing = 0 //does it pierce through thick clothes when shot with syringe gun materials = list(MAT_METAL=10, MAT_GLASS=20) - container_type = TRANSPARENT_1 + container_type = TRANSPARENT /obj/item/reagent_containers/syringe/Initialize() . = ..() @@ -107,11 +107,8 @@ update_icon() if(SYRINGE_INJECT) - //Always log attemped injections for admins - var/list/rinject = list() - for(var/datum/reagent/R in reagents.reagent_list) - rinject += R.name - var/contained = english_list(rinject) + // Always log attemped injections for admins + var/contained = reagents.log_list() add_logs(user, L, "attemped to inject", src, addition="which had [contained]") if(!reagents.total_volume) diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index ea80f4c508..f0c0ecfb68 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -5,7 +5,7 @@ icon_state = "water" density = TRUE anchored = FALSE - container_type = DRAWABLE_1 + container_type = DRAINABLE | AMOUNT_VISIBLE pressure_resistance = 2*ONE_ATMOSPHERE max_integrity = 300 var/tank_volume = 1000 //In units, how much the dispenser can hold @@ -18,7 +18,7 @@ boom() /obj/structure/reagent_dispensers/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/reagent_containers)) + if(W.is_refillable()) return 0 //so we can refill them via their afterattack. else return ..() @@ -28,14 +28,6 @@ reagents.add_reagent(reagent_id, tank_volume) . = ..() -/obj/structure/reagent_dispensers/examine(mob/user) - ..() - if(reagents.total_volume) - to_chat(user, "It has [reagents.total_volume] unit\s left.") - else - to_chat(user, "It's empty.") - - /obj/structure/reagent_dispensers/proc/boom() visible_message("\The [src] ruptures!") chem_splash(loc, 5, list(reagents)) diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index a66fdf7e03..26fa304209 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -8,7 +8,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). name = "circuit imprinter" desc = "Manufactures circuit boards for the construction of machines." icon_state = "circuit_imprinter" - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER circuit = /obj/item/circuitboard/machine/circuit_imprinter var/efficiency_coeff diff --git a/code/modules/research/departmental_circuit_imprinter.dm b/code/modules/research/departmental_circuit_imprinter.dm index bd3414884f..991feccb66 100644 --- a/code/modules/research/departmental_circuit_imprinter.dm +++ b/code/modules/research/departmental_circuit_imprinter.dm @@ -2,7 +2,7 @@ name = "Department Circuit Imprinter" desc = "A special circuit imprinter with a built in interface meant for departmental usage, with built in ExoSync recievers allowing it to print designs researched that match its ROM-encoded department type. Features a bluespace materials reciever for recieving materials without the hassle of running to mining!" icon_state = "circuit_imprinter" - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER circuit = /obj/item/circuitboard/machine/circuit_imprinter/department console_link = FALSE requires_console = FALSE diff --git a/code/modules/research/departmental_lathe.dm b/code/modules/research/departmental_lathe.dm index 2e534195d9..83f543e4cb 100644 --- a/code/modules/research/departmental_lathe.dm +++ b/code/modules/research/departmental_lathe.dm @@ -2,7 +2,7 @@ name = "department protolathe" desc = "A special protolathe with a built in interface meant for departmental usage, with built in ExoSync recievers allowing it to print designs researched that match its ROM-encoded department type. Features a bluespace materials reciever for recieving materials without the hassle of running to mining!" icon_state = "protolathe" - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER circuit = /obj/item/circuitboard/machine/protolathe/department console_link = FALSE requires_console = FALSE diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index 6c52fd4678..f76ff1c7ff 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -11,7 +11,7 @@ Note: Must be placed west/left of and R&D console to function. name = "protolathe" desc = "Converts raw materials into useful objects." icon_state = "protolathe" - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER circuit = /obj/item/circuitboard/machine/protolathe var/efficiency_coeff diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index ad75ddf07b..61b06d356e 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -59,7 +59,7 @@ return if(default_deconstruction_crowbar(O)) return - if(is_open_container() && O.is_open_container()) + if(is_refillable() && O.is_drainable()) return FALSE //inserting reagents into the machine if(Insert_Item(O, user)) return TRUE diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 7d8ff00e91..ae0e8f5c5e 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -11,7 +11,7 @@ throwforce = 0 throw_speed = 3 throw_range = 6 - container_type = INJECTABLE_1 + container_type = INJECTABLE | DRAWABLE grind_results = list() var/Uses = 1 // uses before it goes inert var/qdel_timer = null // deletion timer, for delayed reactions From d59e85e2144501beebb7782eef280db4d704f8a6 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:20:39 -0600 Subject: [PATCH 20/96] Update weldingtool.dm --- code/game/objects/items/tools/weldingtool.dm | 393 ++----------------- 1 file changed, 26 insertions(+), 367 deletions(-) diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index a09f0d2a1a..12c056c9af 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -1,4 +1,3 @@ -<<<<<<< HEAD #define WELDER_FUEL_BURN_INTERVAL 13 /obj/item/weldingtool name = "welding tool" @@ -22,7 +21,7 @@ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) resistance_flags = FIRE_PROOF - materials = list(MAT_METAL=70, MAT_GLASS=30) + materials = list(MAT_METAL=70, MAT_GLASS=30) var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) var/max_fuel = 20 //The max amount of fuel the welder can hold @@ -52,7 +51,7 @@ cut_overlays() if(change_icons) var/ratio = get_fuel() / max_fuel - ratio = Ceiling(ratio*4) * 25 + ratio = CEILING(ratio*4, 1) * 25 add_overlay("[initial(icon_state)][ratio]") update_torch() return @@ -90,18 +89,15 @@ flamethrower_screwdriver(I, user) else if(istype(I, /obj/item/stack/rods)) flamethrower_rods(I, user) - else if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) - var/amountNeeded = max_fuel - get_fuel() - var/obj/item/reagent_containers/container = I - if(length(container.reagents.reagent_list) > 1) - to_chat(user, "[container] has too many chemicals mixed into it. You wouldn't want to put the wrong chemicals into [src].") - return ..() - if(amountNeeded > 0 && container.reagents.has_reagent("welding_fuel")) - container.reagents.trans_id_to(src, "welding_fuel", amountNeeded) - to_chat(user, "You transfer some fuel from [container] to [src].") else - return ..() + . = ..() + update_icon() +/obj/item/weldingtool/proc/explode() + var/turf/T = get_turf(loc) + var/plasmaAmount = reagents.get_reagent_amount("plasma") + dyn_explosion(T, plasmaAmount/5)//20 plasma in a standard welder has a 4 power explosion. no breaches, but enough to kill/dismember holder + qdel(src) /obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) if(!istype(H)) @@ -124,7 +120,10 @@ /obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) if(!proximity) return - + if(!status && O.is_refillable()) + reagents.trans_to(O, reagents.total_volume) + to_chat(user, "You empty [src]'s fuel tank into [O].") + update_icon() if(welding) remove_fuel(1) var/turf/location = get_turf(user) @@ -140,6 +139,9 @@ /obj/item/weldingtool/attack_self(mob/user) + if(src.reagents.has_reagent("plasma")) + message_admins("[key_name_admin(user)] activated a rigged welder.") + explode() switched_on(user) if(welding) set_light(light_intensity) @@ -235,9 +237,11 @@ return status = !status if(status) - to_chat(user, "You resecure [src].") + to_chat(user, "You resecure [src] and close the fuel tank.") + container_type = NONE else - to_chat(user, "[src] can now be attached and modified.") + to_chat(user, "[src] can now be attached, modified, and refuelled.") + container_type = OPENCONTAINER add_fingerprint(user) /obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) @@ -265,7 +269,7 @@ desc = "A slightly larger welder with a larger tank." icon_state = "indwelder" max_fuel = 40 - materials = list(MAT_GLASS=60) + materials = list(MAT_GLASS=60) /obj/item/weldingtool/largetank/cyborg name = "integrated welding tool" @@ -295,7 +299,7 @@ icon_state = "welder" toolspeed = 0.1 light_intensity = 0 - change_icons = 0 + change_icons = 0 /obj/item/weldingtool/abductor/process() if(get_fuel() <= max_fuel) @@ -308,7 +312,7 @@ icon_state = "upindwelder" item_state = "upindwelder" max_fuel = 80 - materials = list(MAT_METAL=70, MAT_GLASS=120) + materials = list(MAT_METAL=70, MAT_GLASS=120) /obj/item/weldingtool/experimental name = "experimental welding tool" @@ -316,7 +320,7 @@ icon_state = "exwelder" item_state = "exwelder" max_fuel = 40 - materials = list(MAT_METAL=70, MAT_GLASS=120) + materials = list(MAT_METAL=70, MAT_GLASS=120) var/last_gen = 0 change_icons = 0 can_off_process = 1 @@ -337,350 +341,5 @@ if(get_fuel() < max_fuel && nextrefueltick < world.time) nextrefueltick = world.time + 10 reagents.add_reagent("welding_fuel", 1) -======= -#define WELDER_FUEL_BURN_INTERVAL 13 -/obj/item/weldingtool - name = "welding tool" - desc = "A standard edition welder provided by Nanotrasen." - icon = 'icons/obj/tools.dmi' - icon_state = "welder" - item_state = "welder" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 3 - throwforce = 5 - hitsound = "swing_hit" - usesound = 'sound/items/welder.ogg' - var/acti_sound = 'sound/items/welderactivate.ogg' - var/deac_sound = 'sound/items/welderdeactivate.ogg' - throw_speed = 3 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) - resistance_flags = FIRE_PROOF - - materials = list(MAT_METAL=70, MAT_GLASS=30) - var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) - var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) - var/max_fuel = 20 //The max amount of fuel the welder can hold - var/change_icons = 1 - var/can_off_process = 0 - var/light_intensity = 2 //how powerful the emitted light is when used. - var/burned_fuel_for = 0 //when fuel was last removed - heat = 3800 - toolspeed = 1 - -/obj/item/weldingtool/Initialize() - . = ..() - create_reagents(max_fuel) - reagents.add_reagent("welding_fuel", max_fuel) - update_icon() - - -/obj/item/weldingtool/proc/update_torch() - if(welding) - add_overlay("[initial(icon_state)]-on") - item_state = "[initial(item_state)]1" - else - item_state = "[initial(item_state)]" - - -/obj/item/weldingtool/update_icon() - cut_overlays() - if(change_icons) - var/ratio = get_fuel() / max_fuel - ratio = CEILING(ratio*4, 1) * 25 - add_overlay("[initial(icon_state)][ratio]") - update_torch() - return - - -/obj/item/weldingtool/process() - switch(welding) - if(0) - force = 3 - damtype = "brute" - update_icon() - if(!can_off_process) - STOP_PROCESSING(SSobj, src) - return - //Welders left on now use up fuel, but lets not have them run out quite that fast - if(1) - force = 15 - damtype = "fire" - ++burned_fuel_for - if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) - remove_fuel(1) - update_icon() - - //This is to start fires. process() is only called if the welder is on. - open_flame() - - -/obj/item/weldingtool/suicide_act(mob/user) - user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") - return (FIRELOSS) - - -/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/screwdriver)) - flamethrower_screwdriver(I, user) - else if(istype(I, /obj/item/stack/rods)) - flamethrower_rods(I, user) - else - . = ..() - update_icon() - -/obj/item/weldingtool/proc/explode() - var/turf/T = get_turf(loc) - var/plasmaAmount = reagents.get_reagent_amount("plasma") - dyn_explosion(T, plasmaAmount/5)//20 plasma in a standard welder has a 4 power explosion. no breaches, but enough to kill/dismember holder - qdel(src) - -/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) - if(!istype(H)) - return ..() - - var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) - - if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) - if(src.remove_fuel(1)) - playsound(loc, usesound, 50, 1) - if(user == H) - user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") - if(!do_mob(user, H, 50)) - return - item_heal_robotic(H, user, 15, 0) - else - return ..() - - -/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) - if(!proximity) - return - if(!status && O.is_refillable()) - reagents.trans_to(O, reagents.total_volume) - to_chat(user, "You empty [src]'s fuel tank into [O].") - update_icon() - if(welding) - remove_fuel(1) - var/turf/location = get_turf(user) - location.hotspot_expose(700, 50, 1) - if(get_fuel() <= 0) - set_light(0) - - if(isliving(O)) - var/mob/living/L = O - if(L.IgniteMob()) - message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") - log_game("[key_name(user)] set [key_name(L)] on fire") - - -/obj/item/weldingtool/attack_self(mob/user) - if(src.reagents.has_reagent("plasma")) - message_admins("[key_name_admin(user)] activated a rigged welder.") - explode() - switched_on(user) - if(welding) - set_light(light_intensity) - - update_icon() - - -//Returns the amount of fuel in the welder -/obj/item/weldingtool/proc/get_fuel() - return reagents.get_reagent_amount("welding_fuel") - - -//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() -/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) - if(!welding || !check_fuel()) - return 0 - if(amount) - burned_fuel_for = 0 - if(get_fuel() >= amount) - reagents.remove_reagent("welding_fuel", amount) - check_fuel() - if(M) - M.flash_act(light_intensity) - return TRUE - else - if(M) - to_chat(M, "You need more welding fuel to complete this task!") - return FALSE - - -//Turns off the welder if there is no more fuel (does this really need to be its own proc?) -/obj/item/weldingtool/proc/check_fuel(mob/user) - if(get_fuel() <= 0 && welding) - switched_on(user) - update_icon() - //mob icon update - if(ismob(loc)) - var/mob/M = loc - M.update_inv_hands(0) - - return 0 - return 1 - -//Switches the welder on -/obj/item/weldingtool/proc/switched_on(mob/user) - if(!status) - to_chat(user, "[src] can't be turned on while unsecured!") - return - welding = !welding - if(welding) - if(get_fuel() >= 1) - to_chat(user, "You switch [src] on.") - playsound(loc, acti_sound, 50, 1) - force = 15 - damtype = "fire" - hitsound = 'sound/items/welder.ogg' - update_icon() - START_PROCESSING(SSobj, src) - else - to_chat(user, "You need more fuel!") - switched_off(user) - else - to_chat(user, "You switch [src] off.") - playsound(loc, deac_sound, 50, 1) - switched_off(user) - -//Switches the welder off -/obj/item/weldingtool/proc/switched_off(mob/user) - welding = 0 - set_light(0) - - force = 3 - damtype = "brute" - hitsound = "swing_hit" - update_icon() - - -/obj/item/weldingtool/examine(mob/user) - ..() - to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") - -/obj/item/weldingtool/is_hot() - return welding * heat - -//Returns whether or not the welding tool is currently on. -/obj/item/weldingtool/proc/isOn() - return welding - - -/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) - if(welding) - to_chat(user, "Turn it off first!") - return - status = !status - if(status) - to_chat(user, "You resecure [src] and close the fuel tank.") - container_type = NONE - else - to_chat(user, "[src] can now be attached, modified, and refuelled.") - container_type = OPENCONTAINER - add_fingerprint(user) - -/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) - if(!status) - var/obj/item/stack/rods/R = I - if (R.use(1)) - var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) - if(!remove_item_from_storage(F)) - user.transferItemToLoc(src, F, TRUE) - F.weldtool = src - add_fingerprint(user) - to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") - user.put_in_hands(F) - else - to_chat(user, "You need one rod to start building a flamethrower!") - -/obj/item/weldingtool/ignition_effect(atom/A, mob/user) - if(welding && remove_fuel(1, user)) - . = "[user] casually lights [A] with [src], what a badass." - else - . = "" - -/obj/item/weldingtool/largetank - name = "industrial welding tool" - desc = "A slightly larger welder with a larger tank." - icon_state = "indwelder" - max_fuel = 40 - materials = list(MAT_GLASS=60) - -/obj/item/weldingtool/largetank/cyborg - name = "integrated welding tool" - desc = "An advanced welder designed to be used in robotic systems." - toolspeed = 0.5 - -/obj/item/weldingtool/largetank/flamethrower_screwdriver() - return - - -/obj/item/weldingtool/mini - name = "emergency welding tool" - desc = "A miniature welder used during emergencies." - icon_state = "miniwelder" - max_fuel = 10 - w_class = WEIGHT_CLASS_TINY - materials = list(MAT_METAL=30, MAT_GLASS=10) - change_icons = 0 - -/obj/item/weldingtool/mini/flamethrower_screwdriver() - return - -/obj/item/weldingtool/abductor - name = "alien welding tool" - desc = "An alien welding tool. Whatever fuel it uses, it never runs out." - icon = 'icons/obj/abductor.dmi' - icon_state = "welder" - toolspeed = 0.1 - light_intensity = 0 - change_icons = 0 - -/obj/item/weldingtool/abductor/process() - if(get_fuel() <= max_fuel) - reagents.add_reagent("welding_fuel", 1) - ..() - -/obj/item/weldingtool/hugetank - name = "upgraded industrial welding tool" - desc = "An upgraded welder based of the industrial welder." - icon_state = "upindwelder" - item_state = "upindwelder" - max_fuel = 80 - materials = list(MAT_METAL=70, MAT_GLASS=120) - -/obj/item/weldingtool/experimental - name = "experimental welding tool" - desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." - icon_state = "exwelder" - item_state = "exwelder" - max_fuel = 40 - materials = list(MAT_METAL=70, MAT_GLASS=120) - var/last_gen = 0 - change_icons = 0 - can_off_process = 1 - light_intensity = 1 - toolspeed = 0.5 - var/nextrefueltick = 0 - -/obj/item/weldingtool/experimental/brass - name = "brass welding tool" - desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "brasswelder" - item_state = "brasswelder" - - -/obj/item/weldingtool/experimental/process() - ..() - if(get_fuel() < max_fuel && nextrefueltick < world.time) - nextrefueltick = world.time + 10 - reagents.add_reagent("welding_fuel", 1) - ->>>>>>> 40699a8... [READY]Refactors reagent container types (#33470) -#undef WELDER_FUEL_BURN_INTERVAL \ No newline at end of file + +#undef WELDER_FUEL_BURN_INTERVAL From a8db6dc9c2657ff22088c7a9ba26fd9c86de3d5e Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:29:36 -0600 Subject: [PATCH 21/96] Update mop_bucket.dm --- code/game/objects/structures/mop_bucket.dm | 32 ++++------------------ 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm index 43da5073ed..d468e87a34 100644 --- a/code/game/objects/structures/mop_bucket.dm +++ b/code/game/objects/structures/mop_bucket.dm @@ -1,28 +1,9 @@ -/obj/structure/mopbucket - name = "mop bucket" - desc = "Fill it with water, but don't forget a mop!" - icon = 'icons/obj/janitor.dmi' - icon_state = "mopbucket" +/obj/structure/mopbucket + name = "mop bucket" + desc = "Fill it with water, but don't forget a mop!" + icon = 'icons/obj/janitor.dmi' + icon_state = "mopbucket" density = TRUE -<<<<<<< HEAD - container_type = OPENCONTAINER_1 - var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite - - -/obj/structure/mopbucket/New() - create_reagents(100) - ..() - -/obj/structure/mopbucket/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/mop)) - if(reagents.total_volume < 1) - to_chat(user, "[src] is out of water!") - else - reagents.trans_to(I, 5) - to_chat(user, "You wet [I] in [src].") - playsound(loc, 'sound/effects/slosh.ogg', 25, 1) - else -======= container_type = OPENCONTAINER var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite @@ -40,5 +21,4 @@ to_chat(user, "You wet [I] in [src].") playsound(loc, 'sound/effects/slosh.ogg', 25, 1) else ->>>>>>> 40699a8... [READY]Refactors reagent container types (#33470) - return ..() \ No newline at end of file + return ..() From b46275079e30e6530f82ea4f704d65cd5528c7e5 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:29:45 -0600 Subject: [PATCH 22/96] Update ammo_casings.dm --- code/modules/projectiles/ammunition/ammo_casings.dm | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm index d3ca08dc85..edd28e72a8 100644 --- a/code/modules/projectiles/ammunition/ammo_casings.dm +++ b/code/modules/projectiles/ammunition/ammo_casings.dm @@ -284,15 +284,9 @@ icon_state = "cshell" projectile_type = /obj/item/projectile/bullet/dart -<<<<<<< HEAD -/obj/item/ammo_casing/shotgun/dart/New() - ..() - container_type |= OPENCONTAINER_1 -======= /obj/item/ammo_casing/shotgun/dart/Initialize() . = ..() container_type |= OPENCONTAINER ->>>>>>> 40699a8... [READY]Refactors reagent container types (#33470) create_reagents(30) reagents.set_reacting(TRUE) @@ -308,4 +302,4 @@ reagents.add_reagent("spore", 6) reagents.add_reagent("mutetoxin", 6) //;HELP OPS IN MAINT reagents.add_reagent("coniine", 6) - reagents.add_reagent("sodium_thiopental", 6) \ No newline at end of file + reagents.add_reagent("sodium_thiopental", 6) From 1b9d60c604109f136d892f1a631365466d66e9c1 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:29:55 -0600 Subject: [PATCH 23/96] Update reagent_containers.dm --- code/modules/reagents/reagent_containers.dm | 6 ------ 1 file changed, 6 deletions(-) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 842d2dc2c3..2645997d22 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -118,11 +118,5 @@ reagents.clear_reagents() /obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M) -<<<<<<< HEAD - if(is_open_container()) - reagents.chem_temp = max(reagents.chem_temp, 1000) - reagents.handle_reactions() -======= reagents.expose_temperature(1000) ->>>>>>> 40699a8... [READY]Refactors reagent container types (#33470) ..() From 678762209a047cfce5b5c66621ea7e13b617b61c Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:33:31 -0600 Subject: [PATCH 24/96] Update ticker.dm --- code/controllers/subsystem/ticker.dm | 201 --------------------------- 1 file changed, 201 deletions(-) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index f178a1bd24..0f06caa20d 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -398,207 +398,6 @@ SUBSYSTEM_DEF(ticker) var/mob/living/L = I L.notransform = FALSE -<<<<<<< HEAD -/datum/controller/subsystem/ticker/proc/declare_completion() - set waitfor = FALSE - var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED - var/num_survivors = 0 - var/num_escapees = 0 - var/num_shuttle_escapees = 0 - var/list/successfulCrew = list() - var/list/miscreants = list() - - to_chat(world, "


    The round has ended.") - if(LAZYLEN(GLOB.round_end_notifiees)) - send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.") - -/* var/nocredits = config.no_credits_round_end - for(var/client/C in GLOB.clients) - if(!C.credits && !nocredits) - C.RollCredits() - C.playtitlemusic(40)*/ - - //Player status report - for(var/i in GLOB.mob_list) - var/mob/Player = i - if(Player.mind && !isnewplayer(Player)) - if(Player.stat != DEAD && !isbrain(Player)) - num_survivors++ - if(station_evacuated) //If the shuttle has already left the station - var/list/area/shuttle_areas - if(SSshuttle && SSshuttle.emergency) - shuttle_areas = SSshuttle.emergency.shuttle_areas - if(!Player.onCentCom() && !Player.onSyndieBase()) - to_chat(Player, "You managed to survive, but were marooned on [station_name()]...") - else - num_escapees++ - to_chat(Player, "You managed to survive the events on [station_name()] as [Player.real_name].") - if(shuttle_areas[get_area(Player)]) - num_shuttle_escapees++ - else - to_chat(Player, "You managed to survive the events on [station_name()] as [Player.real_name].") - else - to_chat(Player, "You did not survive the events on [station_name()]...") - - CHECK_TICK - - //Round statistics report - var/datum/station_state/end_state = new /datum/station_state() - end_state.count() - var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100) - - to_chat(world, "
    [GLOB.TAB]Shift Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]") - to_chat(world, "
    [GLOB.TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]") - if(mode.station_was_nuked) - SSticker.news_report = STATION_DESTROYED_NUKE - var/total_players = GLOB.joined_player_list.len - if(total_players) - to_chat(world, "
    [GLOB.TAB]Total Population: [total_players]") - if(station_evacuated) - to_chat(world, "
    [GLOB.TAB]Evacuation Rate: [num_escapees] ([PERCENT(num_escapees/total_players)]%)") - to_chat(world, "
    [GLOB.TAB](on emergency shuttle): [num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)") - news_report = STATION_EVACUATED - if(SSshuttle.emergency.is_hijacked()) - news_report = SHUTTLE_HIJACK - to_chat(world, "
    [GLOB.TAB]Survival Rate: [num_survivors] ([PERCENT(num_survivors/total_players)]%)") - to_chat(world, "
    ") - - CHECK_TICK - - //Silicon laws report - for (var/i in GLOB.ai_list) - var/mob/living/silicon/ai/aiPlayer = i - if (aiPlayer.stat != DEAD && aiPlayer.mind) - to_chat(world, "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws at the end of the round were:") - aiPlayer.show_laws(1) - else if (aiPlayer.mind) //if the dead ai has a mind, use its key instead - to_chat(world, "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws when it was deactivated were:") - aiPlayer.show_laws(1) - - to_chat(world, "Total law changes: [aiPlayer.law_change_counter]") - - if (aiPlayer.connected_robots.len) - var/robolist = "[aiPlayer.real_name]'s minions were: " - for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots) - if(robo.mind) - robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]" - to_chat(world, "[robolist]") - - CHECK_TICK - - for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs) - if (!robo.connected_ai && robo.mind) - if (robo.stat != DEAD) - to_chat(world, "[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:") - else - to_chat(world, "[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:") - - if(robo) //How the hell do we lose robo between here and the world messages directly above this? - robo.laws.show_laws(world) - - CHECK_TICK - - mode.declare_completion()//To declare normal completion. - - CHECK_TICK - - //calls auto_declare_completion_* for all modes - for(var/handler in typesof(/datum/game_mode/proc)) - if (findtext("[handler]","auto_declare_completion_")) - call(mode, handler)(force_ending) - - CHECK_TICK - - if(CONFIG_GET(string/cross_server_address)) - send_news_report() - - CHECK_TICK - - //Print a list of antagonists to the server log - var/list/total_antagonists = list() - //Look into all mobs in world, dead or alive - for(var/datum/mind/Mind in minds) - var/temprole = Mind.special_role - if(temprole) //if they are an antagonist of some sort. - if(temprole in total_antagonists) //If the role exists already, add the name to it - total_antagonists[temprole] += ", [Mind.name]([Mind.key])" - else - total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob - total_antagonists[temprole] += ": [Mind.name]([Mind.key])" - - CHECK_TICK - - //Now print them all into the log! - log_game("Antagonists at round end were...") - for(var/i in total_antagonists) - log_game("[i]s[total_antagonists[i]].") - - CHECK_TICK - - for(var/datum/mind/crewMind in minds) - if(!crewMind.current || !crewMind.objectives.len) - continue - for(var/datum/objective/miscreant/MO in crewMind.objectives) - miscreants += "[crewMind.current.real_name] (Played by: [crewMind.key])
    Objective: [MO.explanation_text] (Optional)" - for(var/datum/objective/crew/CO in crewMind.objectives) - if(CO.check_completion()) - to_chat(crewMind.current, "
    Your optional objective: [CO.explanation_text] Success!") - successfulCrew += "[crewMind.current.real_name] (Played by: [crewMind.key])
    Objective: [CO.explanation_text] Success! (Optional)" - else - to_chat(crewMind.current, "
    Your optional objective: [CO.explanation_text] Failed.") - - if (successfulCrew.len) - var/completedObjectives = "The following crew members completed their Crew Objectives:
    " - for(var/i in successfulCrew) - completedObjectives += "[i]
    " - to_chat(world, "[completedObjectives]
    ") - else - if(CONFIG_GET(flag/allow_crew_objectives)) - to_chat(world, "Nobody completed their Crew Objectives!
    ") - - CHECK_TICK - - if (miscreants.len) - var/miscreantObjectives = "The following crew members were miscreants:
    " - for(var/i in miscreants) - miscreantObjectives += "[i]
    " - to_chat(world, "[miscreantObjectives]
    ") - - CHECK_TICK - - mode.declare_station_goal_completion() - - CHECK_TICK - //medals, placed far down so that people can actually see the commendations. - if(GLOB.commendations.len) - to_chat(world, "Medal Commendations:") - for (var/com in GLOB.commendations) - to_chat(world, com) - - CHECK_TICK - - //Collects persistence features - if(mode.allow_persistence_save) - SSpersistence.CollectData() - - //stop collecting feedback during grifftime - SSblackbox.Seal() - - sleep(50) - ready_for_reboot = TRUE - standard_reboot() - -/datum/controller/subsystem/ticker/proc/standard_reboot() - if(ready_for_reboot) - if(mode.station_was_nuked) - Reboot("Station destroyed by Nuclear Device.", "nuke") - else - Reboot("Round ended.", "proper completion") - else - CRASH("Attempted standard reboot without ticker roundend completion") - -======= ->>>>>>> 3d81385... Roundend report refactor (#33246) /datum/controller/subsystem/ticker/proc/send_tip_of_the_round() var/m if(selected_tip) From 98d752fe215851f39f7db700dac8248f59651f43 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:34:27 -0600 Subject: [PATCH 25/96] Update traitor_bro.dm --- code/game/gamemodes/brother/traitor_bro.dm | 35 ---------------------- 1 file changed, 35 deletions(-) diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index 34373da5c8..978f871ba2 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -62,41 +62,6 @@ /datum/game_mode/traitor/bros/generate_report() return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust." -<<<<<<< HEAD -/datum/game_mode/proc/auto_declare_completion_brother() - if(!LAZYLEN(brother_teams)) - return - var/text = "
    The blood brothers were:" - var/teamnumber = 1 - for(var/datum/objective_team/brother_team/team in brother_teams) - if(!team.members.len) - continue - text += "
    Team #[teamnumber++]" - for(var/datum/mind/M in team.members) - text += printplayer(M) - var/win = TRUE - var/objective_count = 1 - for(var/datum/objective/objective in team.objectives) - if(objective.check_completion()) - text += "
    Objective #[objective_count]: [objective.explanation_text] Success! [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" - SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "SUCCESS")) - else - text += "
    Objective #[objective_count]: [objective.explanation_text] Fail. [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" - SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "FAIL")) - if(!(istype(objective, /datum/objective/crew))) - win = FALSE - objective_count++ - if(win) - text += "
    The blood brothers were successful!" - SSblackbox.record_feedback("tally", "brother_success", 1, "SUCCESS") - else - text += "
    The blood brothers have failed!" - SSblackbox.record_feedback("tally", "brother_success", 1, "FAIL") - text += "
    " - to_chat(world, text) - -======= ->>>>>>> 3d81385... Roundend report refactor (#33246) /datum/game_mode/proc/update_brother_icons_added(datum/mind/brother_mind) var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER] brotherhud.join_hud(brother_mind.current) From cb8c6cd5e2484365c55d6134a384fd513ebdb182 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:34:38 -0600 Subject: [PATCH 26/96] Update changeling.dm --- code/game/gamemodes/changeling/changeling.dm | 44 -------------------- 1 file changed, 44 deletions(-) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 6fc06f7bca..ad76d41d47 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -94,50 +94,6 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th of the Thing being sent to a station in this sector is highly likely. It may be in the guise of any crew member. Trust nobody - suspect everybody. Do not announce this to the crew, \ as paranoia may spread and inhibit workplace efficiency." -<<<<<<< HEAD -/datum/game_mode/proc/auto_declare_completion_changeling() - var/list/changelings = get_antagonists(/datum/antagonist/changeling,TRUE) //Only real lings get a mention - if(changelings.len) - var/text = "
    The changelings were:" - for(var/datum/mind/changeling in changelings) - var/datum/antagonist/changeling/ling = changeling.has_antag_datum(/datum/antagonist/changeling) - var/changelingwin = 1 - if(!changeling.current) - changelingwin = 0 - - text += printplayer(changeling) - - //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed. - text += "
    Changeling ID: [ling.changelingID]." - text += "
    Genomes Extracted: [ling.absorbedcount]" - - if(changeling.objectives.len) - var/count = 1 - for(var/datum/objective/objective in changeling.objectives) - if(objective.check_completion()) - text += "
    Objective #[count]: [objective.explanation_text] Success! [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" - SSblackbox.record_feedback("nested tally", "changeling_objective", 1, list("[objective.type]", "SUCCESS")) - else - text += "
    Objective #[count]: [objective.explanation_text] Fail. [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" - SSblackbox.record_feedback("nested tally", "changeling_objective", 1, list("[objective.type]", "FAIL")) - if(!(istype(objective, /datum/objective/crew))) - changelingwin = 0 - count++ - - if(changelingwin) - text += "
    The changeling was successful!" - SSblackbox.record_feedback("tally", "changeling_success", 1, "SUCCESS") - else - text += "
    The changeling has failed." - SSblackbox.record_feedback("tally", "changeling_success", 1, "FAIL") - text += "
    " - - to_chat(world, text) - - return 1 - -======= ->>>>>>> 3d81385... Roundend report refactor (#33246) /proc/changeling_transform(mob/living/carbon/human/user, datum/changelingprofile/chosen_prof) var/datum/dna/chosen_dna = chosen_prof.dna user.real_name = chosen_prof.name From 61c7080c34e5c5490228a6bc763c444f3ed58bfd Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:34:59 -0600 Subject: [PATCH 27/96] Update game_mode.dm --- code/game/gamemodes/game_mode.dm | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 0c6a8fd1e0..71824c4590 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -450,8 +450,6 @@ /datum/game_mode/proc/OnNukeExplosion(off_station) if(off_station < 2) station_was_nuked = TRUE //Will end the round on next check. -<<<<<<< HEAD -======= //Additional report section in roundend report /datum/game_mode/proc/special_report() @@ -466,4 +464,3 @@ SSticker.news_report = STATION_EVACUATED if(SSshuttle.emergency.is_hijacked()) SSticker.news_report = SHUTTLE_HIJACK ->>>>>>> 3d81385... Roundend report refactor (#33246) From 2d65e0df49aed7715aec38161214e9bb24127913 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:35:29 -0600 Subject: [PATCH 28/96] Update nuclear.dm --- code/game/gamemodes/nuclear/nuclear.dm | 127 ------------------------- 1 file changed, 127 deletions(-) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index c7fc1bfdc8..a6eb199322 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -171,88 +171,6 @@ return FALSE //its a static var btw ..() -<<<<<<< HEAD -/datum/game_mode/nuclear/declare_completion() - var/disk_rescued = 1 - for(var/obj/item/disk/nuclear/D in GLOB.poi_list) - if(!D.onCentCom()) - disk_rescued = 0 - break - var/crew_evacuated = (SSshuttle.emergency.mode == SHUTTLE_ENDGAME) - - if(nuke_off_station == NUKE_SYNDICATE_BASE) - SSticker.mode_result = "loss - syndicate nuked - disk secured" - to_chat(world, "Humiliating Syndicate Defeat") - to_chat(world, "The crew of [station_name()] gave [syndicate_name()] operatives back their bomb! The syndicate base was destroyed! Next time, don't lose the nuke!") - - SSticker.news_report = NUKE_SYNDICATE_BASE - - else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape) - SSticker.mode_result = "win - syndicate nuke" - to_chat(world, "Syndicate Major Victory!") - to_chat(world, "[syndicate_name()] operatives have destroyed [station_name()]!") - - SSticker.news_report = STATION_NUKED - - else if (!disk_rescued && station_was_nuked && syndies_didnt_escape) - SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time" - to_chat(world, "Total Annihilation") - to_chat(world, "[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!") - - SSticker.news_report = STATION_NUKED - - else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape) - SSticker.mode_result = "halfwin - blew wrong station" - to_chat(world, "Crew Minor Victory") - to_chat(world, "[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't do that!") - - SSticker.news_report = NUKE_MISS - - else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape) - SSticker.mode_result = "halfwin - blew wrong station - did not evacuate in time" - to_chat(world, "[syndicate_name()] operatives have earned Darwin Award!") - to_chat(world, "[syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't do that!") - - SSticker.news_report = NUKE_MISS - - else if ((disk_rescued || SSshuttle.emergency.mode != SHUTTLE_ENDGAME) && are_operatives_dead()) - SSticker.mode_result = "loss - evacuation - disk secured - syndi team dead" - to_chat(world, "Crew Major Victory!") - to_chat(world, "The Research Staff has saved the disk and killed the [syndicate_name()] Operatives") - - SSticker.news_report = OPERATIVES_KILLED - - else if (disk_rescued) - SSticker.mode_result = "loss - evacuation - disk secured" - to_chat(world, "Crew Major Victory") - to_chat(world, "The Research Staff has saved the disk and stopped the [syndicate_name()] Operatives!") - - SSticker.news_report = OPERATIVES_KILLED - - else if (!disk_rescued && are_operatives_dead()) - SSticker.mode_result = "halfwin - evacuation - disk not secured" - to_chat(world, "Neutral Victory!") - to_chat(world, "The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!") - - SSticker.news_report = OPERATIVE_SKIRMISH - - else if (!disk_rescued && crew_evacuated) - SSticker.mode_result = "halfwin - detonation averted" - to_chat(world, "Syndicate Minor Victory!") - to_chat(world, "[syndicate_name()] operatives survived the assault but did not achieve the destruction of [station_name()]. Next time, don't lose the disk!") - - SSticker.news_report = OPERATIVE_SKIRMISH - - else if (!disk_rescued && !crew_evacuated) - SSticker.mode_result = "halfwin - interrupted" - to_chat(world, "Neutral Victory") - to_chat(world, "Round was mysteriously interrupted!") - - SSticker.news_report = OPERATIVE_SKIRMISH - - ..() - return -======= /datum/game_mode/nuclear/set_round_result() var result = nuke_team.get_result() switch(result) @@ -287,57 +205,12 @@ SSticker.mode_result = "halfwin - interrupted" SSticker.news_report = OPERATIVE_SKIRMISH return ..() ->>>>>>> 3d81385... Roundend report refactor (#33246) /datum/game_mode/nuclear/generate_report() return "One of Central Command's trading routes was recently disrupted by a raid carried out by the Gorlex Marauders. They seemed to only be after one ship - a highly-sensitive \ transport containing a nuclear fission explosive, although it is useless without the proper code and authorization disk. While the code was likely found in minutes, the only disk that \ can activate this explosive is on your station. Ensure that it is protected at all times, and remain alert for possible intruders." -<<<<<<< HEAD -/datum/game_mode/proc/auto_declare_completion_nuclear() - if( syndicates.len || (SSticker && istype(SSticker.mode, /datum/game_mode/nuclear)) ) - var/text = "
    The syndicate operatives were:" - var/purchases = "" - var/TC_uses = 0 - for(var/datum/mind/syndicate in syndicates) - text += printplayer(syndicate) - for(var/datum/component/uplink/H in GLOB.uplinks) - if(H.purchase_log) - purchases += H.purchase_log.generate_render() - else - stack_trace("WARNING: Uplink with no purchase_log in nuclear mode! Owner: [H.owner]") - text += "
    " - text += "(Syndicates used [TC_uses] TC) [purchases]" - if(TC_uses == 0 && station_was_nuked && !are_operatives_dead()) - text += "[icon2html('icons/badass.dmi', world, "badass")]" - to_chat(world, text) - return TRUE - - -/proc/nukelastname(mob/M) //--All praise goes to NEO|Phyte, all blame goes to DH, and it was Cindi-Kate's idea. Also praise Urist for copypasta ho. - var/randomname = pick(GLOB.last_names) - var/newname = copytext(sanitize(input(M,"You are the nuke operative [pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")]. Please choose a last name for your family.", "Name change",randomname)),1,MAX_NAME_LEN) - - if (!newname) - newname = randomname - - else - if (newname == "Unknown" || newname == "floor" || newname == "wall" || newname == "rwall" || newname == "_") - to_chat(M, "That name is reserved.") - return nukelastname(M) - - return capitalize(newname) - -/proc/NukeNameAssign(lastname,list/syndicates) - for(var/datum/mind/synd_mind in syndicates) - var/mob/living/carbon/human/H = synd_mind.current - synd_mind.name = H.dna.species.random_name(H.gender,0,lastname) - synd_mind.current.real_name = synd_mind.name - return - -======= ->>>>>>> 3d81385... Roundend report refactor (#33246) /proc/is_nuclear_operative(mob/M) return M && istype(M) && M.mind && SSticker && SSticker.mode && M.mind in SSticker.mode.syndicates From a30de42820db062adab30126aee731ffa5e55f7c Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:35:45 -0600 Subject: [PATCH 29/96] Update traitor.dm --- code/game/gamemodes/traitor/traitor.dm | 72 -------------------------- 1 file changed, 72 deletions(-) diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 468725074d..42c96cb5c0 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -86,78 +86,6 @@ new_antag.should_specialise = TRUE character.add_antag_datum(new_antag) -<<<<<<< HEAD - - -/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/auto_declare_completion_traitor() - if(traitors.len) - var/text = "
    The [traitor_name]s were:" - for(var/datum/mind/traitor in traitors) - var/traitorwin = TRUE - - text += printplayer(traitor) - - var/TC_uses = 0 - var/uplink_true = FALSE - var/purchases = "" - for(var/datum/component/uplink/H in GLOB.uplinks) - if(H && H.owner && H.owner == traitor.key) - TC_uses += H.spent_telecrystals - uplink_true = TRUE - purchases += H.purchase_log.generate_render(FALSE) - - var/objectives = "" - if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this. - var/count = 1 - for(var/datum/objective/objective in traitor.objectives) - if(objective.check_completion()) - objectives += "
    Objective #[count]: [objective.explanation_text] Success! [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" - SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "SUCCESS")) - else - objectives += "
    Objective #[count]: [objective.explanation_text] Fail. [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" - SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "FAIL")) - if(!(istype(objective, /datum/objective/crew))) - traitorwin = FALSE - 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 += "[icon2html(badass, world)]" - - text += objectives - - var/special_role_text - if(traitor.special_role) - special_role_text = lowertext(traitor.special_role) - else - special_role_text = "antagonist" - - - if(traitorwin) - text += "
    The [special_role_text] was successful!" - SSblackbox.record_feedback("tally", "traitor_success", 1, "SUCCESS") - else - text += "
    The [special_role_text] has failed!" - SSblackbox.record_feedback("tally", "traitor_success", 1, "FAIL") - SEND_SOUND(traitor.current, 'sound/ambience/ambifailure.ogg') - - text += "
    " - - text += "
    The code phrases were: [GLOB.syndicate_code_phrase]
    \ - The code responses were: [GLOB.syndicate_code_response]
    " - to_chat(world, text) - - return TRUE - -======= ->>>>>>> 3d81385... Roundend report refactor (#33246) /datum/game_mode/traitor/generate_report() return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \ Nanotrasen employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions." From 7d193a530322b0ea2d3755b5441450d5ff244a8d Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:35:57 -0600 Subject: [PATCH 30/96] Update wizard.dm --- code/game/gamemodes/wizard/wizard.dm | 45 ---------------------------- 1 file changed, 45 deletions(-) diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 6dd38e9d58..0d9655ae8e 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -64,54 +64,9 @@ SSticker.mode_result = "loss - wizard killed" SSticker.news_report = WIZARD_KILLED -<<<<<<< HEAD - for(var/datum/mind/wizard in wizards) - - text += "
    [wizard.key] was [wizard.name] (" - if(wizard.current) - if(wizard.current.stat == DEAD) - text += "died" - else - text += "survived" - if(wizard.current.real_name != wizard.name) - text += " as [wizard.current.real_name]" - else - text += "body destroyed" - text += ")" - - var/count = 1 - var/wizardwin = 1 - for(var/datum/objective/objective in wizard.objectives) - if(objective.check_completion()) - text += "
    Objective #[count]: [objective.explanation_text] Success! [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" - SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "SUCCESS")) - else - text += "
    Objective #[count]: [objective.explanation_text] Fail. [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" - SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "FAIL")) - if(!(istype(objective, /datum/objective/crew))) - wizardwin = 0 - count++ - - if(wizard.current && wizardwin) - text += "
    The wizard was successful!" - SSblackbox.record_feedback("tally", "wizard_success", 1, "SUCCESS") - else - text += "
    The wizard has failed!" - SSblackbox.record_feedback("tally", "wizard_success", 1, "FAIL") - if(wizard.spell_list.len>0) - text += "
    [wizard.name] used the following spells: " - var/i = 1 - for(var/obj/effect/proc_holder/spell/S in wizard.spell_list) - text += "[S.name]" - if(wizard.spell_list.len > i) - text += ", " - i++ - text += "
    " -======= /datum/game_mode/wizard/special_report() if(finished) return "The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!" ->>>>>>> 3d81385... Roundend report refactor (#33246) //returns whether the mob is a wizard (or apprentice) /proc/iswizard(mob/living/M) From 5ed003a0f5c80bafe74db8b1746e559ea4f31e00 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 15:36:07 -0600 Subject: [PATCH 31/96] Update client_defines.dm --- code/modules/client/client_defines.dm | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index a7e3b20e7a..10d3866672 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -68,9 +68,6 @@ var/datum/chatOutput/chatOutput -<<<<<<< HEAD -======= var/list/credits //lazy list of all credit object bound to this client var/datum/player_details/player_details //these persist between logins/logouts during the same round. ->>>>>>> 3d81385... Roundend report refactor (#33246) From 0a05b499fd26f2e95257b89c919cd2293b085657 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 17:14:57 -0600 Subject: [PATCH 32/96] Update cleanable.dm --- code/game/objects/effects/decals/cleanable.dm | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 0e0c7c606e..031e5059b3 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -46,11 +46,8 @@ if(istype(W, /obj/item/clothing/mask/cigarette)) return else - var/hotness = W.is_hot() - var/added_heat = (hotness / 100) - src.reagents.chem_temp = min(src.reagents.chem_temp + added_heat, hotness) - src.reagents.handle_reactions() - to_chat(user, "You heat [src] with [W]!") + reagents.expose_temperature(hotness) + to_chat(user, "You heat [name] with [W]!") else return ..() @@ -62,8 +59,7 @@ /obj/effect/decal/cleanable/fire_act(exposed_temperature, exposed_volume) if(reagents) - reagents.chem_temp += 30 - reagents.handle_reactions() + reagents.expose_temperature(exposed_temperature) ..() From 5e0ddfce60ae9d6aefa090f87977c36ffa071eae Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 17:15:37 -0600 Subject: [PATCH 33/96] Update drinks.dm --- code/modules/food_and_drinks/drinks/drinks.dm | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index c03b183ecc..5eae2b80d8 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -94,12 +94,10 @@ else /obj/item/reagent_containers/food/drinks/attackby(obj/item/I, mob/user, params) - if(I.is_hot()) - var/added_heat = (I.is_hot() / 100) //ishot returns a temperature - if(reagents) - reagents.chem_temp += added_heat - to_chat(user, "You heat [src] with [I].") - reagents.handle_reactions() + var/hotness = I.is_hot() + if(hotness && reagents) + reagents.expose_temperature(hotness) + to_chat(user, "You heat [name] with [I]!") ..() /obj/item/reagent_containers/food/drinks/throw_impact(atom/target, mob/thrower) From 9e452adcc83c25ee9decc8412c0a49f051699e07 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 17:16:45 -0600 Subject: [PATCH 34/96] Update holder.dm --- code/modules/reagents/chemistry/holder.dm | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 5958dc0eab..737e07c2a8 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -241,8 +241,7 @@ var/list/cached_reagents = reagent_list var/list/cached_addictions = addiction_list if(C) - chem_temp = C.bodytemperature - handle_reactions() + expose_temperature(C.bodytemperature, 0.25) var/need_mob_update = 0 for(var/reagent in cached_reagents) var/datum/reagent/R = reagent @@ -744,6 +743,16 @@ out += "[taste_desc]" return english_list(out, "something indescribable") + + +/datum/reagents/proc/expose_temperature(var/temperature, var/coeff=0.02) + var/temp_delta = (temperature - chem_temp) * coeff + if(temp_delta > 0) + chem_temp = min(chem_temp + max(temp_delta, 1), temperature) + else + chem_temp = max(chem_temp + min(temp_delta, -1), temperature) + chem_temp = round(chem_temp) + handle_reactions() /////////////////////////////////////////////////////////////////////////////////// From 39b016306cf60c4662036d0f1828b6103330c162 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 17:17:54 -0600 Subject: [PATCH 35/96] Update reagent_containers.dm --- code/modules/reagents/reagent_containers.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 2645997d22..6fb21e847b 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -71,8 +71,7 @@ ..() /obj/item/reagent_containers/fire_act(exposed_temperature, exposed_volume) - reagents.chem_temp += 30 - reagents.handle_reactions() + reagents.expose_temperature(exposed_temperature) ..() /obj/item/reagent_containers/throw_impact(atom/target) @@ -120,3 +119,6 @@ /obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M) reagents.expose_temperature(1000) ..() + +/obj/item/reagent_containers/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + reagents.expose_temperature(exposed_temperature) From fdfdaa230a55509f8b2b0b06f3c982222e6d1d29 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 17:18:27 -0600 Subject: [PATCH 36/96] Update glass.dm --- code/modules/reagents/reagent_containers/glass.dm | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 33a45fd27b..06a242cca9 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -89,15 +89,9 @@ /obj/item/reagent_containers/glass/attackby(obj/item/I, mob/user, params) var/hotness = I.is_hot() - if(hotness) - var/added_heat = (hotness / 100) //ishot returns a temperature - if(reagents) - if(reagents.chem_temp < hotness) //can't be heated to be hotter than the source - reagents.chem_temp += added_heat - to_chat(user, "You heat [src] with [I].") - reagents.handle_reactions() - else - to_chat(user, "[src] is already hotter than [I]!") + if(hotness && reagents) + reagents.expose_temperature(hotness) + to_chat(user, "You heat [name] with [I]!") if(istype(I, /obj/item/reagent_containers/food/snacks/egg)) //breaking eggs var/obj/item/reagent_containers/food/snacks/egg/E = I @@ -403,4 +397,4 @@ /obj/item/reagent_containers/glass/beaker/large/bromine name = "bromine beaker" - list_reagents = list("bromine" = 50) \ No newline at end of file + list_reagents = list("bromine" = 50) From 349b0f4f20f100f441d63256897215b7513da887 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 17:19:05 -0600 Subject: [PATCH 37/96] Update spray.dm --- code/modules/reagents/reagent_containers/spray.dm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index f8158ba948..2e34e39f8f 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -123,6 +123,14 @@ current_range = spray_range to_chat(user, "You switch the nozzle setting to [stream_mode ? "\"stream\"":"\"spray\""]. You'll now use [amount_per_transfer_from_this] units per use.") +/obj/item/reagent_containers/spray/attackby(obj/item/I, mob/user, params) + var/hotness = I.is_hot() + if(hotness && reagents) + reagents.expose_temperature(hotness) + to_chat(user, "You heat [name] with [I]!") + return ..() + + /obj/item/reagent_containers/spray/verb/empty() set name = "Empty Spray Bottle" set category = "Object" From a0a4acbc2c9f8d21b828d27262d7d7cdcaab6b8b Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 17:33:55 -0600 Subject: [PATCH 38/96] Update nuclear.dm --- code/game/gamemodes/nuclear/nuclear.dm | 153 +++++-------------------- 1 file changed, 31 insertions(+), 122 deletions(-) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index a6eb199322..f131046cac 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -1,7 +1,3 @@ -/datum/game_mode - var/list/datum/mind/syndicates = list() - var/nukeops_lastname = "" - /datum/game_mode/nuclear name = "nuclear emergency" config_tag = "nuclear" @@ -18,12 +14,11 @@ Crew: Defend the nuclear authentication disk and ensure that it leaves with you on the emergency shuttle." var/const/agents_possible = 5 //If we ever need more syndicate agents. - var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! - var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station - var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level var/list/pre_nukeops = list() + var/datum/team/nuclear/nuke_team + /datum/game_mode/nuclear/pre_setup() var/n_agents = min(round(num_players() / 10), antag_candidates.len, agents_possible) for(var/i = 0, i < n_agents, ++i) @@ -33,120 +28,23 @@ new_op.special_role = "Nuclear Operative" log_game("[new_op.key] (ckey) has been selected as a nuclear operative") return TRUE - -//////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) - var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] - opshud.join_hud(synd_mind.current) - set_antag_hud(synd_mind.current, "synd") - -/datum/game_mode/proc/update_synd_icons_removed(datum/mind/synd_mind) - var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] - opshud.leave_hud(synd_mind.current) - set_antag_hud(synd_mind.current, null) - //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// /datum/game_mode/nuclear/post_setup() - var/nuke_code = random_nukecode() - var/agent_number = 1 - var/datum/mind/leader = pick(pre_nukeops) - syndicates += pre_nukeops - for(var/i = 1 to pre_nukeops.len) - var/datum/mind/op = pre_nukeops[i] - - forge_syndicate_objectives(op) - greet_syndicate(op) - equip_syndicate(op.current) - - if(nuke_code) - op.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0) - to_chat(op.current, "The nuclear authorization code is: [nuke_code]") - - if(op == leader) - op.current.forceMove(pick(GLOB.nukeop_leader_start)) - prepare_syndicate_leader(op, nuke_code) - else - op.current.forceMove(GLOB.nukeop_start[((i - 1) % GLOB.nukeop_start.len) + 1]) - op.current.real_name = "[syndicate_name()] Operative #[agent_number++]" - - update_synd_icons_added(op) - op.current.playsound_local(get_turf(op.current), 'sound/ambience/antag/ops.ogg',100,0) - - var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list - if(nuke) - nuke.r_code = nuke_code + //Assign leader + var/datum/mind/leader_mind = pre_nukeops[1] + var/datum/antagonist/nukeop/L = leader_mind.add_antag_datum(/datum/antagonist/nukeop/leader) + nuke_team = L.nuke_team + //Assign the remaining operatives + for(var/i = 2 to pre_nukeops.len) + var/datum/mind/nuke_mind = pre_nukeops[i] + nuke_mind.add_antag_datum(/datum/antagonist/nukeop,nuke_team) return ..() -/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code) - var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord") - addtimer(CALLBACK(src, .proc/nuketeam_name_assign, synd_mind), 1) - synd_mind.current.real_name = "[syndicate_name()] [leader_title]" - to_chat(synd_mind.current, "You are the Syndicate [leader_title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.") - to_chat(synd_mind.current, "If you feel you are not up to this task, give your ID to another operative.") - to_chat(synd_mind.current, "In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.") - - var/obj/item/device/nuclear_challenge/challenge = new /obj/item/device/nuclear_challenge - synd_mind.current.put_in_hands(challenge, TRUE) - - var/static/id_cache = typecacheof(/obj/item/card/id) - var/list/foundIDs = typecache_filter_list(synd_mind.current.GetAllContents(), id_cache) - if(foundIDs.len) - for(var/i in 1 to foundIDs.len) - var/obj/item/card/id/ID = foundIDs[i] - ID.name = "lead agent card" - ID.access += ACCESS_SYNDICATE_LEADER - else - message_admins("Warning: Nuke Ops spawned without access to leave their spawn area!") - - var/obj/item/device/radio/headset/syndicate/alt/A = locate() in synd_mind.current - if(A) - A.command = TRUE - - if(nuke_code) - var/obj/item/paper/P = new - P.info = "The nuclear authorization code is: [nuke_code]" - P.name = "nuclear bomb code" - var/mob/living/carbon/human/H = synd_mind.current - H.put_in_hands(P, TRUE) - H.update_icons() - else - nuke_code = "code will be provided later" - return - -/datum/game_mode/proc/nuketeam_name_assign(datum/mind/synd_mind) - nukeops_lastname = nukelastname(synd_mind.current) - NukeNameAssign(nukeops_lastname, syndicates) - - -/datum/game_mode/proc/forge_syndicate_objectives(datum/mind/syndicate) - var/datum/objective/nuclear/syndobj = new - syndobj.owner = syndicate - syndicate.objectives += syndobj - - -/datum/game_mode/proc/greet_syndicate(datum/mind/syndicate, you_are=1) - if(you_are) - to_chat(syndicate.current, "You are a [syndicate_name()] agent!") - syndicate.announce_objectives() - -/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob, telecrystals = TRUE) - synd_mob.set_species(/datum/species/human) //Plasamen burn up otherwise, and lizards are vulnerable to asimov AIs - - if(telecrystals) - synd_mob.equipOutfit(/datum/outfit/syndicate) - else - synd_mob.equipOutfit(/datum/outfit/syndicate/no_crystals) - return TRUE - /datum/game_mode/nuclear/OnNukeExplosion(off_station) ..() nukes_left-- - var/obj/docking_port/mobile/Shuttle = SSshuttle.getShuttle("syndicate") - syndies_didnt_escape = (Shuttle && (Shuttle.z == ZLEVEL_CENTCOM || Shuttle.z == ZLEVEL_TRANSIT)) ? 0 : 1 - nuke_off_station = off_station /datum/game_mode/nuclear/check_win() if (nukes_left == 0) @@ -154,8 +52,8 @@ return ..() /datum/game_mode/proc/are_operatives_dead() - for(var/datum/mind/operative_mind in syndicates) - if(ishuman(operative_mind.current) && (operative_mind.current.stat!=2)) + for(var/datum/mind/operative_mind in get_antagonists(/datum/antagonist/nukeop)) + if(ishuman(operative_mind.current) && (operative_mind.current.stat != DEAD)) return FALSE return TRUE @@ -164,7 +62,7 @@ return replacementmode.check_finished() if((SSshuttle.emergency.mode == SHUTTLE_ENDGAME) || station_was_nuked) return TRUE - if(are_operatives_dead()) + if(nuke_team.operatives_dead()) var/obj/machinery/nuclearbomb/N pass(N) //suppress unused warning if(N.bomb_set) //snaaaaaaaaaake! It's not over yet! @@ -172,6 +70,7 @@ ..() /datum/game_mode/nuclear/set_round_result() + ..() var result = nuke_team.get_result() switch(result) if(NUKE_RESULT_FLUKE) @@ -204,7 +103,6 @@ else SSticker.mode_result = "halfwin - interrupted" SSticker.news_report = OPERATIVE_SKIRMISH - return ..() /datum/game_mode/nuclear/generate_report() return "One of Central Command's trading routes was recently disrupted by a raid carried out by the Gorlex Marauders. They seemed to only be after one ship - a highly-sensitive \ @@ -212,7 +110,7 @@ can activate this explosive is on your station. Ensure that it is protected at all times, and remain alert for possible intruders." /proc/is_nuclear_operative(mob/M) - return M && istype(M) && M.mind && SSticker && SSticker.mode && M.mind in SSticker.mode.syndicates + return M && istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/nukeop) /datum/outfit/syndicate name = "Syndicate Operative - Basic" @@ -225,18 +123,28 @@ l_pocket = /obj/item/pinpointer/nuke/syndicate id = /obj/item/card/id/syndicate belt = /obj/item/gun/ballistic/automatic/pistol - backpack_contents = list(/obj/item/storage/box/syndie=1) + backpack_contents = list(/obj/item/storage/box/syndie=1,\ + /obj/item/kitchen/knife/combat/survival) var/tc = 25 + var/command_radio = FALSE + + +/datum/outfit/syndicate/leader + name = "Syndicate Leader - Basic" + id = /obj/item/card/id/syndicate/nuke_leader + r_hand = /obj/item/device/nuclear_challenge + command_radio = TRUE /datum/outfit/syndicate/no_crystals tc = 0 - /datum/outfit/syndicate/post_equip(mob/living/carbon/human/H) var/obj/item/device/radio/R = H.ears - R.set_frequency(GLOB.SYND_FREQ) - R.freqlock = 1 + R.set_frequency(FREQ_SYNDICATE) + R.freqlock = TRUE + if(command_radio) + R.command = TRUE if(tc) var/obj/item/device/radio/uplink/nuclear/U = new(H, H.key, tc) @@ -261,4 +169,5 @@ r_hand = /obj/item/gun/ballistic/automatic/shotgun/bulldog backpack_contents = list(/obj/item/storage/box/syndie=1,\ /obj/item/tank/jetpack/oxygen/harness=1,\ - /obj/item/gun/ballistic/automatic/pistol=1) + /obj/item/gun/ballistic/automatic/pistol=1,\ + /obj/item/kitchen/knife/combat/survival) From 1b6b8a7c00e78577985e4ebe5d37bf46cde433e5 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 17:46:15 -0600 Subject: [PATCH 39/96] Update cleanable.dm --- code/game/objects/effects/decals/cleanable.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 031e5059b3..f06525863d 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -46,6 +46,7 @@ if(istype(W, /obj/item/clothing/mask/cigarette)) return else + var/hotness = W.is_hot() reagents.expose_temperature(hotness) to_chat(user, "You heat [name] with [W]!") else From dfa53390dfda9e4b967d55ef346658b4d34f0f68 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Tue, 19 Dec 2017 19:12:26 -0600 Subject: [PATCH 40/96] Update nuclear.dm --- code/game/gamemodes/nuclear/nuclear.dm | 306 +++++++++++++++++++------ 1 file changed, 242 insertions(+), 64 deletions(-) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index f131046cac..94c372ef23 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -1,3 +1,7 @@ +/datum/game_mode + var/list/datum/mind/syndicates = list() + var/nukeops_lastname = "" + /datum/game_mode/nuclear name = "nuclear emergency" config_tag = "nuclear" @@ -14,10 +18,11 @@ Crew: Defend the nuclear authentication disk and ensure that it leaves with you on the emergency shuttle." var/const/agents_possible = 5 //If we ever need more syndicate agents. - var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! - var/list/pre_nukeops = list() - var/datum/team/nuclear/nuke_team + var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! + var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station + var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level + var/list/pre_nukeops = list() /datum/game_mode/nuclear/pre_setup() var/n_agents = min(round(num_players() / 10), antag_candidates.len, agents_possible) @@ -28,23 +33,120 @@ new_op.special_role = "Nuclear Operative" log_game("[new_op.key] (ckey) has been selected as a nuclear operative") return TRUE + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] + opshud.join_hud(synd_mind.current) + set_antag_hud(synd_mind.current, "synd") + +/datum/game_mode/proc/update_synd_icons_removed(datum/mind/synd_mind) + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] + opshud.leave_hud(synd_mind.current) + set_antag_hud(synd_mind.current, null) + //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// /datum/game_mode/nuclear/post_setup() - //Assign leader - var/datum/mind/leader_mind = pre_nukeops[1] - var/datum/antagonist/nukeop/L = leader_mind.add_antag_datum(/datum/antagonist/nukeop/leader) - nuke_team = L.nuke_team - //Assign the remaining operatives - for(var/i = 2 to pre_nukeops.len) - var/datum/mind/nuke_mind = pre_nukeops[i] - nuke_mind.add_antag_datum(/datum/antagonist/nukeop,nuke_team) + var/nuke_code = random_nukecode() + var/agent_number = 1 + var/datum/mind/leader = pick(pre_nukeops) + syndicates += pre_nukeops + for(var/i = 1 to pre_nukeops.len) + var/datum/mind/op = pre_nukeops[i] + + forge_syndicate_objectives(op) + greet_syndicate(op) + equip_syndicate(op.current) + + if(nuke_code) + op.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0) + to_chat(op.current, "The nuclear authorization code is: [nuke_code]") + + if(op == leader) + op.current.forceMove(pick(GLOB.nukeop_leader_start)) + prepare_syndicate_leader(op, nuke_code) + else + op.current.forceMove(GLOB.nukeop_start[((i - 1) % GLOB.nukeop_start.len) + 1]) + op.current.real_name = "[syndicate_name()] Operative #[agent_number++]" + + update_synd_icons_added(op) + op.current.playsound_local(get_turf(op.current), 'sound/ambience/antag/ops.ogg',100,0) + + var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list + if(nuke) + nuke.r_code = nuke_code return ..() +/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code) + var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord") + addtimer(CALLBACK(src, .proc/nuketeam_name_assign, synd_mind), 1) + synd_mind.current.real_name = "[syndicate_name()] [leader_title]" + to_chat(synd_mind.current, "You are the Syndicate [leader_title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.") + to_chat(synd_mind.current, "If you feel you are not up to this task, give your ID to another operative.") + to_chat(synd_mind.current, "In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.") + + var/obj/item/device/nuclear_challenge/challenge = new /obj/item/device/nuclear_challenge + synd_mind.current.put_in_hands(challenge, TRUE) + + var/static/id_cache = typecacheof(/obj/item/card/id) + var/list/foundIDs = typecache_filter_list(synd_mind.current.GetAllContents(), id_cache) + if(foundIDs.len) + for(var/i in 1 to foundIDs.len) + var/obj/item/card/id/ID = foundIDs[i] + ID.name = "lead agent card" + ID.access += ACCESS_SYNDICATE_LEADER + else + message_admins("Warning: Nuke Ops spawned without access to leave their spawn area!") + + var/obj/item/device/radio/headset/syndicate/alt/A = locate() in synd_mind.current + if(A) + A.command = TRUE + + if(nuke_code) + var/obj/item/paper/P = new + P.info = "The nuclear authorization code is: [nuke_code]" + P.name = "nuclear bomb code" + var/mob/living/carbon/human/H = synd_mind.current + H.put_in_hands(P, TRUE) + H.update_icons() + else + nuke_code = "code will be provided later" + return + +/datum/game_mode/proc/nuketeam_name_assign(datum/mind/synd_mind) + nukeops_lastname = nukelastname(synd_mind.current) + NukeNameAssign(nukeops_lastname, syndicates) + + +/datum/game_mode/proc/forge_syndicate_objectives(datum/mind/syndicate) + var/datum/objective/nuclear/syndobj = new + syndobj.owner = syndicate + syndicate.objectives += syndobj + + +/datum/game_mode/proc/greet_syndicate(datum/mind/syndicate, you_are=1) + if(you_are) + to_chat(syndicate.current, "You are a [syndicate_name()] agent!") + syndicate.announce_objectives() + +/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob, telecrystals = TRUE) + synd_mob.set_species(/datum/species/human) //Plasamen burn up otherwise, and lizards are vulnerable to asimov AIs + + if(telecrystals) + synd_mob.equipOutfit(/datum/outfit/syndicate) + else + synd_mob.equipOutfit(/datum/outfit/syndicate/no_crystals) + return TRUE + /datum/game_mode/nuclear/OnNukeExplosion(off_station) ..() nukes_left-- + var/obj/docking_port/mobile/Shuttle = SSshuttle.getShuttle("syndicate") + syndies_didnt_escape = (Shuttle && (Shuttle.z == ZLEVEL_CENTCOM || Shuttle.z == ZLEVEL_TRANSIT)) ? 0 : 1 + nuke_off_station = off_station /datum/game_mode/nuclear/check_win() if (nukes_left == 0) @@ -52,8 +154,8 @@ return ..() /datum/game_mode/proc/are_operatives_dead() - for(var/datum/mind/operative_mind in get_antagonists(/datum/antagonist/nukeop)) - if(ishuman(operative_mind.current) && (operative_mind.current.stat != DEAD)) + for(var/datum/mind/operative_mind in syndicates) + if(ishuman(operative_mind.current) && (operative_mind.current.stat!=2)) return FALSE return TRUE @@ -62,55 +164,142 @@ return replacementmode.check_finished() if((SSshuttle.emergency.mode == SHUTTLE_ENDGAME) || station_was_nuked) return TRUE - if(nuke_team.operatives_dead()) + if(are_operatives_dead()) var/obj/machinery/nuclearbomb/N pass(N) //suppress unused warning if(N.bomb_set) //snaaaaaaaaaake! It's not over yet! return FALSE //its a static var btw ..() -/datum/game_mode/nuclear/set_round_result() +/datum/game_mode/nuclear/declare_completion() + var/disk_rescued = 1 + for(var/obj/item/disk/nuclear/D in GLOB.poi_list) + if(!D.onCentCom()) + disk_rescued = 0 + break + var/crew_evacuated = (SSshuttle.emergency.mode == SHUTTLE_ENDGAME) + + if(nuke_off_station == NUKE_SYNDICATE_BASE) + SSticker.mode_result = "loss - syndicate nuked - disk secured" + to_chat(world, "Humiliating Syndicate Defeat") + to_chat(world, "The crew of [station_name()] gave [syndicate_name()] operatives back their bomb! The syndicate base was destroyed! Next time, don't lose the nuke!") + + SSticker.news_report = NUKE_SYNDICATE_BASE + + else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape) + SSticker.mode_result = "win - syndicate nuke" + to_chat(world, "Syndicate Major Victory!") + to_chat(world, "[syndicate_name()] operatives have destroyed [station_name()]!") + + SSticker.news_report = STATION_NUKED + + else if (!disk_rescued && station_was_nuked && syndies_didnt_escape) + SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time" + to_chat(world, "Total Annihilation") + to_chat(world, "[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!") + + SSticker.news_report = STATION_NUKED + + else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape) + SSticker.mode_result = "halfwin - blew wrong station" + to_chat(world, "Crew Minor Victory") + to_chat(world, "[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't do that!") + + SSticker.news_report = NUKE_MISS + + else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape) + SSticker.mode_result = "halfwin - blew wrong station - did not evacuate in time" + to_chat(world, "[syndicate_name()] operatives have earned Darwin Award!") + to_chat(world, "[syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't do that!") + + SSticker.news_report = NUKE_MISS + + else if ((disk_rescued || SSshuttle.emergency.mode != SHUTTLE_ENDGAME) && are_operatives_dead()) + SSticker.mode_result = "loss - evacuation - disk secured - syndi team dead" + to_chat(world, "Crew Major Victory!") + to_chat(world, "The Research Staff has saved the disk and killed the [syndicate_name()] Operatives") + + SSticker.news_report = OPERATIVES_KILLED + + else if (disk_rescued) + SSticker.mode_result = "loss - evacuation - disk secured" + to_chat(world, "Crew Major Victory") + to_chat(world, "The Research Staff has saved the disk and stopped the [syndicate_name()] Operatives!") + + SSticker.news_report = OPERATIVES_KILLED + + else if (!disk_rescued && are_operatives_dead()) + SSticker.mode_result = "halfwin - evacuation - disk not secured" + to_chat(world, "Neutral Victory!") + to_chat(world, "The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!") + + SSticker.news_report = OPERATIVE_SKIRMISH + + else if (!disk_rescued && crew_evacuated) + SSticker.mode_result = "halfwin - detonation averted" + to_chat(world, "Syndicate Minor Victory!") + to_chat(world, "[syndicate_name()] operatives survived the assault but did not achieve the destruction of [station_name()]. Next time, don't lose the disk!") + + SSticker.news_report = OPERATIVE_SKIRMISH + + else if (!disk_rescued && !crew_evacuated) + SSticker.mode_result = "halfwin - interrupted" + to_chat(world, "Neutral Victory") + to_chat(world, "Round was mysteriously interrupted!") + + SSticker.news_report = OPERATIVE_SKIRMISH + ..() - var result = nuke_team.get_result() - switch(result) - if(NUKE_RESULT_FLUKE) - SSticker.mode_result = "loss - syndicate nuked - disk secured" - SSticker.news_report = NUKE_SYNDICATE_BASE - if(NUKE_RESULT_NUKE_WIN) - SSticker.mode_result = "win - syndicate nuke" - SSticker.news_report = STATION_NUKED - if(NUKE_RESULT_NOSURVIVORS) - SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time" - SSticker.news_report = STATION_NUKED - if(NUKE_RESULT_WRONG_STATION) - SSticker.mode_result = "halfwin - blew wrong station" - SSticker.news_report = NUKE_MISS - if(NUKE_RESULT_WRONG_STATION_DEAD) - SSticker.mode_result = "halfwin - blew wrong station - did not evacuate in time" - SSticker.news_report = NUKE_MISS - if(NUKE_RESULT_CREW_WIN_SYNDIES_DEAD) - SSticker.mode_result = "loss - evacuation - disk secured - syndi team dead" - SSticker.news_report = OPERATIVES_KILLED - if(NUKE_RESULT_CREW_WIN) - SSticker.mode_result = "loss - evacuation - disk secured" - SSticker.news_report = OPERATIVES_KILLED - if(NUKE_RESULT_DISK_LOST) - SSticker.mode_result = "halfwin - evacuation - disk not secured" - SSticker.news_report = OPERATIVE_SKIRMISH - if(NUKE_RESULT_DISK_STOLEN) - SSticker.mode_result = "halfwin - detonation averted" - SSticker.news_report = OPERATIVE_SKIRMISH - else - SSticker.mode_result = "halfwin - interrupted" - SSticker.news_report = OPERATIVE_SKIRMISH + return /datum/game_mode/nuclear/generate_report() return "One of Central Command's trading routes was recently disrupted by a raid carried out by the Gorlex Marauders. They seemed to only be after one ship - a highly-sensitive \ transport containing a nuclear fission explosive, although it is useless without the proper code and authorization disk. While the code was likely found in minutes, the only disk that \ can activate this explosive is on your station. Ensure that it is protected at all times, and remain alert for possible intruders." +/datum/game_mode/proc/auto_declare_completion_nuclear() + if( syndicates.len || (SSticker && istype(SSticker.mode, /datum/game_mode/nuclear)) ) + var/text = "
    The syndicate operatives were:" + var/purchases = "" + var/TC_uses = 0 + for(var/datum/mind/syndicate in syndicates) + text += printplayer(syndicate) + for(var/datum/component/uplink/H in GLOB.uplinks) + if(H.purchase_log) + purchases += H.purchase_log.generate_render() + else + stack_trace("WARNING: Uplink with no purchase_log in nuclear mode! Owner: [H.owner]") + text += "
    " + text += "(Syndicates used [TC_uses] TC) [purchases]" + if(TC_uses == 0 && station_was_nuked && !are_operatives_dead()) + text += "[icon2html('icons/badass.dmi', world, "badass")]" + to_chat(world, text) + return TRUE + + +/proc/nukelastname(mob/M) //--All praise goes to NEO|Phyte, all blame goes to DH, and it was Cindi-Kate's idea. Also praise Urist for copypasta ho. + var/randomname = pick(GLOB.last_names) + var/newname = copytext(sanitize(input(M,"You are the nuke operative [pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")]. Please choose a last name for your family.", "Name change",randomname)),1,MAX_NAME_LEN) + + if (!newname) + newname = randomname + + else + if (newname == "Unknown" || newname == "floor" || newname == "wall" || newname == "rwall" || newname == "_") + to_chat(M, "That name is reserved.") + return nukelastname(M) + + return capitalize(newname) + +/proc/NukeNameAssign(lastname,list/syndicates) + for(var/datum/mind/synd_mind in syndicates) + var/mob/living/carbon/human/H = synd_mind.current + synd_mind.name = H.dna.species.random_name(H.gender,0,lastname) + synd_mind.current.real_name = synd_mind.name + return + /proc/is_nuclear_operative(mob/M) - return M && istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/nukeop) + return M && istype(M) && M.mind && SSticker && SSticker.mode && M.mind in SSticker.mode.syndicates /datum/outfit/syndicate name = "Syndicate Operative - Basic" @@ -123,28 +312,18 @@ l_pocket = /obj/item/pinpointer/nuke/syndicate id = /obj/item/card/id/syndicate belt = /obj/item/gun/ballistic/automatic/pistol - backpack_contents = list(/obj/item/storage/box/syndie=1,\ - /obj/item/kitchen/knife/combat/survival) + backpack_contents = list(/obj/item/storage/box/syndie=1) var/tc = 25 - var/command_radio = FALSE - - -/datum/outfit/syndicate/leader - name = "Syndicate Leader - Basic" - id = /obj/item/card/id/syndicate/nuke_leader - r_hand = /obj/item/device/nuclear_challenge - command_radio = TRUE /datum/outfit/syndicate/no_crystals tc = 0 + /datum/outfit/syndicate/post_equip(mob/living/carbon/human/H) var/obj/item/device/radio/R = H.ears - R.set_frequency(FREQ_SYNDICATE) - R.freqlock = TRUE - if(command_radio) - R.command = TRUE + R.set_frequency(GLOB.SYND_FREQ) + R.freqlock = 1 if(tc) var/obj/item/device/radio/uplink/nuclear/U = new(H, H.key, tc) @@ -169,5 +348,4 @@ r_hand = /obj/item/gun/ballistic/automatic/shotgun/bulldog backpack_contents = list(/obj/item/storage/box/syndie=1,\ /obj/item/tank/jetpack/oxygen/harness=1,\ - /obj/item/gun/ballistic/automatic/pistol=1,\ - /obj/item/kitchen/knife/combat/survival) + /obj/item/gun/ballistic/automatic/pistol=1) From 8a1ed708881310b760eaef93e4b23df0327d9adc Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 20 Dec 2017 00:08:37 -0600 Subject: [PATCH 41/96] Update roundend.dm --- code/__HELPERS/roundend.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 7bd08167e6..9ba1c767b7 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -71,10 +71,10 @@ if(LAZYLEN(GLOB.round_end_notifiees)) send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.") - for(var/client/C in GLOB.clients) + /*for(var/client/C in GLOB.clients) if(!C.credits) C.RollCredits() - C.playtitlemusic(40) + C.playtitlemusic(40)*/ display_report() @@ -409,4 +409,4 @@ else objective_parts += "Objective #[count]: [objective.explanation_text] Fail." count++ - return objective_parts.Join("
    ") \ No newline at end of file + return objective_parts.Join("
    ") From 5f69eac0503b6d225b25d395db5b67c048a229bd Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 20 Dec 2017 00:19:39 -0600 Subject: [PATCH 42/96] Update mind.dm --- code/datums/mind.dm | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 14d619c917..88d84eeb6c 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -202,12 +202,10 @@ SSticker.mode.update_brother_icons_removed(src) /datum/mind/proc/remove_nukeop() - if(src in SSticker.mode.syndicates) - SSticker.mode.syndicates -= src - SSticker.mode.update_synd_icons_removed(src) - special_role = null - remove_objectives() - remove_antag_equip() + var/datum/antagonist/nukeop/nuke = has_antag_datum(/datum/antagonist/nukeop,TRUE) + if(nuke) + remove_antag_datum(nuke.type) +special_role = null /datum/mind/proc/remove_wizard() remove_antag_datum(/datum/antagonist/wizard) From 00d3b8f1b7d831020d8ea187ce4d10185247fef9 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 20 Dec 2017 02:53:51 -0600 Subject: [PATCH 43/96] a lot of shit synced in this one commit. --- code/__HELPERS/roundend.dm | 20 ++++----- code/datums/antagonists/abductor.dm | 16 ++++---- code/datums/antagonists/antag_datum.dm | 6 +-- code/datums/antagonists/brother.dm | 18 ++++---- code/datums/antagonists/clockcult.dm | 18 ++++---- code/datums/antagonists/cult.dm | 30 +++++++------- code/datums/antagonists/pirate.dm | 25 ++++++----- code/datums/antagonists/revolution.dm | 36 ++++++++-------- code/datums/antagonists/wizard.dm | 14 +++---- code/datums/mind.dm | 12 +++--- code/game/gamemodes/antag_spawner.dm | 6 +-- code/game/gamemodes/brother/traitor_bro.dm | 8 ++-- code/game/gamemodes/clock_cult/clock_cult.dm | 9 ++-- code/game/gamemodes/cult/cult.dm | 10 ++--- code/game/gamemodes/cult/cult_comms.dm | 8 ++-- code/game/gamemodes/cult/runes.dm | 41 +++++++------------ code/game/gamemodes/game_mode.dm | 2 +- .../miniantags/abduction/abduction.dm | 16 ++++---- code/game/gamemodes/nuclear/nuclear.dm | 21 ++++------ code/game/gamemodes/revolution/revolution.dm | 2 +- code/game/gamemodes/wizard/soulstone.dm | 1 - code/modules/admin/player_panel.dm | 2 +- code/modules/admin/verbs/one_click_antag.dm | 15 ++++--- code/modules/power/singularity/narsie.dm | 2 +- tgstation.dme | 3 +- 25 files changed, 161 insertions(+), 180 deletions(-) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 9ba1c767b7..3b346f7e1c 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -47,7 +47,7 @@ antag_info["antagonist_name"] = A.name //For auto and custom roles antag_info["objectives"] = list() antag_info["team"] = list() - var/datum/objective_team/T = A.get_team() + var/datum/team/T = A.get_team() if(T) antag_info["team"]["type"] = T.type antag_info["team"]["name"] = T.name @@ -84,9 +84,9 @@ //Set news report and mode result mode.set_round_result() - + send2irc("Server", "Round just ended.") - + if(CONFIG_GET(string/cross_server_address)) send_news_report() @@ -142,15 +142,15 @@ parts += mode.special_report() CHECK_TICK - + //AI laws parts += law_report() - + CHECK_TICK //Antagonists parts += antag_report() - + CHECK_TICK //Medals parts += medal_report() @@ -202,7 +202,7 @@ /datum/controller/subsystem/ticker/proc/show_roundend_report(client/C,common_report) var/list/report_parts = list() - + report_parts += personal_report(C) report_parts += common_report @@ -212,7 +212,7 @@ roundend_report.set_content(report_parts.Join()) roundend_report.stylesheets = list() roundend_report.add_stylesheet("roundend",'html/browser/roundend.css') - + roundend_report.open(0) /datum/controller/subsystem/ticker/proc/personal_report(client/C) @@ -311,7 +311,7 @@ all_teams |= A.get_team() all_antagonists += A - for(var/datum/objective_team/T in all_teams) + for(var/datum/team/T in all_teams) result += T.roundend_report() for(var/datum/antagonist/X in all_antagonists) if(X.get_team() == T) @@ -336,7 +336,7 @@ previous_category = A result += A.roundend_report() result += "
    " - + if(all_antagonists.len) var/datum/antagonist/last = all_antagonists[all_antagonists.len] result += last.roundend_report_footer() diff --git a/code/datums/antagonists/abductor.dm b/code/datums/antagonists/abductor.dm index 3b8935d9fa..a98acf054e 100644 --- a/code/datums/antagonists/abductor.dm +++ b/code/datums/antagonists/abductor.dm @@ -2,7 +2,7 @@ name = "Abductor" roundend_category = "abductors" job_rank = ROLE_ABDUCTOR - var/datum/objective_team/abductor_team/team + var/datum/team/abductor_team/team var/sub_role var/outfit var/landmark_type @@ -20,7 +20,7 @@ landmark_type = /obj/effect/landmark/abductor/scientist greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve." -/datum/antagonist/abductor/create_team(datum/objective_team/abductor_team/new_team) +/datum/antagonist/abductor/create_team(datum/team/abductor_team/new_team) if(!new_team) return if(!istype(new_team)) @@ -73,20 +73,20 @@ A.scientist = TRUE -/datum/objective_team/abductor_team - member_name = "abductor" +/datum/team/abductor_team + member_name = "abductor" var/team_number var/list/datum/mind/abductees = list() -/datum/objective_team/abductor_team/is_solo() +/datum/team/abductor_team/is_solo() return FALSE -/datum/objective_team/abductor_team/proc/add_objective(datum/objective/O) +/datum/team/abductor_team/proc/add_objective(datum/objective/O) O.team = src O.update_explanation_text() objectives += O -/datum/objective_team/abductor_team/roundend_report() +/datum/team/abductor_team/roundend_report() var/list/result = list() var/won = TRUE @@ -127,7 +127,7 @@ var/datum/objective/abductee/O = new objtype() objectives += O owner.objectives += objectives - + /datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override) SSticker.mode.update_abductor_icons_added(mob_override ? mob_override.mind : owner) diff --git a/code/datums/antagonists/antag_datum.dm b/code/datums/antagonists/antag_datum.dm index 6b5a573eff..9b5dbb6d75 100644 --- a/code/datums/antagonists/antag_datum.dm +++ b/code/datums/antagonists/antag_datum.dm @@ -49,7 +49,7 @@ GLOBAL_LIST_EMPTY(antagonists) return //Assign default team and creates one for one of a kind team antagonists -/datum/antagonist/proc/create_team(datum/objective_team/team) +/datum/antagonist/proc/create_team(datum/team/team) return //Proc called when the datum is given to a mind. @@ -84,7 +84,7 @@ GLOBAL_LIST_EMPTY(antagonists) LAZYREMOVE(owner.antag_datums, src) if(!silent && owner.current) farewell() - var/datum/objective_team/team = get_team() + var/datum/team/team = get_team() if(team) team.remove_member(owner) qdel(src) @@ -155,6 +155,6 @@ GLOBAL_LIST_EMPTY(antagonists) else already_registered_objectives |= A.objectives objectives = owner.objectives - already_registered_objectives - + //This one is created by admin tools for custom objectives /datum/antagonist/custom \ No newline at end of file diff --git a/code/datums/antagonists/brother.dm b/code/datums/antagonists/brother.dm index dd3bdef9d2..b06c75e4fa 100644 --- a/code/datums/antagonists/brother.dm +++ b/code/datums/antagonists/brother.dm @@ -2,12 +2,12 @@ name = "Brother" job_rank = ROLE_BROTHER var/special_role = "blood brother" - var/datum/objective_team/brother_team/team + var/datum/team/brother_team/team /datum/antagonist/brother/New(datum/mind/new_owner) return ..() -/datum/antagonist/brother/create_team(datum/objective_team/brother_team/new_team) +/datum/antagonist/brother/create_team(datum/team/brother_team/new_team) if(!new_team) return if(!istype(new_team)) @@ -57,15 +57,15 @@ SSticker.mode.update_brother_icons_added(owner) -/datum/objective_team/brother_team +/datum/team/brother_team name = "brotherhood" member_name = "blood brother" var/meeting_area -/datum/objective_team/brother_team/is_solo() +/datum/team/brother_team/is_solo() return FALSE -/datum/objective_team/brother_team/proc/update_name() +/datum/team/brother_team/proc/update_name() var/list/last_names = list() for(var/datum/mind/M in members) var/list/split_name = splittext(M.name," ") @@ -73,7 +73,7 @@ name = last_names.Join(" & ") -/datum/objective_team/brother_team/roundend_report() +/datum/team/brother_team/roundend_report() var/list/parts = list() parts += "The blood brothers of [name] were:" @@ -95,14 +95,14 @@ return "
    [parts.Join("
    ")]
    " -/datum/objective_team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE) +/datum/team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE) O.team = src if(needs_target) O.find_target() O.update_explanation_text() objectives += O -/datum/objective_team/brother_team/proc/forge_brother_objectives() +/datum/team/brother_team/proc/forge_brother_objectives() objectives = list() var/is_hijacker = prob(10) for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker)) @@ -113,7 +113,7 @@ else if(!locate(/datum/objective/escape) in objectives) add_objective(new/datum/objective/escape) -/datum/objective_team/brother_team/proc/forge_single_objective() +/datum/team/brother_team/proc/forge_single_objective() if(prob(50)) if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len)) add_objective(new/datum/objective/destroy, TRUE) diff --git a/code/datums/antagonists/clockcult.dm b/code/datums/antagonists/clockcult.dm index 5f99ccc5dd..48f9b53425 100644 --- a/code/datums/antagonists/clockcult.dm +++ b/code/datums/antagonists/clockcult.dm @@ -4,7 +4,7 @@ roundend_category = "clock cultists" job_rank = ROLE_SERVANT_OF_RATVAR var/datum/action/innate/hierophant/hierophant_network = new() - var/datum/objective_team/clockcult/clock_team + var/datum/team/clockcult/clock_team var/make_team = TRUE //This should be only false for tutorial scarabs /datum/antagonist/clockcult/silent @@ -17,14 +17,14 @@ /datum/antagonist/clockcult/get_team() return clock_team -/datum/antagonist/clockcult/create_team(datum/objective_team/clockcult/new_team) +/datum/antagonist/clockcult/create_team(datum/team/clockcult/new_team) if(!new_team && make_team) //TODO blah blah same as the others, allow multiple for(var/datum/antagonist/clockcult/H in GLOB.antagonists) if(H.clock_team) clock_team = H.clock_team return - clock_team = new /datum/objective_team/clockcult + clock_team = new /datum/team/clockcult return if(make_team && !istype(new_team)) stack_trace("Wrong team type passed to [type] initialization.") @@ -175,7 +175,7 @@ SSticker.mode.servants_of_ratvar -= owner SSticker.mode.update_servant_icons_removed(owner) if(!silent) - owner.current.visible_message("[owner] seems to have remembered their true allegiance!", ignored_mob = owner.current) + owner.current.visible_message("[owner] seems to have remembered their true allegiance!", ignored_mob = owner.current) to_chat(owner, "A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant.") owner.current.log_message("Has renounced the cult of Ratvar!", INDIVIDUAL_ATTACK_LOG) owner.wipe_memory() @@ -185,19 +185,19 @@ . = ..() -/datum/objective_team/clockcult +/datum/team/clockcult name = "Clockcult" var/list/objective var/datum/mind/eminence -/datum/objective_team/clockcult/proc/check_clockwork_victory() +/datum/team/clockcult/proc/check_clockwork_victory() if(GLOB.clockwork_gateway_activated) return TRUE return FALSE -/datum/objective_team/clockcult/roundend_report() +/datum/team/clockcult/roundend_report() var/list/parts = list() - + if(check_clockwork_victory()) parts += "Ratvar's servants defended the Ark until its activation!" else @@ -213,5 +213,5 @@ if(members.len) parts += "Ratvar's servants were:" parts += printplayerlist(members - eminence) - + return "
    [parts.Join("
    ")]
    " \ No newline at end of file diff --git a/code/datums/antagonists/cult.dm b/code/datums/antagonists/cult.dm index bce9123fb3..916123ddff 100644 --- a/code/datums/antagonists/cult.dm +++ b/code/datums/antagonists/cult.dm @@ -9,19 +9,19 @@ var/ignore_implant = FALSE var/give_equipment = FALSE - var/datum/objective_team/cult/cult_team + var/datum/team/cult/cult_team /datum/antagonist/cult/get_team() return cult_team -/datum/antagonist/cult/create_team(datum/objective_team/cult/new_team) +/datum/antagonist/cult/create_team(datum/team/cult/new_team) if(!new_team) //todo remove this and allow admin buttons to create more than one cult for(var/datum/antagonist/cult/H in GLOB.antagonists) if(H.cult_team) cult_team = H.cult_team return - cult_team = new /datum/objective_team/cult + cult_team = new /datum/team/cult cult_team.setup_objectives() return if(!istype(new_team)) @@ -59,7 +59,7 @@ SSticker.mode.cult += owner // Only add after they've been given objectives SSticker.mode.update_cult_icons_added(owner) current.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) - + if(cult_team.blood_target && cult_team.blood_target_image && current.client) current.client.images += cult_team.blood_target_image @@ -183,28 +183,28 @@ current.update_action_buttons_icon() current.remove_status_effect(/datum/status_effect/cult_master) -/datum/objective_team/cult +/datum/team/cult name = "Cult" var/blood_target var/image/blood_target_image var/blood_target_reset_timer - + var/cult_vote_called = FALSE var/cult_mastered = FALSE var/reckoning_complete = FALSE -/datum/objective_team/cult/proc/setup_objectives() +/datum/team/cult/proc/setup_objectives() //SAC OBJECTIVE , todo: move this to objective internals var/list/target_candidates = list() var/datum/objective/sacrifice/sac_objective = new sac_objective.team = src - + for(var/mob/living/carbon/human/player in GLOB.player_list) if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && player.stat != DEAD) target_candidates += player.mind - + if(target_candidates.len == 0) message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") for(var/mob/living/carbon/human/player in GLOB.player_list) @@ -214,7 +214,7 @@ if(LAZYLEN(target_candidates)) sac_objective.target = pick(target_candidates) sac_objective.update_explanation_text() - + var/datum/job/sacjob = SSjob.GetJob(sac_objective.target.assigned_role) var/datum/preferences/sacface = sac_objective.target.current.client.prefs var/icon/reshape = get_flat_human_icon(null, sacjob, sacface) @@ -235,7 +235,7 @@ summon_objective.team = src objectives += summon_objective -/datum/objective/sacrifice +/datum/objective/sacrifice var/sacced = FALSE var/sac_image @@ -268,13 +268,13 @@ /datum/objective/eldergod/check_completion() return summoned || completed -/datum/objective_team/cult/proc/check_cult_victory() +/datum/team/cult/proc/check_cult_victory() for(var/datum/objective/O in objectives) if(!O.check_completion()) return FALSE return TRUE -/datum/objective_team/cult/roundend_report() +/datum/team/cult/roundend_report() var/list/parts = list() if(check_cult_victory()) @@ -291,9 +291,9 @@ else parts += "Objective #[count]: [objective.explanation_text] Fail." count++ - + if(members.len) parts += "The cultists were:" parts += printplayerlist(members) - + return "
    [parts.Join("
    ")]
    " \ No newline at end of file diff --git a/code/datums/antagonists/pirate.dm b/code/datums/antagonists/pirate.dm index e0ce38c1e4..9bf20a4bf5 100644 --- a/code/datums/antagonists/pirate.dm +++ b/code/datums/antagonists/pirate.dm @@ -2,7 +2,7 @@ name = "Space Pirate" job_rank = ROLE_TRAITOR roundend_category = "space pirates" - var/datum/objective_team/pirate/crew + var/datum/team/pirate/crew /datum/antagonist/pirate/greet() to_chat(owner, "You are a Space Pirate!") @@ -12,15 +12,16 @@ /datum/antagonist/pirate/get_team() return crew -/datum/antagonist/pirate/create_team(datum/objective_team/pirate/new_team) +/datum/antagonist/pirate/create_team(datum/team/pirate/new_team) if(!new_team) for(var/datum/antagonist/pirate/P in GLOB.antagonists) if(P.crew) - new_team = P.crew + crew = P.crew + return if(!new_team) - crew = new /datum/objective_team/pirate + crew = new /datum/team/pirate crew.forge_objectives() - return + return if(!istype(new_team)) stack_trace("Wrong team type passed to [type] initialization.") crew = new_team @@ -35,10 +36,10 @@ owner.objectives -= crew.objectives . = ..() -/datum/objective_team/pirate +/datum/team/pirate name = "Pirate crew" -/datum/objective_team/pirate/proc/forge_objectives() +/datum/team/pirate/proc/forge_objectives() var/datum/objective/loot/getbooty = new() getbooty.team = src getbooty.storage_area = locate(/area/shuttle/pirate/vault) in GLOB.sortedAreas @@ -104,13 +105,11 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list( /datum/objective/loot/check_completion() return ..() || get_loot_value() >= target_value - - -/datum/objective_team/pirate/roundend_report() +/datum/team/pirate/roundend_report() var/list/parts = list() parts += "Space Pirates were:" - + var/all_dead = TRUE for(var/datum/mind/M in members) if(considered_alive(M)) @@ -126,5 +125,5 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list( parts += "The pirate crew was successful!" else parts += "The pirate crew has failed." - - return parts.Join("
    ") \ No newline at end of file + + return "
    [parts.Join("
    ")]
    " \ No newline at end of file diff --git a/code/datums/antagonists/revolution.dm b/code/datums/antagonists/revolution.dm index 14c6d1ab0e..3209b9221c 100644 --- a/code/datums/antagonists/revolution.dm +++ b/code/datums/antagonists/revolution.dm @@ -6,7 +6,7 @@ roundend_category = "revolutionaries" // if by some miracle revolutionaries without revolution happen job_rank = ROLE_REV var/hud_type = "rev" - var/datum/objective_team/revolution/rev_team + var/datum/team/revolution/rev_team /datum/antagonist/rev/can_be_owned(datum/mind/new_owner) . = ..() @@ -40,17 +40,17 @@ . = ..() /datum/antagonist/rev/greet() - to_chat(owner, " You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!") + to_chat(owner, "You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!") owner.announce_objectives() -/datum/antagonist/rev/create_team(datum/objective_team/revolution/new_team) +/datum/antagonist/rev/create_team(datum/team/revolution/new_team) if(!new_team) //For now only one revolution at a time for(var/datum/antagonist/rev/head/H in GLOB.antagonists) if(H.rev_team) rev_team = H.rev_team return - rev_team = new /datum/objective_team/revolution + rev_team = new /datum/team/revolution rev_team.update_objectives() rev_team.update_heads() return @@ -78,7 +78,7 @@ old_owner.add_antag_datum(new_revhead,old_team) new_revhead.silent = FALSE to_chat(old_owner, "You have proved your devotion to revolution! You are a head revolutionary now!") - + /datum/antagonist/rev/head name = "Head Revolutionary" @@ -132,14 +132,14 @@ old_owner.add_antag_datum(new_rev,old_team) new_rev.silent = FALSE to_chat(old_owner, "Revolution has been disappointed of your leader traits! You are a regular revolutionary now!") - + /datum/antagonist/rev/farewell() if(ishuman(owner.current)) - owner.current.visible_message("[owner.current] looks like they just remembered their real allegiance!") - to_chat(owner, "You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...") + owner.current.visible_message("[owner.current] looks like they just remembered their real allegiance!", ignored_mob = owner.current) + to_chat(owner, "You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...") else if(issilicon(owner.current)) - owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.") - to_chat(owner, "The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.") + owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.", ignored_mob = owner.current) + to_chat(owner, "The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.") /datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter) log_attack("[owner.current] (Key: [key_name(owner.current)]) has been deconverted from the revolution by [deconverter] (Key: [key_name(deconverter)])!") @@ -164,7 +164,7 @@ if(remove_clumsy && owner.assigned_role == "Clown") to_chat(owner, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") H.dna.remove_mutation(CLOWNMUT) - + if(give_flash) var/obj/item/device/assembly/flash/T = new(H) var/list/slots = list ( @@ -177,17 +177,17 @@ to_chat(H, "The Syndicate were unfortunately unable to get you a flash.") else to_chat(H, "The flash in your [where] will help you to persuade the crew to join your cause.") - + if(give_hud) var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = new(H) S.Insert(H, special = FALSE, drop_if_replaced = FALSE) to_chat(H, "Your eyes have been implanted with a cybernetic security HUD which will help you keep track of who is mindshield-implanted, and therefore unable to be recruited.") -/datum/objective_team/revolution +/datum/team/revolution name = "Revolution" var/max_headrevs = 3 -/datum/objective_team/revolution/proc/update_objectives(initial = FALSE) +/datum/team/revolution/proc/update_objectives(initial = FALSE) var/untracked_heads = SSjob.get_all_heads() for(var/datum/objective/mutiny/O in objectives) untracked_heads -= O.target @@ -199,16 +199,16 @@ objectives += new_target for(var/datum/mind/M in members) M.objectives |= objectives - + addtimer(CALLBACK(src,.proc/update_objectives),HEAD_UPDATE_PERIOD,TIMER_UNIQUE) -/datum/objective_team/revolution/proc/head_revolutionaries() +/datum/team/revolution/proc/head_revolutionaries() . = list() for(var/datum/mind/M in members) if(M.has_antag_datum(/datum/antagonist/rev/head)) . += M -/datum/objective_team/revolution/proc/update_heads() +/datum/team/revolution/proc/update_heads() if(SSticker.HasRoundStarted()) var/list/datum/mind/head_revolutionaries = head_revolutionaries() var/list/datum/mind/heads = SSjob.get_all_heads() @@ -229,7 +229,7 @@ addtimer(CALLBACK(src,.proc/update_heads),HEAD_UPDATE_PERIOD,TIMER_UNIQUE) -/datum/objective_team/revolution/roundend_report() +/datum/team/revolution/roundend_report() if(!members.len) return diff --git a/code/datums/antagonists/wizard.dm b/code/datums/antagonists/wizard.dm index 7f23215d6c..e856a6642f 100644 --- a/code/datums/antagonists/wizard.dm +++ b/code/datums/antagonists/wizard.dm @@ -11,7 +11,7 @@ var/strip = TRUE //strip before equipping var/allow_rename = TRUE var/hud_version = "wizard" - var/datum/objective_team/wizard/wiz_team //Only created if wizard summons apprentices + var/datum/team/wizard/wiz_team //Only created if wizard summons apprentices var/move_to_lair = TRUE var/outfit_type = /datum/outfit/wizard var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */ @@ -33,7 +33,7 @@ /datum/antagonist/wizard/proc/unregister() SSticker.mode.wizards -= src -/datum/antagonist/wizard/create_team(datum/objective_team/wizard/new_team) +/datum/antagonist/wizard/create_team(datum/team/wizard/new_team) if(!new_team) return if(!istype(new_team)) @@ -43,7 +43,7 @@ /datum/antagonist/wizard/get_team() return wiz_team -/datum/objective_team/wizard +/datum/team/wizard name = "wizard team" var/datum/antagonist/wizard/master_wizard @@ -307,18 +307,18 @@ parts += "The wizard was successful!" else parts += "The wizard has failed!" - + if(owner.spell_list.len>0) parts += "[owner.name] used the following spells: " var/list/spell_names = list() for(var/obj/effect/proc_holder/spell/S in owner.spell_list) spell_names += S.name parts += spell_names.Join(", ") - + return parts.Join("
    ") //Wizard with apprentices report -/datum/objective_team/wizard/roundend_report() +/datum/team/wizard/roundend_report() var/list/parts = list() parts += "Wizards/witches of [master_wizard.owner.name] team were:" @@ -326,5 +326,5 @@ parts += " " parts += "[master_wizard.owner.name] apprentices were:" parts += printplayerlist(members - master_wizard.owner) - + return "
    [parts.Join("
    ")]
    " \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index dbbb30e231..231ce66f28 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -149,7 +149,7 @@ return LAZYADD(antag_datums, A) A.create_team(team) - var/datum/objective_team/antag_team = A.get_team() + var/datum/team/antag_team = A.get_team() if(antag_team) antag_team.add_member(src) A.on_gain() @@ -206,7 +206,7 @@ var/datum/antagonist/nukeop/nuke = has_antag_datum(/datum/antagonist/nukeop,TRUE) if(nuke) remove_antag_datum(nuke.type) -special_role = null + special_role = null /datum/mind/proc/remove_wizard() remove_antag_datum(/datum/antagonist/wizard) @@ -333,7 +333,7 @@ special_role = null N.send_to_spawnpoint = FALSE N.nukeop_outfit = null add_antag_datum(N,converter.nuke_team) - + enslaved_to = creator @@ -775,13 +775,13 @@ special_role = null objective = locate(href_list["obj_edit"]) if (!objective) return - + for(var/datum/antagonist/A in antag_datums) if(objective in A.objectives) target_antag = A objective_pos = A.objectives.Find(objective) break - + if(!target_antag) //Shouldn't happen stack_trace("objective without antagonist found") objective_pos = objectives.Find(objective) @@ -943,7 +943,7 @@ special_role = null var/datum/objective/objective = locate(href_list["obj_delete"]) if(!istype(objective)) return - + for(var/datum/antagonist/A in antag_datums) if(objective in A.objectives) A.objectives -= objective diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index e413f0ebaf..d8ba1f5fa1 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -73,7 +73,7 @@ C.prefs.copy_to(M) M.key = C.key var/datum/mind/app_mind = M.mind - + var/datum/antagonist/wizard/apprentice/app = new(app_mind) app.master = user app.school = kind @@ -165,7 +165,7 @@ var/datum/antagonist/nukeop/creator_op = user.has_antag_datum(/datum/antagonist/nukeop,TRUE) if(!creator_op) return - + switch(borg_to_spawn) if("Medical") R = new /mob/living/silicon/robot/modules/syndicate/medical(T) @@ -187,7 +187,7 @@ R.real_name = R.name R.key = C.key - + var/datum/antagonist/nukeop/new_borg = new(R.mind) new_borg.send_to_spawnpoint = FALSE R.mind.add_antag_datum(new_borg,creator_op.nuke_team) diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index 978f871ba2..609f5bb6ab 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -1,6 +1,6 @@ /datum/game_mode var/list/datum/mind/brothers = list() - var/list/datum/objective_team/brother_team/brother_teams = list() + var/list/datum/team/brother_team/brother_teams = list() /datum/game_mode/traitor/bros name = "traitor+brothers" @@ -13,7 +13,7 @@ Blood Brothers: Accomplish your objectives.\n\ Crew: Do not let the traitors or brothers succeed!" - var/list/datum/objective_team/brother_team/pre_brother_teams = list() + var/list/datum/team/brother_team/pre_brother_teams = list() var/const/team_amount = 2 //hard limit on brother teams if scaling is turned off var/const/min_team_size = 2 traitors_required = FALSE //Only teams are possible @@ -36,7 +36,7 @@ for(var/j = 1 to num_teams) if(possible_brothers.len < min_team_size || antag_candidates.len <= required_enemies) break - var/datum/objective_team/brother_team/team = new + var/datum/team/brother_team/team = new var/team_size = prob(10) ? min(3, possible_brothers.len) : 2 for(var/k = 1 to team_size) var/datum/mind/bro = pick(possible_brothers) @@ -49,7 +49,7 @@ return ..() /datum/game_mode/traitor/bros/post_setup() - for(var/datum/objective_team/brother_team/team in pre_brother_teams) + for(var/datum/team/brother_team/team in pre_brother_teams) team.meeting_area = pick(meeting_areas) meeting_areas -= team.meeting_area team.forge_brother_objectives() diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 778cf41022..e4f75ea563 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -112,8 +112,8 @@ Credit where due: var/servants_to_serve = list() var/roundstart_player_count var/ark_time //In minutes, how long the Ark waits before activation; this is equal to 30 + (number of players / 5) (max 40 mins.) - - var/datum/objective_team/clockcult/main_clockcult + + var/datum/team/clockcult/main_clockcult /datum/game_mode/clockwork_cult/pre_setup() if(CONFIG_GET(flag/protect_roles_from_antagonist)) @@ -189,10 +189,9 @@ Credit where due: return FALSE /datum/game_mode/clockwork_cult/check_finished() - var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar - if(G && !GLOB.ratvar_awakens) // Doesn't end until the Ark is destroyed or completed + if(GLOB.ark_of_the_clockwork_justiciar && !GLOB.ratvar_awakens) // Doesn't end until the Ark is destroyed or completed return FALSE - . = ..() + return ..() /datum/game_mode/clockwork_cult/proc/check_clockwork_victory() return main_clockcult.check_clockwork_victory() diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 67e2225772..697a5c8eba 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -6,13 +6,13 @@ /proc/iscultist(mob/living/M) return istype(M) && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_CULT) -/datum/objective_team/cult/proc/is_sacrifice_target(datum/mind/mind) +/datum/team/cult/proc/is_sacrifice_target(datum/mind/mind) for(var/datum/objective/sacrifice/sac_objective in objectives) if(mind == sac_objective.target) return TRUE return FALSE - -/proc/is_convertable_to_cult(mob/living/M,datum/objective_team/cult/specific_cult) + +/proc/is_convertable_to_cult(mob/living/M,datum/team/cult/specific_cult) if(!istype(M)) return FALSE if(M.mind) @@ -54,7 +54,7 @@ var/list/cultists_to_cult = list() //the cultists we'll convert - var/datum/objective_team/cult/main_cult + var/datum/team/cult/main_cult /datum/game_mode/cult/pre_setup() @@ -96,7 +96,7 @@ var/datum/antagonist/cult/new_cultist = new(cult_mind) new_cultist.give_equipment = equip - + if(cult_mind.add_antag_datum(new_cultist)) if(stun) cult_mind.current.Unconscious(100) diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm index 2938f5abf4..b809f2419c 100644 --- a/code/game/gamemodes/cult/cult_comms.dm +++ b/code/game/gamemodes/cult/cult_comms.dm @@ -30,7 +30,7 @@ user.whisper("O bidai nabora se[pick("'","`")]sma!", language = /datum/language/common) user.whisper(html_decode(message)) var/title = "Acolyte" - var/span = "cultitalic" + var/span = "cult italic" if(user.mind && user.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER)) span = "cultlarge" if(ishuman(user)) @@ -97,7 +97,7 @@ var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) pollCultists(owner,C.cult_team) -/proc/pollCultists(var/mob/living/Nominee,datum/objective_team/cult/team) //Cult Master Poll +/proc/pollCultists(var/mob/living/Nominee,datum/team/cult/team) //Cult Master Poll if(world.time < CULT_POLL_WAIT) to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [DisplayTimeText(CULT_POLL_WAIT-world.time)].") return @@ -276,7 +276,7 @@ return FALSE var/datum/antagonist/cult/C = caller.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - + if(target in view(7, get_turf(ranged_ability_user))) C.cult_team.blood_target = target var/area/A = get_area(target) @@ -297,7 +297,7 @@ return TRUE return FALSE -/proc/reset_blood_target(datum/objective_team/cult/team) +/proc/reset_blood_target(datum/team/cult/team) for(var/datum/mind/B in team.members) if(B.current && B.current.stat != DEAD && B.current.client) if(team.blood_target) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index fc6a36376b..ff85499029 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -407,8 +407,8 @@ structure_check() searches for nearby cultist structures required for the invoca var/datum/antagonist/cult/C = first_invoker.mind.has_antag_datum(/datum/antagonist/cult,TRUE) if(!C) return - - + + var/big_sac = FALSE if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3) for(var/M in invokers) @@ -510,10 +510,10 @@ structure_check() searches for nearby cultist structures required for the invoca message_admins("[key_name_admin(user)] erased a Narsie rune with a null rod") ..() -//Rite of Resurrection: Requires a dead or inactive cultist. When reviving the dead, you can only perform one revival for every sacrifice your cult has carried out. +//Rite of Resurrection: Requires the corpse of a cultist and that there have been less revives than the number of people GLOB.sacrificed /obj/effect/rune/raise_dead - cultist_name = "Revive Cultist" - cultist_desc = "requires a dead, mindless, or inactive cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be given a new life." + cultist_name = "Resurrect Cultist" + cultist_desc = "requires the corpse of a cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be revived." invocation = "Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!" //Depends on the name of the user - see below icon_state = "1" color = RUNE_COLOR_MEDIUMRED @@ -534,11 +534,16 @@ structure_check() searches for nearby cultist structures required for the invoca return rune_in_use = TRUE for(var/mob/living/M in T.contents) - if(iscultist(M) && (M.stat == DEAD || !M.client || M.client.is_afk())) + if(iscultist(M) && M.stat == DEAD) potential_revive_mobs |= M if(!potential_revive_mobs.len) to_chat(user, "There are no dead cultists on the rune!") - log_game("Raise Dead rune failed - no cultists to revive") + log_game("Raise Dead rune failed - no corpses to revive") + fail_invoke() + rune_in_use = FALSE + return + if(LAZYLEN(GLOB.sacrificed) <= revives_used) + to_chat(user, "You have sacrificed too few people to revive a cultist!") fail_invoke() rune_in_use = FALSE return @@ -554,25 +559,9 @@ structure_check() searches for nearby cultist structures required for the invoca else invocation = initial(invocation) ..() - if(mob_to_revive.stat == DEAD) - if(LAZYLEN(GLOB.sacrificed) <= revives_used) - to_chat(user, "Your cult must carry out another sacrifice before it can revive a cultist!") - fail_invoke() - rune_in_use = FALSE - return - revives_used++ - mob_to_revive.revive(1, 1) //This does remove disabilities and such, but the rune might actually see some use because of it! - mob_to_revive.grab_ghost() - else if(!mob_to_revive.client || mob_to_revive.client.is_afk()) - set waitfor = FALSE - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [mob_to_revive.name], an inactive blood cultist?", "[name]", null, "Blood Cultist", 50, mob_to_revive) - var/mob/dead/observer/theghost = null - if(candidates.len) - theghost = pick(candidates) - to_chat(mob_to_revive.mind, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form.") - message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.") - mob_to_revive.ghostize(0) - mob_to_revive.key = theghost.key + revives_used++ + mob_to_revive.revive(1, 1) //This does remove disabilities and such, but the rune might actually see some use because of it! + mob_to_revive.grab_ghost() to_chat(mob_to_revive, "\"PASNAR SAVRAE YAM'TOTH. Arise.\"") mob_to_revive.visible_message("[mob_to_revive] draws in a huge breath, red light shining from [mob_to_revive.p_their()] eyes.", \ "You awaken suddenly from the void. You're alive!") diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 344eb53507..a0e5a9f147 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -465,4 +465,4 @@ if(EMERGENCY_ESCAPED_OR_ENDGAMED) SSticker.news_report = STATION_EVACUATED if(SSshuttle.emergency.is_hijacked()) - SSticker.news_report = SHUTTLE_HIJACK + SSticker.news_report = SHUTTLE_HIJACK \ No newline at end of file diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm index 050cac443d..f9e8f8d752 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction.dm @@ -10,7 +10,7 @@ required_players = 15 maximum_players = 50 var/max_teams = 4 - var/list/datum/objective_team/abductor_team/abductor_teams = list() + var/list/datum/team/abductor_team/abductor_teams = list() var/finished = FALSE var/static/team_count = 0 @@ -37,7 +37,7 @@ if(team_number > max_teams) return //or should it try to stuff them in anway ? - var/datum/objective_team/abductor_team/team = new + var/datum/team/abductor_team/team = new team.team_number = team_number team.name = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names team.add_objective(new/datum/objective/experiment) @@ -50,6 +50,7 @@ antag_candidates -= scientist team.members |= scientist scientist.assigned_role = "Abductor Scientist" + scientist.special_role = "Abductor Scientist" log_game("[scientist.key] (ckey) has been selected as [team.name] abductor scientist.") if(!agent) @@ -57,18 +58,19 @@ antag_candidates -= agent team.members |= agent agent.assigned_role = "Abductor Agent" + agent.special_role = "Abductor Agent" log_game("[agent.key] (ckey) has been selected as [team.name] abductor agent.") abductor_teams += team return team /datum/game_mode/abduction/post_setup() - for(var/datum/objective_team/abductor_team/team in abductor_teams) + for(var/datum/team/abductor_team/team in abductor_teams) post_setup_team(team) return ..() //Used for create antag buttons -/datum/game_mode/abduction/proc/post_setup_team(datum/objective_team/abductor_team/team) +/datum/game_mode/abduction/proc/post_setup_team(datum/team/abductor_team/team) for(var/datum/mind/M in team.members) if(M.assigned_role == "Abductor Scientist") M.add_antag_datum(ANTAG_DATUM_ABDUCTOR_SCIENTIST, team) @@ -77,7 +79,7 @@ /datum/game_mode/abduction/check_finished() if(!finished) - for(var/datum/objective_team/abductor_team/team in abductor_teams) + for(var/datum/team/abductor_team/team in abductor_teams) for(var/datum/objective/O in team.objectives) if(O.check_completion()) SSshuttle.emergency.request(null, set_coefficient = 0.5) @@ -101,9 +103,9 @@ /datum/objective/experiment/check_completion() for(var/obj/machinery/abductor/experiment/E in GLOB.machines) - if(!istype(team, /datum/objective_team/abductor_team)) + if(!istype(team, /datum/team/abductor_team)) return FALSE - var/datum/objective_team/abductor_team/T = team + var/datum/team/abductor_team/T = team if(E.team_number == T.team_number) return E.points >= target_amount return FALSE diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 4fcde56a72..890a3bb456 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -17,7 +17,7 @@ var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! var/list/pre_nukeops = list() - var/datum/objective_team/nuclear/nuke_team + var/datum/team/nuclear/nuke_team /datum/game_mode/nuclear/pre_setup() var/n_agents = min(round(num_players() / 10), antag_candidates.len, agents_possible) @@ -69,7 +69,8 @@ return FALSE //its a static var btw ..() -/datum/game_mode/nuclear/declare_completion() +/datum/game_mode/nuclear/set_round_result() + ..() var result = nuke_team.get_result() switch(result) if(NUKE_RESULT_FLUKE) @@ -102,22 +103,12 @@ else SSticker.mode_result = "halfwin - interrupted" SSticker.news_report = OPERATIVE_SKIRMISH - return ..() /datum/game_mode/nuclear/generate_report() return "One of Central Command's trading routes was recently disrupted by a raid carried out by the Gorlex Marauders. They seemed to only be after one ship - a highly-sensitive \ transport containing a nuclear fission explosive, although it is useless without the proper code and authorization disk. While the code was likely found in minutes, the only disk that \ can activate this explosive is on your station. Ensure that it is protected at all times, and remain alert for possible intruders." -/datum/game_mode/proc/auto_declare_completion_nuclear() - var/list/nuke_teams = list() - for(var/datum/antagonist/nukeop/N in GLOB.antagonists) //collect all nuke teams - nuke_teams |= N.nuke_team - for(var/datum/objective_team/nuclear/nuke_team in nuke_teams) - nuke_team.roundend_display() - return TRUE - - /proc/is_nuclear_operative(mob/M) return M && istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/nukeop) @@ -132,7 +123,8 @@ l_pocket = /obj/item/pinpointer/nuke/syndicate id = /obj/item/card/id/syndicate belt = /obj/item/gun/ballistic/automatic/pistol - backpack_contents = list(/obj/item/storage/box/syndie=1) + backpack_contents = list(/obj/item/storage/box/syndie=1,\ + /obj/item/kitchen/knife/combat/survival) var/tc = 25 var/command_radio = FALSE @@ -177,4 +169,5 @@ r_hand = /obj/item/gun/ballistic/automatic/shotgun/bulldog backpack_contents = list(/obj/item/storage/box/syndie=1,\ /obj/item/tank/jetpack/oxygen/harness=1,\ - /obj/item/gun/ballistic/automatic/pistol=1) + /obj/item/gun/ballistic/automatic/pistol=1,\ + /obj/item/kitchen/knife/combat/survival) diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index cbfdb98c69..f20e16b36b 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -26,7 +26,7 @@ var/finished = 0 var/check_counter = 0 var/max_headrevs = 3 - var/datum/objective_team/revolution/revolution + var/datum/team/revolution/revolution var/list/datum/mind/headrev_candidates = list() /////////////////////////// diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 92c01bc241..8b80b9ab69 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -64,7 +64,6 @@ to_chat(user, "\"Come now, do not capture your bretheren's soul.\"") return add_logs(user, M, "captured [M.name]'s soul", src) - transfer_soul("VICTIM", M, user) ///////////////////Options for using captured souls/////////////////////////////////////// diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index b5d908d669..2a3812be3b 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -524,7 +524,7 @@ if(SSticker.mode.brother_teams.len > 0) dat += "
    " - for(var/datum/objective_team/brother_team/team in SSticker.mode.brother_teams) + for(var/datum/team/brother_team/team in SSticker.mode.brother_teams) for(var/datum/mind/brother in team.members) var/mob/M = brother.current if(M) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 1d60f4f28d..ece3775872 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -240,14 +240,13 @@ //Let's find the spawn locations var/leader_chosen = FALSE - - var/datum/objective_team/nuclear/nuke_team + var/datum/team/nuclear/nuke_team for(var/mob/c in chosen) var/mob/living/carbon/human/new_character=makeBody(c) if(!leader_chosen) leader_chosen = TRUE var/datum/antagonist/nukeop/N = new_character.mind.add_antag_datum(/datum/antagonist/nukeop/leader) - nuke_team = N.nuke_team + nuke_team = N.nuke_team else new_character.mind.add_antag_datum(/datum/antagonist/nukeop,nuke_team) return 1 @@ -309,13 +308,13 @@ //Assign antag status and the mission SSticker.mode.traitors += Commando.mind Commando.mind.special_role = "deathsquad" - + var/datum/objective/missionobj = new missionobj.owner = Commando.mind missionobj.explanation_text = mission missionobj.completed = 1 Commando.mind.objectives += missionobj - + Commando.mind.add_antag_datum(/datum/antagonist/auto_custom) //Greet the commando @@ -364,13 +363,13 @@ //Assign antag status and the mission SSticker.mode.traitors += newmob.mind newmob.mind.special_role = "official" - + var/datum/objective/missionobj = new missionobj.owner = newmob.mind missionobj.explanation_text = mission missionobj.completed = 1 newmob.mind.objectives += missionobj - + newmob.mind.add_antag_datum(/datum/antagonist/auto_custom) if(CONFIG_GET(flag/enforce_human_authority)) @@ -472,7 +471,7 @@ //Assign antag status and the mission SSticker.mode.traitors += ERTOperative.mind ERTOperative.mind.special_role = "ERT" - + var/datum/objective/missionobj = new missionobj.owner = ERTOperative.mind missionobj.explanation_text = mission diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 9801e98614..15b76d2641 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -50,7 +50,7 @@ var/list/all_cults = list() for(var/datum/antagonist/cult/C in GLOB.antagonists) all_cults |= C.cult_team - for(var/datum/objective_team/cult/T in all_cults) + for(var/datum/team/cult/T in all_cults) deltimer(T.blood_target_reset_timer) T.blood_target = src var/datum/objective/eldergod/summon_objective = locate() in T.objectives diff --git a/tgstation.dme b/tgstation.dme index 98b6a4dcab..64e5b2c686 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -490,6 +490,7 @@ #include "code\game\gamemodes\antag_hud.dm" #include "code\game\gamemodes\antag_spawner.dm" #include "code\game\gamemodes\antag_spawner_cit.dm" +#include "code\game\gamemodes\antag_team.dm" #include "code\game\gamemodes\cit_objectives.dm" #include "code\game\gamemodes\events.dm" #include "code\game\gamemodes\game_mode.dm" @@ -1305,8 +1306,8 @@ #include "code\modules\client\client_colour.dm" #include "code\modules\client\client_defines.dm" #include "code\modules\client\client_procs.dm" -#include "code\modules\client\player_details.dm" #include "code\modules\client\message.dm" +#include "code\modules\client\player_details.dm" #include "code\modules\client\preferences.dm" #include "code\modules\client\preferences_savefile.dm" #include "code\modules\client\preferences_toggles.dm" From 2be1b5eb2948692eb1060e2a6931a346a0f88394 Mon Sep 17 00:00:00 2001 From: Michiyamenotehifunana <31995558+Michiyamenotehifunana@users.noreply.github.com> Date: Wed, 20 Dec 2017 23:05:05 +0800 Subject: [PATCH 44/96] Removes pierce immunity from roundstart xenos --- .../mob/living/carbon/human/species_types/furrypeople.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm index 79bbee9db1..fe41c074c0 100644 --- a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm @@ -90,10 +90,9 @@ id = "xeno" say_mod = "hisses" default_color = "00FF00" - species_traits = list(MUTCOLORS,LIPS,DIGITIGRADE,PIERCEIMMUNE,SPECIES_ORGANIC) + species_traits = list(MUTCOLORS,LIPS,DIGITIGRADE,SPECIES_ORGANIC) mutant_bodyparts = list("xenotail", "xenohead", "xenodorsal", "taur","mam_body_markings") default_features = list("xenotail"="xeno","xenohead"="standard","xenodorsal"="standard","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None","mam_body_markings" = "xeno") - heatmod = 1.3 attack_verb = "slash" attack_sound = 'sound/weapons/slash.ogg' miss_sound = 'sound/weapons/slashmiss.ogg' From 84f51a8cbbd6aad92d06010b4cbead01d8006c06 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 20 Dec 2017 13:24:06 -0600 Subject: [PATCH 45/96] antag team --- code/game/gamemodes/antag_team.dm | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 code/game/gamemodes/antag_team.dm diff --git a/code/game/gamemodes/antag_team.dm b/code/game/gamemodes/antag_team.dm new file mode 100644 index 0000000000..372ee26dfa --- /dev/null +++ b/code/game/gamemodes/antag_team.dm @@ -0,0 +1,34 @@ +//A barebones antagonist team. +/datum/team + var/list/datum/mind/members = list() + var/name = "team" + var/member_name = "member" + var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes. + +/datum/team/New(starting_members) + . = ..() + if(starting_members) + if(islist(starting_members)) + for(var/datum/mind/M in starting_members) + add_member(M) + else + add_member(starting_members) + +/datum/team/proc/is_solo() + return members.len == 1 + +/datum/team/proc/add_member(datum/mind/new_member) + members |= new_member + +/datum/team/proc/remove_member(datum/mind/member) + members -= member + +//Display members/victory/failure/objectives for the team +/datum/team/proc/roundend_report() + var/list/report = list() + + report += "[name]:" + report += "The [member_name]s were:" + report += printplayerlist(members) + + return report.Join("
    ") \ No newline at end of file From 5869eae8e9ce04c767f9ae0599e79a4f2f012b58 Mon Sep 17 00:00:00 2001 From: QualityVan Date: Tue, 19 Dec 2017 21:56:45 -0500 Subject: [PATCH 46/96] Fixes some syndicate duffelbags missing inhands --- code/game/objects/items/storage/backpack.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 14529b4078..533858b748 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -419,7 +419,7 @@ name = "suspicious looking duffel bag" desc = "A large duffel bag for holding extra tactical supplies." icon_state = "duffel-syndie" - item_state = "duffel-syndie" + item_state = "duffel-syndieammo" silent = 1 slowdown = 0 From 1c736a02da22708b9d665d6924ffc12042e1a46f Mon Sep 17 00:00:00 2001 From: deathride58 Date: Wed, 20 Dec 2017 22:29:52 -0500 Subject: [PATCH 48/96] Update changelog.css --- html/changelog.css | 44 -------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/html/changelog.css b/html/changelog.css index ab993f8364..2bfa3fa495 100644 --- a/html/changelog.css +++ b/html/changelog.css @@ -1,46 +1,3 @@ -<<<<<<< HEAD -.top{font-family:Tahoma,sans-serif;font-size:12px;} -h2{font-family:Tahoma,sans-serif;} -a img {border:none;} -.bgimages16 li { - padding:2px 10px 2px 30px; - background-position:6px center; - background-repeat:no-repeat; - border:1px solid #ddd; - border-left:4px solid #999; - margin-bottom:2px; -} -.bugfix {background-image:url(bug-minus.png)} -.wip {background-image:url(hard-hat-exclamation.png)} -.tweak {background-image:url(wrench-screwdriver.png)} -.soundadd {background-image:url(music-plus.png)} -.sounddel {background-image:url(music-minus.png)} -.rscdel {background-image:url(cross-circle.png)} -.rscadd {background-image:url(tick-circle.png)} -.imageadd {background-image:url(image-plus.png)} -.imagedel {background-image:url(image-minus.png)} -.spellcheck {background-image:url(spell-check.png)} -.experiment {background-image:url(burn-exclamation.png)} -.refactor {background-image:url(burn-exclamation.png)} -.code_imp {background-image:url(coding.png)} -.config {background-image:url(chrome_wrench.png)} -.admin {background-image:url(ban.png)} -.server {background-image:url(hard-hat-exclamation.png)} -.balance {background-image:url(scales.png)} -.sansserif {font-family:Tahoma,sans-serif;font-size:12px;} -.commit {margin-bottom:20px;font-size:100%;font-weight:normal;} -.changes {list-style:none;margin:5px 0;padding:0 0 0 25px;font-size:0.8em;} -.date {margin:10px 0;color:blue;border-bottom:2px solid #00f;width:60%;padding:2px 0;font-size:1em;font-weight:bold;} -.author {padding-left:10px;margin:0;font-weight:bold;font-size:0.9em;} -.drop {cursor:pointer;border:1px solid #999;display:inline;font-size:0.9em;padding:1px 20px 1px 5px;line-height:16px;} -.hidden {display:none;} -.indrop {margin:2px 0 0 0;clear:both;background:#fff;border:1px solid #ddd;padding:5px 10px;} -.indrop p {margin:0;font-size:0.8em;line-height:16px;margin:1px 0;} -.indrop img {margin-right:5px;vertical-align:middle;} -.closed {background:url(chevron-expand.png) right center no-repeat;} -.open {background:url(chevron.png) right center no-repeat;} -.lic {font-size:9px;} -======= .top{font-family:Tahoma,sans-serif;font-size:12px;} h2{font-family:Tahoma,sans-serif;} a img {border:none;} @@ -82,4 +39,3 @@ a img {border:none;} .closed {background:url(chevron-expand.png) right center no-repeat;} .open {background:url(chevron.png) right center no-repeat;} .lic {font-size:9px;} ->>>>>>> 2c96cc9... Fixes config entries in the changelog having no icon (#33625) From 680e44fb6479be287762e0ce11421411f309cc09 Mon Sep 17 00:00:00 2001 From: deathride58 Date: Wed, 20 Dec 2017 22:56:46 -0500 Subject: [PATCH 49/96] Update observer.dm --- code/modules/mob/dead/observer/observer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 4ecae3730d..4481de1e36 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -471,7 +471,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set hidden = TRUE var/max_view = client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT if(input) - client.change_view(CLAMP(client.view + input, 7, max_view)) + client.rescale_view(input, 7, max_view) /mob/dead/observer/verb/boo() set category = "Ghost" From 92b018bed7e9c59336464352357e474574323c55 Mon Sep 17 00:00:00 2001 From: ShizCalev Date: Thu, 21 Dec 2017 01:08:39 -0500 Subject: [PATCH 50/96] Fixes bullets making sounds in space and water (#33672) * Bullet sounds * explicit lists --- code/modules/projectiles/ammunition.dm | 45 +++++++++++++++++++ .../projectiles/ammunition/caseless.dm | 1 + code/modules/projectiles/ammunition/energy.dm | 1 + .../modules/projectiles/ammunition/special.dm | 1 + code/modules/projectiles/box_magazine.dm | 5 ++- code/modules/projectiles/guns/ballistic.dm | 6 +-- .../projectiles/guns/ballistic/revolver.dm | 4 +- .../projectiles/guns/ballistic/shotgun.dm | 3 +- 8 files changed, 55 insertions(+), 11 deletions(-) diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index 71befb50f1..4e341fa2a4 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -17,6 +17,7 @@ var/delay = 0 //Delay for energy weapons var/click_cooldown_override = 0 //Override this to make your gun have a faster fire rate, in tenths of a second. 4 is the default gun cooldown. var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the ammo is fired. + var/heavy_metal = TRUE /obj/item/ammo_casing/New() @@ -58,3 +59,47 @@ to_chat(user, "You fail to collect anything!") else return ..() + +/obj/item/ammo_casing/throw_impact(atom/A) + if(heavy_metal) + bounce_away(FALSE, NONE) + . = ..() + +/obj/item/ammo_casing/proc/bounce_away(still_warm = FALSE, delay = 3) + SpinAnimation(10, 1) + update_icon() + var/turf/T = get_turf(src) + if(still_warm && T && (is_type_in_typecache(T, GLOB.bullet_bounce_away_sizzle))) + addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, src, 'sound/items/welder.ogg', 20, 1), delay) + else if(T && (!is_type_in_typecache(T, GLOB.bullet_bounce_away_blacklist))) + addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, src, 'sound/weapons/bulletremove.ogg', 60, 1), delay) + +GLOBAL_LIST_INIT(bullet_bounce_away_sizzle, typecacheof(list( + /turf/closed/indestructible/rock/snow, + /turf/closed/wall/ice, + /turf/closed/wall/mineral/snow, + /turf/open/floor/grass/snow, + /turf/open/floor/holofloor/snow, + /turf/open/floor/plating/asteroid/snow, + /turf/open/floor/plating/ice, + /turf/open/water))) + +GLOBAL_LIST_INIT(bullet_bounce_away_blacklist, typecacheof(list( + /turf/closed/indestructible/rock/snow, + /turf/closed/indestructible/splashscreen, + /turf/closed/wall/mineral/snow, + /turf/open/chasm, + /turf/open/floor/carpet, + /turf/open/floor/grass, + /turf/open/floor/holofloor/beach, + /turf/open/floor/holofloor/carpet, + /turf/open/floor/holofloor/grass, + /turf/open/floor/holofloor/hyperspace, + /turf/open/floor/holofloor/snow, + /turf/open/floor/plating/asteroid/snow, + /turf/open/floor/plating/beach, + /turf/open/indestructible/reebe_void, + /turf/open/lava, + /turf/open/space, + /turf/open/water, + /turf/template_noop))) diff --git a/code/modules/projectiles/ammunition/caseless.dm b/code/modules/projectiles/ammunition/caseless.dm index 7432f9f8e7..b3439c86b2 100644 --- a/code/modules/projectiles/ammunition/caseless.dm +++ b/code/modules/projectiles/ammunition/caseless.dm @@ -4,6 +4,7 @@ /obj/item/ammo_casing/caseless desc = "A caseless bullet casing." firing_effect_type = null + heavy_metal = FALSE /obj/item/ammo_casing/caseless/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread) if (..()) //successfully firing diff --git a/code/modules/projectiles/ammunition/energy.dm b/code/modules/projectiles/ammunition/energy.dm index dcd9d356ad..40c198ec4e 100644 --- a/code/modules/projectiles/ammunition/energy.dm +++ b/code/modules/projectiles/ammunition/energy.dm @@ -7,6 +7,7 @@ var/select_name = "energy" fire_sound = 'sound/weapons/laser.ogg' firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect/energy + heavy_metal = FALSE /obj/item/ammo_casing/energy/chameleon projectile_type = /obj/item/projectile/energy/chameleon diff --git a/code/modules/projectiles/ammunition/special.dm b/code/modules/projectiles/ammunition/special.dm index 11fd12da70..de103b399e 100644 --- a/code/modules/projectiles/ammunition/special.dm +++ b/code/modules/projectiles/ammunition/special.dm @@ -3,6 +3,7 @@ desc = "I didn't even know magic needed ammo..." projectile_type = /obj/item/projectile/magic firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect/magic + heavy_metal = FALSE /obj/item/ammo_casing/magic/change projectile_type = /obj/item/projectile/magic/change diff --git a/code/modules/projectiles/box_magazine.dm b/code/modules/projectiles/box_magazine.dm index 0e6ab6c23f..bf941108ff 100644 --- a/code/modules/projectiles/box_magazine.dm +++ b/code/modules/projectiles/box_magazine.dm @@ -96,9 +96,10 @@ /obj/item/ammo_box/attack_self(mob/user) var/obj/item/ammo_casing/A = get_round() if(A) - user.put_in_hands(A) + if(!user.put_in_hands(A)) + A.bounce_away(FALSE, NONE) + playsound(src, 'sound/weapons/bulletinsert.ogg', 60, 1) to_chat(user, "You remove a round from \the [src]!") - playsound(A, 'sound/weapons/bulletremove.ogg', 60, 1) update_icon() /obj/item/ammo_box/update_icon() diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index c4ba7a33b7..680c86ff5c 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -31,8 +31,7 @@ if(istype(AC)) //there's a chambered round if(casing_ejector) AC.forceMove(drop_location()) //Eject casing onto ground. - AC.SpinAnimation(10, 1) //next gen special effects - addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, AC, 'sound/weapons/bulletremove.ogg', 60, 1), 3) + AC.bounce_away(TRUE) chambered = null else if(empty_chamber) chambered = null @@ -125,8 +124,7 @@ to_chat(user, "You pull the magazine out of \the [src].") else if(chambered) AC.forceMove(drop_location()) - AC.SpinAnimation(10, 1) - addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, AC, 'sound/weapons/bulletremove.ogg', 60, 1), 3) + AC.bounce_away() chambered = null to_chat(user, "You unload the round from \the [src]'s chamber.") playsound(src, "gun_slide_lock", 70, 1) diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index f642a94284..563b3d9ad5 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -40,9 +40,7 @@ CB = magazine.get_round(0) if(CB) CB.forceMove(drop_location()) - CB.SpinAnimation(10, 1) - CB.update_icon() - addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, CB, 'sound/weapons/bulletremove.ogg', 60, 1), 3) + CB.bounce_away(FALSE, NONE) num_unloaded++ if (num_unloaded) to_chat(user, "You unload [num_unloaded] shell\s from [src].") diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index d3b1815d0b..e702013233 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -57,8 +57,7 @@ /obj/item/gun/ballistic/shotgun/proc/pump_unload(mob/M) if(chambered)//We have a shell in the chamber chambered.forceMove(drop_location())//Eject casing - chambered.SpinAnimation(10, 1) - addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, chambered, 'sound/weapons/bulletremove.ogg', 60, 1), 3) + chambered.bounce_away() chambered = null /obj/item/gun/ballistic/shotgun/proc/pump_reload(mob/M) From 6c4d687db6c0ccca8a13275d59245b8313ed67e0 Mon Sep 17 00:00:00 2001 From: AnturK Date: Thu, 21 Dec 2017 07:11:32 +0100 Subject: [PATCH 52/96] Immovable rod abuse, smite and event trigger. (#33681) --- code/__DEFINES/admin.dm | 1 + code/modules/admin/verbs/randomverbs.dm | 8 ++++- code/modules/events/immovable_rod.dm | 41 ++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 65d028ea34..7622fc0ea7 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -145,6 +145,7 @@ #define ADMIN_PUNISHMENT_GIB "Gib" #define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device" #define ADMIN_PUNISHMENT_FIREBALL "Fireball" +#define ADMIN_PUNISHMENT_ROD "Immovable Rod" #define AHELP_ACTIVE 1 #define AHELP_CLOSED 2 diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index eed265598e..8f13d887aa 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1207,7 +1207,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits if(!holder) return - var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL) + var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_ROD) var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list @@ -1229,6 +1229,12 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits bluespace_artillery(target) if(ADMIN_PUNISHMENT_FIREBALL) new /obj/effect/temp_visual/target(get_turf(target)) + if(ADMIN_PUNISHMENT_ROD) + var/turf/T = get_turf(target) + var/startside = pick(GLOB.cardinals) + var/turf/startT = spaceDebrisStartLoc(startside, T.z) + var/turf/endT = spaceDebrisFinishLoc(startside, T.z) + new /obj/effect/immovablerod(startT, endT,target) var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]." message_admins(msg) diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index b933e566be..9612fd8018 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -12,6 +12,16 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 typepath = /datum/round_event/immovable_rod min_players = 15 max_occurrences = 5 + var/atom/special_target + + +/datum/round_event_control/immovable_rod/admin_setup() + if(!check_rights(R_FUN)) + return + + var/aimed = alert("Aimed at current location?","Sniperod", "Yes", "No") + if(aimed == "Yes") + special_target = get_turf(usr) /datum/round_event/immovable_rod announceWhen = 5 @@ -20,10 +30,11 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 priority_announce("What the fuck was that?!", "General Alert") /datum/round_event/immovable_rod/start() + var/datum/round_event_control/immovable_rod/C = control var/startside = pick(GLOB.cardinals) var/turf/startT = spaceDebrisStartLoc(startside, ZLEVEL_STATION_PRIMARY) var/turf/endT = spaceDebrisFinishLoc(startside, ZLEVEL_STATION_PRIMARY) - new /obj/effect/immovablerod(startT, endT) + new /obj/effect/immovablerod(startT, endT, C.special_target) /obj/effect/immovablerod name = "immovable rod" @@ -36,18 +47,28 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 var/z_original = 0 var/destination var/notify = TRUE + var/atom/special_target -/obj/effect/immovablerod/New(atom/start, atom/end) +/obj/effect/immovablerod/New(atom/start, atom/end, aimed_at) ..() SSaugury.register_doom(src, 2000) z_original = z destination = end + special_target = aimed_at if(notify) notify_ghosts("\A [src] is inbound!", enter_link="(Click to orbit)", source=src, action=NOTIFY_ORBIT) GLOB.poi_list += src - if(end && end.z==z_original) + + var/special_target_valid = FALSE + if(special_target) + var/turf/T = get_turf(special_target) + if(T.z == z_original) + special_target_valid = TRUE + if(special_target_valid) + walk_towards(src, special_target, 1) + else if(end && end.z==z_original) walk_towards(src, destination, 1) /obj/effect/immovablerod/Topic(href, href_list) @@ -60,11 +81,20 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 GLOB.poi_list -= src . = ..() -/obj/effect/immovablerod/Move() +/obj/effect/immovablerod/Moved() if((z != z_original) || (loc == destination)) qdel(src) + if(special_target && loc == get_turf(special_target)) + complete_trajectory() return ..() +/obj/effect/immovablerod/proc/complete_trajectory() + //We hit what we wanted to hit, time to go + special_target = null + destination = get_edge_target_turf(src, dir) + walk(src,0) + walk_towards(src, destination, 1) + /obj/effect/immovablerod/ex_act(severity, target) return 0 @@ -83,6 +113,9 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 x = clong.x y = clong.y + if(special_target && clong == special_target) + complete_trajectory() + if(isturf(clong) || isobj(clong)) if(clong.density) clong.ex_act(EXPLODE_HEAVY) From 30fb3f8f5c6e7b770331b09a5035ee1963f51176 Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Wed, 20 Dec 2017 22:33:54 -0800 Subject: [PATCH 54/96] Fix pulling things across space transitions (#33689) --- code/game/turfs/space/space.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index b1e8215592..5399b748e6 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -139,9 +139,11 @@ if(isliving(A)) var/mob/living/L = A - if(L.pulling) + var/atom/movable/AM = L.pulling + if(AM) var/turf/T = get_step(L.loc,turn(A.dir, 180)) - L.pulling.forceMove(T) + AM.forceMove(T) + L.start_pulling(AM) //now we're on the new z_level, proceed the space drifting stoplag()//Let a diagonal move finish, if necessary From 39ecfd64dbdb1db91a375027b302a1ae1073f5d2 Mon Sep 17 00:00:00 2001 From: MoreRobustThanYou Date: Thu, 21 Dec 2017 01:41:01 -0500 Subject: [PATCH 56/96] Fix smoke machine runtime (#33697) * Fix smoke machine runtime * Woops. --- code/modules/reagents/chemistry/machinery/smoke_machine.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/reagents/chemistry/machinery/smoke_machine.dm b/code/modules/reagents/chemistry/machinery/smoke_machine.dm index 86205caba5..7941853a91 100644 --- a/code/modules/reagents/chemistry/machinery/smoke_machine.dm +++ b/code/modules/reagents/chemistry/machinery/smoke_machine.dm @@ -46,6 +46,8 @@ var/new_volume = REAGENTS_BASE_VOLUME for(var/obj/item/stock_parts/matter_bin/B in component_parts) new_volume += REAGENTS_BASE_VOLUME * B.rating + if(!reagents) + create_reagents(new_volume) reagents.maximum_volume = new_volume if(new_volume < reagents.total_volume) reagents.reaction(loc, TOUCH) // if someone manages to downgrade it without deconstructing From 82114e753d102bf6a39a8159924e15d2259ff2cb Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 21 Dec 2017 01:43:43 -0500 Subject: [PATCH 58/96] Merge pull request #33704 from Fox-McCloud/arm-implant-fix Fixes Arm Implant EMP Effect --- code/modules/surgery/organs/augments_arms.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index e23e7ff7d3..a90923e58f 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -61,7 +61,7 @@ /obj/item/organ/cyberimp/arm/emag_act() return 0 -/obj/item/organ/cyberimp/arm/gun/emp_act(severity) +/obj/item/organ/cyberimp/arm/emp_act(severity) if(prob(15/severity) && owner) to_chat(owner, "[src] is hit by EMP!") // give the owner an idea about why his implant is glitching From 636a87ab8f9283817fa0bced4392294f8c4f3cb5 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 21 Dec 2017 01:45:48 -0500 Subject: [PATCH 60/96] The runtime condenser now supports taking input from stdin and outputting on stdout --- tools/Runtime Condenser/Main.cpp | 419 +++++++++++++++++++ tools/Runtime Condenser/RuntimeCondenser.exe | Bin 216064 -> 258048 bytes 2 files changed, 419 insertions(+) diff --git a/tools/Runtime Condenser/Main.cpp b/tools/Runtime Condenser/Main.cpp index 732318269b..3f8678992b 100644 --- a/tools/Runtime Condenser/Main.cpp +++ b/tools/Runtime Condenser/Main.cpp @@ -1,3 +1,4 @@ +<<<<<<< HEAD /* Runtime Condenser by Nodrak * Cleaned up and refactored by MrStonedOne * This will sum up identical runtimes into one, giving a total of how many times it occured. The first occurance @@ -387,3 +388,421 @@ int main() { return 0; } +======= +/* Runtime Condenser by Nodrak + * Cleaned up and refactored by MrStonedOne + * This will sum up identical runtimes into one, giving a total of how many times it occured. The first occurance + * of the runtime will log the source, usr and src, the rest will just add to the total. Infinite loops will + * also be caught and displayed (if any) above the list of runtimes. + * + * How to use: + * 1) Copy and paste your list of runtimes from Dream Daemon into input.exe + * 2) Run RuntimeCondenser.exe + * 3) Open output.txt for a condensed report of the runtimes + * + * How to compile: + * Requires visual c++ compiler 2012 or any linux compiler with c++11 support. + * Windows: + * Normal: cl.exe /EHsc /Ox /Qpar Main.cpp + * Debug: cl.exe /EHsc /Zi Main.cpp + * Linux: + * Normal: g++ -O3 -std=c++11 Main.cpp -o rc + * Debug: g++ -g -Og -std=c++11 Main.cpp -o rc + * Any Compile errors most likely indicate lack of c++11 support. Google how to upgrade or nag coderbus for help.. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PROGRESS_FPS 10 +#define PROGRESS_BAR_INNER_WIDTH 50 +#define LINEBUFFER (32*1024) //32KiB + +using namespace std; + +struct runtime { + string text; + string proc; + string source; + string usr; + string src; + string loc; + unsigned int count; +}; +struct harddel { + string type; + unsigned int count; +}; +//What we use to read input +string * lastLine = new string(); +string * currentLine = new string(); +string * nextLine = new string(); + +//Stores lines we want to keep to print out +unordered_map storedRuntime; +unordered_map storedInfiniteLoop; +unordered_map storedHardDel; + +//Stat tracking stuff for output +unsigned int totalRuntimes = 0; +unsigned int totalInfiniteLoops = 0; +unsigned int totalHardDels = 0; + + +bool endofbuffer = false; +//like substr, but returns an empty string if the string is smaller then start, rather then an exception. +inline string safe_substr(string * S, size_t start = 0, size_t end = string::npos) { + if (start > S->length()) + start = S->length(); + return S->substr(start, end); +} +//getline() is slow as fucking balls. this is quicker because we prefill a buffer rather then read 1 byte at a time searching for newlines, lowering on i/o calls and overhead. (110MB/s vs 40MB/s on a 1.8GB file pre-filled into the disk cache) +//if i wanted to make it even faster, I'd use a reading thread, a new line searching thread, another thread or four for searching for runtimes in the list to see if they are unique, and finally the main thread for displaying the progress bar. but fuck that noise. +inline string * readline(FILE * f) { + static char buf[LINEBUFFER]; + static size_t pos = 0; + static size_t size = 0; + + for (size_t i = pos; i < LINEBUFFER; i++) { + char c = buf[i]; + if (i >= size && (pos || i < LINEBUFFER-1)) { + if (feof(f) || ferror(f)) + break; + if (size && pos) { //move current stuff to start of buffer + size -= pos; + i -= pos; + memmove(buf, &buf[pos], size); + } + //fill remaining buffer + size += fread(&buf[i], 1, LINEBUFFER-size-1, f); + pos = 0; + c = buf[i]; + } + if (c == '\n') { + //trim off any newlines from the start + while (i > pos && (buf[pos] == '\r' || buf[pos] == '\n')) + pos++; + string * s = new string(&buf[pos], i-pos); + pos = i+1; + return s; + } + + } + string * s = new string(&buf[pos], size-pos); + pos = 0; + size = 0; + endofbuffer = true; + return s; +} + +inline void forward_progress(FILE * inputFile) { + delete(lastLine); + lastLine = currentLine; + currentLine = nextLine; + nextLine = readline(inputFile); + //strip out any timestamps. + if (nextLine->length() >= 10) { + if ((*nextLine)[0] == '[' && (*nextLine)[3] == ':' && (*nextLine)[6] == ':' && (*nextLine)[9] == ']') + nextLine->erase(0, 10); + } +} +//deallocates to, copys from to to. +inline void string_send(string * &from, string * &to) { + delete(to); + to = new string(*from); +} +inline void printprogressbar(unsigned short progress /*as percent*/) { + double const modifer = 100.0L/(double)PROGRESS_BAR_INNER_WIDTH; + size_t bars = (double)progress/modifer; + cerr << "\r[" << string(bars, '=') << ((progress < 100) ? ">" : "") << string(PROGRESS_BAR_INNER_WIDTH-(bars+((progress < 100) ? 1 : 0)), ' ') << "] " << progress << "%"; + cerr.flush(); +} + +bool readFromFile(bool isstdin) { + //Open file to read + FILE * inputFile = stdin; + if (!isstdin) + inputFile = fopen("Input.txt", "r"); + + if (ferror(inputFile)) + return false; + long long fileLength = 0; + clock_t nextupdate = 0; + if (!isstdin) { + fseek(inputFile, 0, SEEK_END); + fileLength = ftell(inputFile); + fseek(inputFile, 0, SEEK_SET); + nextupdate = clock(); + } + + if (feof(inputFile)) + return false; //empty file + do { + //Update our lines + forward_progress(inputFile); + //progress bar + + if (!isstdin && clock() >= nextupdate) { + int dProgress = (int)(((long double)ftell(inputFile) / (long double)fileLength) * 100.0L); + printprogressbar(dProgress); + nextupdate = clock() + (CLOCKS_PER_SEC/PROGRESS_FPS); + } + //Found a runtime! + if (safe_substr(currentLine, 0, 14) == "runtime error:") { + if (currentLine->length() <= 17) { //empty runtime, check next line. + //runtime is on the line before this one. (byond bug) + if (nextLine->length() < 2) { + string_send(lastLine, nextLine); + } + forward_progress(inputFile); + string * tmp = new string("runtime error: " + *currentLine); + string_send(tmp, currentLine); + delete(tmp); + } + //we assign this to the right container in a moment. + unordered_map * storage_container; + + //runtime is actually an infinite loop + if (safe_substr(currentLine, 15, 23) == "Infinite loop suspected" || safe_substr(currentLine, 15, 31) == "Maximum recursion level reached") { + //use our infinite loop container. + storage_container = &storedInfiniteLoop; + totalInfiniteLoops++; + // skip the line about world.loop_checks + forward_progress(inputFile); + string_send(lastLine, currentLine); + } else { + //use the runtime container + storage_container = &storedRuntime; + totalRuntimes++; + } + + string key = *currentLine; + bool procfound = false; //so other things don't have to bother checking for this again. + if (safe_substr(nextLine, 0, 10) == "proc name:") { + key += *nextLine; + procfound = true; + } + + //(get the address of a runtime from (a pointer to a container of runtimes)) to then store in a pointer to a runtime. + //(and who said pointers were hard.) + runtime* R = &((*storage_container)[key]); + + //new + if (R->text != *currentLine) { + R->text = *currentLine; + if (procfound) { + R->proc = *nextLine; + forward_progress(inputFile); + } + R->count = 1; + + //search for source file info + if (safe_substr(nextLine, 2, 12) == "source file:") { + R->source = *nextLine; + //skip again + forward_progress(inputFile); + } + //If we find this, we have new stuff to store + if (safe_substr(nextLine, 2, 4) == "usr:") { + forward_progress(inputFile); + forward_progress(inputFile); + //Store more info + R->usr = *lastLine; + R->src = *currentLine; + if (safe_substr(nextLine, 2, 8) == "src.loc:") { + R->loc = *nextLine; + forward_progress(inputFile); + } + } + + } else { //existed already + R->count++; + if (procfound) + forward_progress(inputFile); + } + + } else if (safe_substr(currentLine, 0, 7) == "Path : ") { + string deltype = safe_substr(currentLine, 7); + if (deltype.substr(deltype.size()-1,1) == " ") //some times they have a single trailing space. + deltype = deltype.substr(0, deltype.size()-1); + + unsigned int failures = strtoul(safe_substr(nextLine, 11).c_str(), NULL, 10); + if (failures <= 0) + continue; + + totalHardDels += failures; + harddel* D = &storedHardDel[deltype]; + if (D->type != deltype) { + D->type = deltype; + D->count = failures; + } else { + D->count += failures; + } + } + } while (!feof(inputFile) || !endofbuffer); //Until end of file + if (!isstdin) + printprogressbar(100); + cerr << endl; + return true; +} + +bool runtimeComp(const runtime &a, const runtime &b) { + return a.count > b.count; +} + +bool hardDelComp(const harddel &a, const harddel &b) { + return a.count > b.count; +} + +bool writeToFile(bool usestdio) { + //Open and clear the file + ostream * output = &cout; + ofstream * outputFile; + if (!usestdio) + output = outputFile = new ofstream("Output.txt", ios::trunc); + + + if(usestdio || outputFile->is_open()) { + *output << "Note: The source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.\n\n"; + if(storedInfiniteLoop.size() > 0) + *output << "Total unique infinite loops: " << storedInfiniteLoop.size() << endl; + + if(totalInfiniteLoops > 0) + *output << "Total infinite loops: " << totalInfiniteLoops << endl << endl; + + *output << "Total unique runtimes: " << storedRuntime.size() << endl; + *output << "Total runtimes: " << totalRuntimes << endl << endl; + if(storedHardDel.size() > 0) + *output << "Total unique hard deletions: " << storedHardDel.size() << endl; + + if(totalHardDels > 0) + *output << "Total hard deletions: " << totalHardDels << endl << endl; + + + //If we have infinite loops, display them first. + if(storedInfiniteLoop.size() > 0) { + vector infiniteLoops; + infiniteLoops.reserve(storedInfiniteLoop.size()); + for (unordered_map::iterator it=storedInfiniteLoop.begin(); it != storedInfiniteLoop.end(); it++) + infiniteLoops.push_back(it->second); + storedInfiniteLoop.clear(); + sort(infiniteLoops.begin(), infiniteLoops.end(), runtimeComp); + *output << "** Infinite loops **"; + for (int i=0; i < infiniteLoops.size(); i++) { + runtime* R = &infiniteLoops[i]; + *output << endl << endl << "The following infinite loop has occurred " << R->count << " time(s).\n"; + *output << R->text << endl; + if(R->proc.length()) + *output << R->proc << endl; + if(R->source.length()) + *output << R->source << endl; + if(R->usr.length()) + *output << R->usr << endl; + if(R->src.length()) + *output << R->src << endl; + if(R->loc.length()) + *output << R->loc << endl; + } + *output << endl << endl; //For spacing + } + + + //Do runtimes next + *output << "** Runtimes **"; + vector runtimes; + runtimes.reserve(storedRuntime.size()); + for (unordered_map::iterator it=storedRuntime.begin(); it != storedRuntime.end(); it++) + runtimes.push_back(it->second); + storedRuntime.clear(); + sort(runtimes.begin(), runtimes.end(), runtimeComp); + for (int i=0; i < runtimes.size(); i++) { + runtime* R = &runtimes[i]; + *output << endl << endl << "The following runtime has occurred " << R->count << " time(s).\n"; + *output << R->text << endl; + if(R->proc.length()) + *output << R->proc << endl; + if(R->source.length()) + *output << R->source << endl; + if(R->usr.length()) + *output << R->usr << endl; + if(R->src.length()) + *output << R->src << endl; + if(R->loc.length()) + *output << R->loc << endl; + } + *output << endl << endl; //For spacing + + //and finally, hard deletes + if(totalHardDels > 0) { + *output << endl << "** Hard deletions **"; + vector hardDels; + hardDels.reserve(storedHardDel.size()); + for (unordered_map::iterator it=storedHardDel.begin(); it != storedHardDel.end(); it++) + hardDels.push_back(it->second); + storedHardDel.clear(); + sort(hardDels.begin(), hardDels.end(), hardDelComp); + for(int i=0; i < hardDels.size(); i++) { + harddel* D = &hardDels[i]; + *output << endl << D->type << " - " << D->count << " time(s).\n"; + } + } + if (!usestdio) { + outputFile->close(); + delete outputFile; + } + } else { + return false; + } + return true; +} + +int main(int argc, const char * argv[]) { + ios_base::sync_with_stdio(false); + ios::sync_with_stdio(false); + bool usestdio = false; + if (argc >= 2 && !strcmp(argv[1], "-s")) + usestdio = true; + + char exit; //Used to stop the program from immediately exiting + cerr << "Reading input.\n"; + if(readFromFile(usestdio)) { + cerr << "Input read successfully!\n"; + } else { + cerr << "Input failed to open, shutting down.\n"; + if (!usestdio) { + cerr << "\nEnter any letter to quit.\n"; + exit = cin.get(); + } + return 1; + } + + + cerr << "Writing output.\n"; + if(writeToFile(usestdio)) { + cerr << "Output was successful!\n"; + if (!usestdio) { + cerr << "\nEnter any letter to quit.\n"; + exit = cin.get(); + } + return 0; + } else { + cerr << "The output file could not be opened, shutting down.\n"; + if (!usestdio) { + cerr << "\nEnter any letter to quit.\n"; + exit = cin.get(); + } + return 1; + } + + return 0; +} +>>>>>>> dbccf52... Merge pull request #33702 from MrStonedOne/rc-the-unix-way diff --git a/tools/Runtime Condenser/RuntimeCondenser.exe b/tools/Runtime Condenser/RuntimeCondenser.exe index e53102f219ae3b742e7189e864747027d1a71094..642efd09f035bac9cb105b9e920cf4b020c4ba22 100644 GIT binary patch literal 258048 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 HAqRNS=@|;+ePerS|&ZyGHzjVb~ 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%0DjQmYtJ|3}N0*dH? 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

    4{-Kyq{FW$h+ZN8KDR#`L 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 I|7{ZZU$L!W9smFU From e3a3082596b3d925a30f1d9a5037ef2151bad4e1 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 21 Dec 2017 01:46:19 -0500 Subject: [PATCH 61/96] Merge pull request #33703 from kevinz000/patch-407 Integrated circuit smoke circuit now requires atleast 10 units of reagents to generate smoke --- .../integrated_electronics/subtypes/reagents.dm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index 78b1e9682e..952015039c 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -1,3 +1,5 @@ +#define IC_SMOKE_REAGENTS_MINIMUM_UNITS 10 + /obj/item/integrated_circuit/reagent category_text = "Reagent" resistance_flags = UNACIDABLE | FIRE_PROOF @@ -8,8 +10,6 @@ if(volume) create_reagents(volume) - - /obj/item/integrated_circuit/reagent/smoke name = "smoke generator" desc = "Unlike most electronics, creating smoke is completely intentional." @@ -44,6 +44,8 @@ push_data() /obj/item/integrated_circuit/reagent/smoke/do_work() + if(!reagents || (reagents.total_volume < IC_SMOKE_REAGENTS_MINIMUM_UNITS)) + return var/location = get_turf(src) var/datum/effect_system/smoke_spread/chem/S = new S.attach(location) @@ -54,11 +56,9 @@ notified = TRUE S.start() - if(reagents) - reagents.clear_reagents() + reagents.clear_reagents() activate_pin(2) - /obj/item/integrated_circuit/reagent/injector name = "integrated hypo-injector" desc = "This scary looking thing is able to pump liquids into whatever it's pointed at." From 09c802f984f33e1078b1e8421f2cd3b4ca486ae8 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 21 Dec 2017 01:50:39 -0500 Subject: [PATCH 63/96] Merge pull request #33550 from ninjanomnom/instanceless-component-dupe Adds instanceless component dupe mode --- code/__DEFINES/components.dm | 7 +- code/datums/components/README.md | 5 +- code/datums/components/_component.dm | 100 ++++++++++++++------------ code/datums/components/radioactive.dm | 11 +-- code/datums/components/thermite.dm | 9 ++- 5 files changed, 76 insertions(+), 56 deletions(-) diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 4bb27d56d6..78ade5c650 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -6,9 +6,10 @@ // How multiple components of the exact same type are handled in the same datum -#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default) -#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed -#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted +#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default) +#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed +#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted +#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 //old component is given the initialization args of the new // All signals. Format: // When the signal is called: (signal arguments) diff --git a/code/datums/components/README.md b/code/datums/components/README.md index 574e628741..026b387e27 100644 --- a/code/datums/components/README.md +++ b/code/datums/components/README.md @@ -40,6 +40,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo * `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it * `COMPONENT_DUPE_ALLOWED`: The components will be treated as separate, `GetComponent()` will return the first added * `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it + * `COMPONENT_DUPE_UNIQUE_PASSARGS`: New component will never exist and instead its initialization arguments will be passed on to the old component. 1. `/datum/component/var/dupe_type` (protected, type) * Definition of a duplicate component type * `null` means exact match on `type` (default) @@ -66,6 +67,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo * All components a datum owns are deleted with the datum * Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set * If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it + * Properly handles duplicate situations based on the `dupe_mode` var 1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final) * Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead 1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async) @@ -104,9 +106,8 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo * Allows the component to react to ownership transfers 1. `/datum/component/proc/_RemoveFromParent()` (private, final) * Clears `parent` and removes the component from it's component list -1. `/datum/component/proc/_CheckDupesAndJoinParent` (private, final) +1. `/datum/component/proc/_JoinParent` (private, final) * Tries to add the component to it's `parent`s `datum_components` list - * Properly handles duplicate situations based on the `dupe_mode` var 1. `/datum/component/proc/RegisterSignal(signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) (Consider removing for performance gainz) * If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments * Makes a component listen for the specified `signal` on it's `parent` datum. diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index c54376d787..fcd4651459 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -6,54 +6,16 @@ var/datum/parent /datum/component/New(datum/P, ...) - if(type == /datum/component) - qdel(src) - CRASH("[type] instantiated!") - - //check for common mishaps - if(!isnum(dupe_mode)) - qdel(src) - CRASH("[type]: Invalid dupe_mode!") - var/dt = dupe_type - if(dt && !ispath(dt)) - qdel(src) - CRASH("[type]: Invalid dupe_type!") - parent = P var/list/arguments = args.Copy(2) if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE) qdel(src, TRUE, TRUE) return - _CheckDupesAndJoinParent(P) + _JoinParent(P) -/datum/component/proc/_CheckDupesAndJoinParent() +/datum/component/proc/_JoinParent() var/datum/P = parent - var/dm = dupe_mode - - var/datum/component/old - if(dm != COMPONENT_DUPE_ALLOWED) - var/dt = dupe_type - if(!dt) - old = P.GetExactComponent(type) - else - old = P.GetComponent(dt) - if(old) - //One or the other has to die - switch(dm) - if(COMPONENT_DUPE_UNIQUE) - old.InheritComponent(src, TRUE) - qdel(src, TRUE, TRUE) - return - if(COMPONENT_DUPE_HIGHLANDER) - InheritComponent(old, FALSE) - qdel(old, FALSE, TRUE) - - //provided we didn't eat someone - if(!old) - //let the others know - P.SendSignal(COMSIG_COMPONENT_ADDED, src) - //lazy init the parent's dc list var/list/dc = P.datum_components if(!dc) @@ -212,10 +174,59 @@ return list(.) /datum/proc/AddComponent(new_type, ...) - var/nt = new_type + var/datum/component/nt = new_type + var/dm = initial(nt.dupe_mode) + var/dt = initial(nt.dupe_type) + + var/datum/component/old_comp + var/datum/component/new_comp + + if(ispath(nt)) + if(nt == /datum/component) + CRASH("[nt] attempted instantiation!") + if(!isnum(dm)) + CRASH("[nt]: Invalid dupe_mode ([dm])!") + if(dt && !ispath(dt)) + CRASH("[nt]: Invalid dupe_type ([dt])!") + else + new_comp = nt + args[1] = src - var/datum/component/C = new nt(arglist(args)) - return QDELING(C) ? GetExactComponent(new_type) : C + + if(dm != COMPONENT_DUPE_ALLOWED) + if(!dt) + old_comp = GetExactComponent(nt) + else + old_comp = GetComponent(dt) + if(old_comp) + switch(dm) + if(COMPONENT_DUPE_UNIQUE) + if(!new_comp) + new_comp = new nt(arglist(args)) + if(!QDELETED(new_comp)) + old_comp.InheritComponent(new_comp, TRUE) + qdel(new_comp) + if(COMPONENT_DUPE_HIGHLANDER) + if(!new_comp) + new_comp = new nt(arglist(args)) + if(!QDELETED(new_comp)) + new_comp.InheritComponent(old_comp, FALSE) + qdel(old_comp) + if(COMPONENT_DUPE_UNIQUE_PASSARGS) + if(!new_comp) + var/list/arguments = args.Copy(2) + old_comp.InheritComponent(null, TRUE, arguments) + else + old_comp.InheritComponent(new_comp, TRUE) + else if(!new_comp) + new_comp = new nt(arglist(args)) // There's a valid dupe mode but there's no old component, act like normal + else if(!new_comp) + new_comp = new nt(arglist(args)) // Dupes are allowed, act like normal + + if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy + SendSignal(COMSIG_COMPONENT_ADDED, new_comp) + return new_comp + return old_comp /datum/proc/LoadComponent(component_type, ...) . = GetComponent(component_type) @@ -235,7 +246,8 @@ C._RemoveFromParent() helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C) C.parent = src - C._CheckDupesAndJoinParent() + if(C == AddComponent(C)) + C._JoinParent() /datum/proc/TransferComponents(datum/target) var/list/dc = datum_components diff --git a/code/datums/components/radioactive.dm b/code/datums/components/radioactive.dm index c149fd8492..fc0456ad10 100644 --- a/code/datums/components/radioactive.dm +++ b/code/datums/components/radioactive.dm @@ -4,7 +4,7 @@ #define RAD_AMOUNT_EXTREME 1000 /datum/component/radioactive - dupe_mode = COMPONENT_DUPE_UNIQUE + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS var/source @@ -47,13 +47,16 @@ if(strength <= RAD_BACKGROUND_RADIATION) return PROCESS_KILL -/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original) +/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, list/arguments) if(!i_am_original) return if(!hl3_release_date) // Permanently radioactive things don't get to grow stronger return - var/datum/component/radioactive/other = C - strength = max(strength, other.strength) + if(C) + var/datum/component/radioactive/other = C + strength = max(strength, other.strength) + else + strength = max(strength, arguments[1]) /datum/component/radioactive/proc/rad_examine(mob/user, atom/thing) var/atom/master = parent diff --git a/code/datums/components/thermite.dm b/code/datums/components/thermite.dm index f76178213d..11611cadfb 100644 --- a/code/datums/components/thermite.dm +++ b/code/datums/components/thermite.dm @@ -1,5 +1,5 @@ /datum/component/thermite - dupe_mode = COMPONENT_DUPE_UNIQUE + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS var/amount var/overlay @@ -46,10 +46,13 @@ master.cut_overlay(overlay) return ..() -/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original) +/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original, list/arguments) if(!i_am_original) return - amount += newC.amount + if(newC) + amount += newC.amount + else + amount += arguments[1] /datum/component/thermite/proc/thermite_melt(mob/user) var/turf/master = parent From 14942fb582482d127ef0fd0660ee521495c4ba35 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 21 Dec 2017 02:37:52 -0500 Subject: [PATCH 65/96] Merge pull request #33706 from AnturK/dumbmechacode Fixes some mecha code. --- code/game/mecha/mecha.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 799344fe54..2d148b4ff4 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -571,9 +571,9 @@ if(bumpsmash && occupant) //Need a pilot to push the PUNCH button. if(nextsmash < world.time) obstacle.mech_melee_attack(src) - if(!obstacle || !obstacle.density) - step(src,dir) nextsmash = world.time + smashcooldown + if(!obstacle || obstacle.CanPass(src,get_step(src,dir))) + step(src,dir) if(isobj(obstacle)) var/obj/O = obstacle if(!O.anchored) From 86fed404b167266251f31a4bab1ef658081c1919 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 21 Dec 2017 04:36:01 -0600 Subject: [PATCH 67/96] Update weldingtool.dm --- code/game/objects/items/tools/weldingtool.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index ee51e6bf82..12c056c9af 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -241,7 +241,7 @@ container_type = NONE else to_chat(user, "[src] can now be attached, modified, and refuelled.") - container_type = OPENCONTAINER_1 + container_type = OPENCONTAINER add_fingerprint(user) /obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) From 4d01f1c6bf6cad2b88e089a5c270a8dc9ad7d7cb Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 04:56:37 -0600 Subject: [PATCH 68/96] Automatic changelog generation for PR #4475 [ci skip] --- html/changelogs/AutoChangeLog-pr-4475.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4475.yml diff --git a/html/changelogs/AutoChangeLog-pr-4475.yml b/html/changelogs/AutoChangeLog-pr-4475.yml new file mode 100644 index 0000000000..f37e80ed55 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4475.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - bugfix: "Passing a space transition no longer interrupts pulls." From e070e5b023aaab3907a6b2d23253ce434c711f23 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 04:57:21 -0600 Subject: [PATCH 69/96] Automatic changelog generation for PR #4477 [ci skip] --- html/changelogs/AutoChangeLog-pr-4477.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4477.yml diff --git a/html/changelogs/AutoChangeLog-pr-4477.yml b/html/changelogs/AutoChangeLog-pr-4477.yml new file mode 100644 index 0000000000..bba0dab724 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4477.yml @@ -0,0 +1,4 @@ +author: "Fox McCloud" +delete-after: True +changes: + - bugfix: "Fixes arm implants being immune to EMPs" From 0decf08a7f68c623f2ae36625eb6d597ac259c42 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 04:58:08 -0600 Subject: [PATCH 70/96] Automatic changelog generation for PR #4479 [ci skip] --- html/changelogs/AutoChangeLog-pr-4479.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4479.yml diff --git a/html/changelogs/AutoChangeLog-pr-4479.yml b/html/changelogs/AutoChangeLog-pr-4479.yml new file mode 100644 index 0000000000..623a1ada72 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4479.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - rscdel: "Integrated circuit smoke circuits now require 10 units of reagents to fire." From 13c6a7d73830ed0081cbdac7642527afbcad61f7 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 04:59:02 -0600 Subject: [PATCH 71/96] Automatic changelog generation for PR #4466 [ci skip] --- html/changelogs/AutoChangeLog-pr-4466.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4466.yml diff --git a/html/changelogs/AutoChangeLog-pr-4466.yml b/html/changelogs/AutoChangeLog-pr-4466.yml new file mode 100644 index 0000000000..e8239ebfb4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4466.yml @@ -0,0 +1,4 @@ +author: "Toriate" +delete-after: True +changes: + - balance: "Roundstart xenos are no longer pierce immune, also no more extra damage from heat." From fddd04c964e1eaed5c012b97000d0c2ce5567bfa Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 04:59:47 -0600 Subject: [PATCH 72/96] Automatic changelog generation for PR #4446 [ci skip] --- html/changelogs/AutoChangeLog-pr-4446.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4446.yml diff --git a/html/changelogs/AutoChangeLog-pr-4446.yml b/html/changelogs/AutoChangeLog-pr-4446.yml new file mode 100644 index 0000000000..3811f7ffb7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4446.yml @@ -0,0 +1,5 @@ +author: "coiax" +delete-after: True +changes: + - balance: "The codespeak manual now has unlimited uses and costs 3 TC." + - bugfix: "Nuke ops can now purchase the codespeak manual, as was intended." From c4f2e2f911e16733da3ef1deb9834de740bcb27e Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 05:01:34 -0600 Subject: [PATCH 73/96] Automatic changelog generation for PR #4412 [ci skip] --- html/changelogs/AutoChangeLog-pr-4412.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4412.yml diff --git a/html/changelogs/AutoChangeLog-pr-4412.yml b/html/changelogs/AutoChangeLog-pr-4412.yml new file mode 100644 index 0000000000..6280189218 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4412.yml @@ -0,0 +1,4 @@ +author: "Xhuis" +delete-after: True +changes: + - tweak: "Vitality matrices don't have visible messages when someone crosses them anymore." From ff4c5907a67b258fbea465a39e837037c53da35c Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 08:04:20 -0600 Subject: [PATCH 74/96] [MIRROR] Fixes chat SDQL permanently disabling all admin sdql and proccalls for the round. (#4484) * Merge pull request #33730 from kevinz000/patch-409 Fixes chat SDQL permanently disabling all admin sdql and proccalls for the round. * Fixes chat SDQL permanently disabling all admin sdql and proccalls for the round. --- code/modules/admin/chat_commands.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/admin/chat_commands.dm b/code/modules/admin/chat_commands.dm index 744455bb9a..bc41b489c0 100644 --- a/code/modules/admin/chat_commands.dm +++ b/code/modules/admin/chat_commands.dm @@ -94,6 +94,7 @@ GLOBAL_LIST(round_end_notifiees) return "Unable to run query, another admin proc call is in progress. Try again later." GLOB.AdminProcCaller = "CHAT_[sender]" //_ won't show up in ckeys so it'll never match with a real admin var/list/results = world.SDQL2_query(params, GLOB.AdminProcCaller, GLOB.AdminProcCaller) + GLOB.AdminProcCaller = null if(!results) return "Query produced no output" var/list/text_res = results.Copy(1, 3) From abced738bd3448659b200328d72276158da9abc3 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 21 Dec 2017 09:52:42 -0600 Subject: [PATCH 75/96] Revert "[MIRROR] Db schema version check by simplification" --- code/game/world.dm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/game/world.dm b/code/game/world.dm index 6c49e37456..2853bb2ef6 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -62,15 +62,15 @@ GLOBAL_PROTECT(security_mode) var/db_major = text2num(query_db_version.item[1]) var/db_minor = text2num(query_db_version.item[2]) if(db_major != DB_MAJOR_VERSION || db_minor != DB_MINOR_VERSION) - message_admins("Database schema ([db_major].[db_minor]) doesn't match the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") - log_sql("Database schema ([db_major].[db_minor]) doesn't match the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") + var/which = "behind" + if(db_major < DB_MAJOR_VERSION || db_minor < DB_MINOR_VERSION) + which = "ahead of" + message_admins("Database schema ([db_major].[db_minor]) is [which] the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") + log_sql("Database schema ([db_major].[db_minor]) is [which] the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") else message_admins("Could not get schema version from database") - log_sql("Could not get schema version from database") else - log_sql("Your server failed to establish a connection with the database.") - else - log_sql("Database is not enabled in configuration.") + log_world("Your server failed to establish a connection with the database.") /world/proc/SetRoundID() if(CONFIG_GET(flag/sql_enabled)) From 6573aa52e4474764c7d756c2b20a1d4d823e293a Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 21 Dec 2017 12:42:18 -0600 Subject: [PATCH 76/96] Update departmental_circuit_imprinter.dm --- code/modules/research/departmental_circuit_imprinter.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/modules/research/departmental_circuit_imprinter.dm b/code/modules/research/departmental_circuit_imprinter.dm index 991feccb66..7b06aaa839 100644 --- a/code/modules/research/departmental_circuit_imprinter.dm +++ b/code/modules/research/departmental_circuit_imprinter.dm @@ -4,10 +4,8 @@ icon_state = "circuit_imprinter" container_type = OPENCONTAINER circuit = /obj/item/circuitboard/machine/circuit_imprinter/department - console_link = FALSE requires_console = FALSE - var/list/allowed_department_flags = DEPARTMENTAL_FLAG_ALL var/list/datum/design/cached_designs var/list/datum/design/matching_designs var/department_tag = "Unidentified" //used for material distribution among other things. From 8e6c8fc8b5eaddf95032b6d4521027994988e83e Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 21 Dec 2017 12:43:21 -0600 Subject: [PATCH 77/96] Update departmental_lathe.dm --- code/modules/research/departmental_lathe.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/modules/research/departmental_lathe.dm b/code/modules/research/departmental_lathe.dm index 83f543e4cb..4e8d33a3a3 100644 --- a/code/modules/research/departmental_lathe.dm +++ b/code/modules/research/departmental_lathe.dm @@ -4,10 +4,8 @@ icon_state = "protolathe" container_type = OPENCONTAINER circuit = /obj/item/circuitboard/machine/protolathe/department - console_link = FALSE requires_console = FALSE - var/list/allowed_department_flags = DEPARTMENTAL_FLAG_ALL var/list/datum/design/cached_designs var/list/datum/design/matching_designs var/department_tag = "Unidentified" //used for material distribution among other things. From 2d995e3f5a9ed632fa8fca98d219589687d99422 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 21 Dec 2017 12:44:16 -0600 Subject: [PATCH 78/96] Update rdconsole.dm --- code/modules/research/rdconsole.dm | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 116d41d7f8..0c468b184a 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -150,11 +150,9 @@ doesn't have toxins access. return FALSE var/price = TN.get_price(stored_research) if(stored_research.research_points >= price) - investigate_log("[key_name_admin(user)] researched [id]([price]) on techweb id [stored_research.id].") + investigate_log("[key_name(user)] researched [id]([price]) on techweb id [stored_research.id].", INVESTIGATE_RESEARCH) if(stored_research == SSresearch.science_tech) - if(stored_research.researched_nodes.len < 30) - SSblackbox.record_feedback("tally", "science_techweb_unlock_first_thirty", 1, "[id]") - SSblackbox.record_feedback("tally", "science_techweb_unlock", 1, "[id]") + SSblackbox.record_feedback("associative", "science_techweb_unlock", 1, list("id" = "[id]", "price" = "[price]", "time" = "[SQLtime()]")) if(stored_research.research_node(SSresearch.techweb_nodes[id])) say("Sucessfully researched [TN.display_name].") var/logname = "Unknown" @@ -231,11 +229,16 @@ doesn't have toxins access. var/list/l = list() if(research_control) l += "

    Technology" - l += "
    Design Disk" - l += "
    Tech Disk" - l += "
    Deconstructive Analyzer" - l += "
    Protolathe" - l += "
    Circuit Imprinter" + if(d_disk) + l += "
    Design Disk" + if(t_disk) + l += "
    Tech Disk" + if(linked_destroy) + l += "
    Deconstructive Analyzer" + if(linked_lathe) + l += "
    Protolathe" + if(linked_imprinter) + l += "
    Circuit Imprinter" l += "
    Settings

    " return l @@ -278,6 +281,8 @@ doesn't have toxins access. var/datum/design/D = stored_research.researched_designs[v] if(!(selected_category in D.category)|| !(D.build_type & PROTOLATHE)) continue + if(!(D.departmental_flags & linked_lathe.allowed_department_flags)) + continue var/temp_material var/c = 50 var/t @@ -328,6 +333,8 @@ doesn't have toxins access. l += ui_protolathe_header() var/coeff = linked_lathe.efficiency_coeff for(var/datum/design/D in matching_designs) + if(!(D.departmental_flags & linked_lathe.allowed_department_flags)) + continue var/temp_material var/c = 50 var/t @@ -416,6 +423,8 @@ doesn't have toxins access. var/datum/design/D = stored_research.researched_designs[v] if(!(selected_category in D.category) || !(D.build_type & IMPRINTER)) continue + if(!(D.departmental_flags & linked_imprinter.allowed_department_flags)) + continue var/temp_materials var/check_materials = TRUE @@ -443,6 +452,8 @@ doesn't have toxins access. var/coeff = linked_imprinter.efficiency_coeff for(var/datum/design/D in matching_designs) + if(!(D.departmental_flags & linked_imprinter.allowed_department_flags)) + continue var/temp_materials var/check_materials = TRUE var/all_materials = D.materials + D.reagents_list From 087c43ab71614c512b0ab5ab9118c9505bd11614 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 21 Dec 2017 12:44:59 -0600 Subject: [PATCH 79/96] Update rdmachines.dm --- code/modules/research/rdmachines.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index 61b06d356e..663d3fc806 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -15,7 +15,8 @@ var/shocked = FALSE var/obj/machinery/computer/rdconsole/linked_console var/obj/item/loaded_item = null //the item loaded inside the machine (currently only used by experimentor and destructive analyzer) - + var/allowed_department_flags = ALL + /obj/machinery/rnd/proc/reset_busy() busy = FALSE From 529e839203e86d83c2086e812c5b743b85fbda13 Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 21 Dec 2017 13:46:44 -0600 Subject: [PATCH 80/96] dog borgs module icon fix --- code/modules/mob/living/silicon/robot/robot_modules.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index b1be1c3076..26e455106b 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -352,7 +352,7 @@ ratvar_modules = list(/obj/item/clockwork/slab/cyborg/security, /obj/item/clockwork/weapon/ratvarian_spear) cyborg_base_icon = "k9" - moduleselect_icon = "k9" + moduleselect_icon = "security" can_be_pushed = FALSE hat_offset = INFINITY @@ -387,7 +387,7 @@ ratvar_modules = list(/obj/item/clockwork/slab/cyborg/medical, /obj/item/clockwork/weapon/ratvarian_spear) cyborg_base_icon = "medihound" - moduleselect_icon = "medihound" + moduleselect_icon = "medical" can_be_pushed = FALSE hat_offset = INFINITY @@ -409,7 +409,7 @@ /obj/item/clockwork/slab/cyborg/janitor, /obj/item/clockwork/replica_fabricator/cyborg) cyborg_base_icon = "scrubpup" - moduleselect_icon = "scrubpup" + moduleselect_icon = "janitor" hat_offset = INFINITY clean_on_move = TRUE From 2eaae2eb14bfc4c6ca22ed53c6ff7da106a9e2a9 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 13:56:22 -0600 Subject: [PATCH 81/96] Automatic changelog generation for PR #4487 [ci skip] --- html/changelogs/AutoChangeLog-pr-4487.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4487.yml diff --git a/html/changelogs/AutoChangeLog-pr-4487.yml b/html/changelogs/AutoChangeLog-pr-4487.yml new file mode 100644 index 0000000000..588566e15c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4487.yml @@ -0,0 +1,4 @@ +author: "ganglyalexander" +delete-after: True +changes: + - bugfix: "module icons for dog borgs now reference to a existing icon" From e9d888840796aff46406bc49a411eeb3e98ac414 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 14:19:55 -0600 Subject: [PATCH 82/96] Automatic changelog generation for PR #4433 [ci skip] --- html/changelogs/AutoChangeLog-pr-4433.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4433.yml diff --git a/html/changelogs/AutoChangeLog-pr-4433.yml b/html/changelogs/AutoChangeLog-pr-4433.yml new file mode 100644 index 0000000000..39bde17139 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4433.yml @@ -0,0 +1,4 @@ +author: "ninjanomnom" +delete-after: True +changes: + - bugfix: "Decals should now rotate the correct way around." From 3f78bdcf59de77c15765d621f351d0e380a6dec9 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 21 Dec 2017 14:15:42 -0500 Subject: [PATCH 83/96] Merge pull request #33606 from coiax/antaghud-on-end Everyone gains antag HUD at round end --- code/__HELPERS/roundend.dm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 3b346f7e1c..f009ff9c00 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -82,6 +82,14 @@ CHECK_TICK + // Add AntagHUD to everyone, see who was really evil the whole time! + for(var/datum/atom_hud/antag/H in GLOB.huds) + for(var/m in GLOB.player_list) + var/mob/M = m + H.add_hud_to(M) + + CHECK_TICK + //Set news report and mode result mode.set_round_result() From 52257ff371778e3ea85295e091fbd221ce9e28bd Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 21 Dec 2017 14:13:46 -0500 Subject: [PATCH 85/96] Merge pull request #33710 from ShizCalev/crashedship Corrects crashedship diags --- _maps/RandomRuins/SpaceRuins/crashedship.dmm | 39 +++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/_maps/RandomRuins/SpaceRuins/crashedship.dmm b/_maps/RandomRuins/SpaceRuins/crashedship.dmm index 0ed7578efd..2a1fc96a1b 100644 --- a/_maps/RandomRuins/SpaceRuins/crashedship.dmm +++ b/_maps/RandomRuins/SpaceRuins/crashedship.dmm @@ -68,7 +68,7 @@ /turf/open/floor/engine, /area/awaymission/BMPship/Aft) "ap" = ( -/turf/closed/wall/mineral/titanium/overspace, +/turf/closed/wall/mineral/titanium/nodiagonal, /area/awaymission/BMPship/Midship) "aq" = ( /turf/closed/wall/mineral/titanium, @@ -2309,6 +2309,27 @@ }, /turf/open/floor/carpet, /area/awaymission/BMPship/Fore) +"hy" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/awaymission/BMPship/Fore) +"hz" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/awaymission/BMPship/Fore) +"hA" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/awaymission/BMPship/Fore) +"hB" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/awaymission/BMPship/Fore) +"hC" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/awaymission/BMPship/Fore) +"hD" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/awaymission/BMPship/Fore) +"hE" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/awaymission/BMPship/Fore) (1,1,1) = {" aa @@ -2684,8 +2705,8 @@ aa aa aa aa -cF -aT +aI +hD bV hx ee @@ -2735,7 +2756,7 @@ aa aa aa aI -aH +hC bV bV dH @@ -2785,7 +2806,7 @@ aa aa aa aI -aT +hB bV bV bV @@ -2834,8 +2855,8 @@ aH aQ bl bt -aT -aT +hy +hA bV bV cY @@ -2849,7 +2870,7 @@ bI fv fJ aH -aH +hE aQ gF gR @@ -2987,7 +3008,7 @@ aH aT aT aT -aT +hz bW co cH From b188266478e71838e0aa439c75307596f6182704 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 21 Dec 2017 12:48:15 -0500 Subject: [PATCH 87/96] Merge pull request #33709 from uraniummeltdown/linespacing Adjustable Chat Line Height --- .../browserassets/css/browserOutput.css | 2 +- .../browserassets/html/browserOutput.html | 2 ++ .../browserassets/js/browserOutput.js | 27 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css index 3403253c07..c72f26a4e7 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ b/code/modules/goonchat/browserassets/css/browserOutput.css @@ -13,7 +13,7 @@ body { background: #fff; font-family: Verdana, sans-serif; font-size: 9pt; - line-height: 1.4; + line-height: 1.2; overflow-x: hidden; overflow-y: scroll; word-wrap: break-word; diff --git a/code/modules/goonchat/browserassets/html/browserOutput.html b/code/modules/goonchat/browserassets/html/browserOutput.html index 82a1ed4885..d40fd75f39 100644 --- a/code/modules/goonchat/browserassets/html/browserOutput.html +++ b/code/modules/goonchat/browserassets/html/browserOutput.html @@ -36,6 +36,8 @@
    Decrease font size - Increase font size + + Decrease line height - + Increase line height + Toggle ping display Highlight string Save chat log diff --git a/code/modules/goonchat/browserassets/js/browserOutput.js b/code/modules/goonchat/browserassets/js/browserOutput.js index 43092846c2..4ca135bfd7 100644 --- a/code/modules/goonchat/browserassets/js/browserOutput.js +++ b/code/modules/goonchat/browserassets/js/browserOutput.js @@ -593,6 +593,7 @@ $(function() { ******************************************/ var savedConfig = { 'sfontSize': getCookie('fontsize'), + 'slineHeight': getCookie('lineheight'), 'spingDisabled': getCookie('pingdisabled'), 'shighlightTerms': getCookie('highlightterms'), 'shighlightColor': getCookie('highlightcolor'), @@ -604,6 +605,10 @@ $(function() { $messages.css('font-size', savedConfig.sfontSize); internalOutput('Loaded font size setting of: '+savedConfig.sfontSize+'', 'internal'); } + if (savedConfig.slineHeight) { + $("body").css('line-height', savedConfig.slineHeight); + internalOutput('Loaded line height setting of: '+savedConfig.slineHeight+'', 'internal'); + } if (savedConfig.spingDisabled) { if (savedConfig.spingDisabled == 'true') { opts.pingDisabled = true; @@ -843,6 +848,28 @@ $(function() { internalOutput('Font size set to '+fontSize+'', 'internal'); }); + $('#decreaseLineHeight').click(function(e) { + var Heightline = parseFloat($("body").css('line-height')); + var Sizefont = parseFloat($("body").css('font-size')); + var lineheightvar = Heightline / Sizefont + lineheightvar -= 0.1; + lineheightvar = lineheightvar.toFixed(1) + $("body").css({'line-height': lineheightvar}); + setCookie('lineheight', lineheightvar, 365); + internalOutput('Line height set to '+lineheightvar+'', 'internal'); + }); + + $('#increaseLineHeight').click(function(e) { + var Heightline = parseFloat($("body").css('line-height')); + var Sizefont = parseFloat($("body").css('font-size')); + var lineheightvar = Heightline / Sizefont + lineheightvar += 0.1; + lineheightvar = lineheightvar.toFixed(1) + $("body").css({'line-height': lineheightvar}); + setCookie('lineheight', lineheightvar, 365); + internalOutput('Line height set to '+lineheightvar+'', 'internal'); + }); + $('#togglePing').click(function(e) { if (opts.pingDisabled) { $('#ping').slideDown('fast'); From 56da16b270ad29120ac2b5737cd6291405795329 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 15:36:08 -0600 Subject: [PATCH 89/96] Automatic changelog generation for PR #4490 [ci skip] --- html/changelogs/AutoChangeLog-pr-4490.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4490.yml diff --git a/html/changelogs/AutoChangeLog-pr-4490.yml b/html/changelogs/AutoChangeLog-pr-4490.yml new file mode 100644 index 0000000000..6477196745 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4490.yml @@ -0,0 +1,5 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - rscadd: "You can adjust line height in chat settings" + - tweak: "Default chat line height is slightly shorter, from 1.4 to 1.2" From a990811cee1b348fa80f8cadcd830187ff6bbfaf Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 21 Dec 2017 15:37:35 -0600 Subject: [PATCH 90/96] Automatic changelog generation for PR #4488 [ci skip] --- html/changelogs/AutoChangeLog-pr-4488.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4488.yml diff --git a/html/changelogs/AutoChangeLog-pr-4488.yml b/html/changelogs/AutoChangeLog-pr-4488.yml new file mode 100644 index 0000000000..21031f2cf3 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4488.yml @@ -0,0 +1,5 @@ +author: "coiax" +delete-after: True +changes: + - rscadd: "At the end of the round, all players can see who the antagonists +are." From a82d0e13cea8710586400a9babaee9de4d2e2688 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Fri, 22 Dec 2017 00:02:48 -0800 Subject: [PATCH 91/96] Fixes RND --- code/__DEFINES/misc.dm | 10 +- code/__DEFINES/research.dm | 6 + code/modules/research/circuitprinter.dm | 14 +- .../departmental_circuit_imprinter.dm | 3 +- code/modules/research/departmental_lathe.dm | 3 +- code/modules/research/designs.dm | 38 ++ .../research/designs/AI_module_designs.dm | 4 +- .../research/designs/autolathe_designs.dm | 8 - code/modules/research/destructive_analyzer.dm | 24 +- code/modules/research/protolathe.dm | 16 +- code/modules/research/rdconsole.dm | 292 ++++++++----- code/modules/research/rdmachines.dm | 29 +- code/modules/research/stock_parts.dm | 1 - .../research/techweb/__techweb_helpers.dm | 7 +- code/modules/research/techweb/_techweb.dm | 34 +- .../modules/research/techweb/_techweb_node.dm | 6 +- code/modules/research/techweb/all_nodes.dm | 411 +++++++++--------- .../research/xenobiology/xenobiology.dm | 2 +- html/browser/techwebs.css | 20 + tgstation.dme | 2 +- 20 files changed, 556 insertions(+), 374 deletions(-) create mode 100644 html/browser/techwebs.css diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index b5d07646d7..d112222816 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -334,9 +334,9 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE #endif #endif - // Consider these images/atoms as part of the UI/HUD +// Consider these images/atoms as part of the UI/HUD #define APPEARANCE_UI_IGNORE_ALPHA RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA|PIXEL_SCALE -#define APPEARANCE_UI RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR +#define APPEARANCE_UI RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|PIXEL_SCALE //Just space #define SPACE_ICON_STATE "[((x + y) ^ ~(x * y) + z) % 25]" @@ -444,6 +444,7 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE #define GIBTONITE_ACTIVE 1 #define GIBTONITE_STABLE 2 #define GIBTONITE_DETONATE 3 + //for obj explosion block calculation #define EXPLOSION_BLOCK_PROC -1 @@ -452,8 +453,6 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE #define BEAT_SLOW 2 #define BEAT_NONE 0 -#define BEAT_CHANNEL 150 - //http://www.byond.com/docs/ref/info.html#/atom/var/mouse_opacity #define MOUSE_OPACITY_TRANSPARENT 0 #define MOUSE_OPACITY_ICON 1 @@ -484,9 +483,6 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE #define SYRINGE_DRAW 0 #define SYRINGE_INJECT 1 -#define RESEARCH_MATERIAL_RECLAMATION_ID "0" - - //gold slime core spawning #define NO_SPAWN 0 #define HOSTILE_SPAWN 1 diff --git a/code/__DEFINES/research.dm b/code/__DEFINES/research.dm index 14e6798528..bb2e232886 100644 --- a/code/__DEFINES/research.dm +++ b/code/__DEFINES/research.dm @@ -1,4 +1,8 @@ +#define RDCONSOLE_UI_MODE_NORMAL 1 +#define RDCONSOLE_UI_MODE_EXPERT 2 +#define RDCONSOLE_UI_MODE_LIST 3 + //RDSCREEN screens #define RDSCREEN_MENU 0 #define RDSCREEN_TECHDISK 1 @@ -59,3 +63,5 @@ //#define DEPARTMENTAL_FLAG_MINING 128 #define DESIGN_ID_IGNORE "IGNORE_THIS_DESIGN" + +#define RESEARCH_MATERIAL_RECLAMATION_ID "__materials" diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index 26fa304209..207b610a8c 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -12,8 +12,6 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). circuit = /obj/item/circuitboard/machine/circuit_imprinter var/efficiency_coeff - var/console_link = TRUE //can this link to a console? - var/requires_console = TRUE var/datum/component/material_container/materials //Store for hyper speed! @@ -32,11 +30,11 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). ) /obj/machinery/rnd/circuit_imprinter/Initialize() - var/datum/component/material_container/materials materials = AddComponent(/datum/component/material_container, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE), 0, FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE create_reagents(0) + RefreshParts() return ..() /obj/machinery/rnd/circuit_imprinter/RefreshParts() @@ -119,11 +117,9 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). return TRUE /obj/machinery/rnd/circuit_imprinter/proc/do_print(path, list/matlist, notify_admins) - if(notify_admins) - if(usr) - usr.investigate_log("built [path] at a circuit imprinter.", INVESTIGATE_RESEARCH) - var/turf/T = get_turf(usr) - message_admins("[key_name(usr)][ADMIN_JMP(T)] has built [path] at a circuit imprinter at [COORD(usr)]") + if(notify_admins && usr) + investigate_log("[key_name(usr)] built [path] at a circuit imprinter.", INVESTIGATE_RESEARCH) + message_admins("[ADMIN_LOOKUPFLW(usr)] has built [path] at a circuit imprinter.") var/obj/item/I = new path(get_turf(src)) I.materials = matlist.Copy() - SSblackbox.record_feedback("nested_tally", "circuit_printed", 1, list("[type]", "[path]")) + SSblackbox.record_feedback("nested tally", "circuit_printed", 1, list("[type]", "[path]")) diff --git a/code/modules/research/departmental_circuit_imprinter.dm b/code/modules/research/departmental_circuit_imprinter.dm index 7b06aaa839..06e7c531b8 100644 --- a/code/modules/research/departmental_circuit_imprinter.dm +++ b/code/modules/research/departmental_circuit_imprinter.dm @@ -143,8 +143,7 @@ /obj/machinery/rnd/circuit_imprinter/department/proc/ui_header() var/list/l = list() - l += "

    Nanotrasen Department Circuit Imprinter: [department_tag]

    [RDSCREEN_NOBREAK]" - l += "
    Connected Technology database: [host_research == SSresearch.science_tech? "Nanotrasen" : "Third Party"]" + l += "
    [host_research.organization] [department_tag] Department Circuit Imprinter" l += "Security protocols: [emagged? "Disabled" : "Enabled"]" l += "Material Amount: [materials.total_amount] / [materials.max_amount]" l += "Chemical volume: [reagents.total_volume] / [reagents.maximum_volume]" diff --git a/code/modules/research/departmental_lathe.dm b/code/modules/research/departmental_lathe.dm index 4e8d33a3a3..dc3c8ad66f 100644 --- a/code/modules/research/departmental_lathe.dm +++ b/code/modules/research/departmental_lathe.dm @@ -186,8 +186,7 @@ /obj/machinery/rnd/protolathe/department/proc/ui_header() var/list/l = list() - l += "

    Nanotrasen Department Lathe: [department_tag]

    [RDSCREEN_NOBREAK]" - l += "
    Connected Technology database: [host_research == SSresearch.science_tech? "Nanotrasen" : "Third Party"]" + l += "
    [host_research.organization] [department_tag] Department Lathe" l += "Security protocols: [emagged? "Disabled" : "Enabled"]" l += "Material Amount: [materials.total_amount] / [materials.max_amount]" l += "Chemical volume: [reagents.total_volume] / [reagents.maximum_volume]" diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index e16aadb7cd..0af1650d42 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -43,11 +43,49 @@ other types of metals and chemistry for reagents). var/lathe_time_factor = 1 //How many times faster than normal is this to build on the protolathe var/dangerous_construction = FALSE //notify and log for admin investigations if this is printed. var/departmental_flags = ALL //bitflags for deplathes. + var/list/datum/techweb_node/unlocked_by = list() + var/icon_cache /datum/design/Destroy() CRASH("DESIGN DATUMS SHOULD NOT EVER BE DESTROYED AS THEY ARE ONLY MEANT TO BE IN A GLOBAL LIST AND REFERENCED FOR US.") return ..() +/datum/design/proc/icon_html(client/user) + if (!icon_cache) + // construct the icon and slap it into the resource cache + var/atom/item = build_path + if (!ispath(item, /atom)) + // biogenerator outputs to beakers by default + if (build_type & BIOGENERATOR) + item = /obj/item/reagent_containers/glass/beaker/large + else + return // shouldn't happen, but just in case + + // circuit boards become their resulting machines or computers + if (ispath(item, /obj/item/circuitboard)) + var/obj/item/circuitboard/C = item + var/machine = initial(C.build_path) + if (machine) + item = machine + var/icon_file = initial(item.icon) + var/icon/I = icon(icon_file, initial(item.icon_state), SOUTH) + + // computers (and snowflakes) get their screen and keyboard sprites + if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control)) + var/obj/machinery/computer/C = item + var/screen = initial(C.icon_screen) + var/keyboard = initial(C.icon_keyboard) + if (screen) + I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY) + if (keyboard) + I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY) + + // based on icon2html + icon_cache = "[generate_asset_name(I)].png" + register_asset(icon_cache, I) + send_asset(user, icon_cache, FALSE) + return "" + //////////////////////////////////////// //Disks for transporting design datums// //////////////////////////////////////// diff --git a/code/modules/research/designs/AI_module_designs.dm b/code/modules/research/designs/AI_module_designs.dm index 13ddd2582f..eb92bb3737 100644 --- a/code/modules/research/designs/AI_module_designs.dm +++ b/code/modules/research/designs/AI_module_designs.dm @@ -20,8 +20,8 @@ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE /datum/design/board/onehuman_module - name = "Module Design (OneCrew)" - desc = "Allows for the construction of a OneCrew AI Module." + name = "Module Design (OneHuman)" + desc = "Allows for the construction of a OneHuman AI Module." id = "onehuman_module" materials = list(MAT_GLASS = 1000, MAT_DIAMOND = 100) build_path = /obj/item/aiModule/zeroth/oneHuman diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index ff2ccc938f..8542660343 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -600,14 +600,6 @@ build_path = /obj/item/device/electropack category = list("hacked", "Tools") -/datum/design/shock_collar - name = "Shock Collar" - id = "shock_collar" - build_type = AUTOLATHE - materials = list(MAT_METAL = 5000, MAT_GLASS = 2000) - build_path = /obj/item/device/electropack/shockcollar - category = list("hacked", "Security") - /datum/design/large_welding_tool name = "Industrial Welding Tool" id = "large_welding_tool" diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index e3caef247c..05acb20f0e 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -44,6 +44,8 @@ Note: Must be placed within 3 tiles of the R&D Console to_chat(user, "You add the [O.name] to the [src.name]!") flick("d_analyzer_la", src) addtimer(CALLBACK(src, .proc/finish_loading), 10) + if (linked_console) + linked_console.updateUsrDialog() /obj/machinery/rnd/destructive_analyzer/proc/finish_loading() update_icon() @@ -93,30 +95,35 @@ Note: Must be placed within 3 tiles of the R&D Console /obj/machinery/rnd/destructive_analyzer/proc/user_try_decon_id(id, mob/user) if(!istype(loaded_item) || !istype(linked_console)) return FALSE - if(id && !(id == RESEARCH_MATERIAL_RECLAMATION_ID)) + + if (id && id != RESEARCH_MATERIAL_RECLAMATION_ID) var/datum/techweb_node/TN = get_techweb_node_by_id(id) if(!istype(TN)) return FALSE - var/list/pos1 = techweb_item_boost_check(loaded_item) - if(isnull(pos1[id])) + var/list/can_boost = techweb_item_boost_check(loaded_item) + if(isnull(can_boost[id])) return FALSE var/dpath = loaded_item.type - if(isnull(TN.boost_item_paths[dpath])) + var/worth = TN.boost_item_paths[dpath] + if(isnull(worth)) return FALSE - var/dboost = TN.boost_item_paths[dpath] - var/choice = input("Are you sure you want to destroy [loaded_item.name] for a boost of [dboost? 0 : dboost] in node [TN.display_name]") in list("Proceed", "Cancel") + var/difference = min(worth, TN.research_cost) - linked_console.stored_research.boosted_nodes[TN.id] + if(worth && difference <= 0) + return FALSE + var/choice = input("Are you sure you want to destroy [loaded_item] to [!worth ? "reveal [TN.display_name]" : "boost [TN.display_name] by [difference] point\s"]?") in list("Proceed", "Cancel") if(choice == "Cancel") return FALSE if(QDELETED(loaded_item) || QDELETED(linked_console) || !user.Adjacent(linked_console) || QDELETED(src)) return FALSE - SSblackbox.record_feedback("nested_tally", "item_deconstructed", 1, list("[TN.id]", "[loaded_item.type]")) + SSblackbox.record_feedback("nested tally", "item_deconstructed", 1, list("[TN.id]", "[loaded_item.type]")) if(destroy_item(loaded_item)) linked_console.stored_research.boost_with_path(SSresearch.techweb_nodes[TN.id], dpath) + else var/point_value = techweb_item_point_check(loaded_item) if(linked_console.stored_research.deconstructed_items[loaded_item.type]) point_value = 0 - var/choice = input("Are you sure you want to destroy [loaded_item.name] for [point_value? "[point_value] points" : "material reclaimation"]?") in list("Proceed", "Cancel") + var/choice = input("Are you sure you want to destroy [loaded_item] for [point_value ? "[point_value] research points" : "material reclamation"]?") in list("Proceed", "Cancel") if(choice == "Cancel") return FALSE if(QDELETED(loaded_item) || QDELETED(linked_console) || !user.Adjacent(linked_console) || QDELETED(src)) @@ -133,4 +140,5 @@ Note: Must be placed within 3 tiles of the R&D Console return FALSE loaded_item.forceMove(get_turf(src)) loaded_item = null + update_icon() return TRUE diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index cbd0fa9f27..1dc32e6dde 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -15,8 +15,6 @@ Note: Must be placed west/left of and R&D console to function. circuit = /obj/item/circuitboard/machine/protolathe var/efficiency_coeff - var/console_link = TRUE //allow console link. - var/requires_console = TRUE var/list/categories = list( "Power Designs", "Medical Designs", @@ -31,7 +29,7 @@ Note: Must be placed west/left of and R&D console to function. "Computer Parts" ) - var/datum/component/material_container/materials + var/datum/component/material_container/materials //Store for hyper speed! /obj/machinery/rnd/protolathe/Initialize() create_reagents(0) @@ -39,6 +37,7 @@ Note: Must be placed west/left of and R&D console to function. list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), 0, FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE + RefreshParts() return ..() /obj/machinery/rnd/protolathe/RefreshParts() @@ -75,6 +74,7 @@ Note: Must be placed west/left of and R&D console to function. materials.retrieve_all() ..() + /obj/machinery/rnd/protolathe/disconnect_console() linked_console.linked_lathe = null ..() @@ -124,13 +124,11 @@ Note: Must be placed west/left of and R&D console to function. return TRUE /obj/machinery/rnd/protolathe/proc/do_print(path, amount, list/matlist, notify_admins) - if(notify_admins) - if(usr) - usr.investigate_log("built [amount] of [path] at a protolathe.", INVESTIGATE_RESEARCH) - var/turf/T = get_turf(usr) - message_admins("[key_name(usr)][ADMIN_JMP(T)] has built [amount] of [path] at a protolathe at [COORD(usr)]") + if(notify_admins && usr) + investigate_log("[key_name(usr)] built [amount] of [path] at a protolathe.", INVESTIGATE_RESEARCH) + message_admins("[ADMIN_LOOKUPFLW(usr)] has built [amount] of [path] at a protolathe") for(var/i in 1 to amount) var/obj/item/I = new path(get_turf(src)) if(!istype(I, /obj/item/stack/sheet) && !istype(I, /obj/item/ore/bluespace_crystal)) I.materials = matlist.Copy() - SSblackbox.record_feedback("nested_tally", "item_printed", amount, list("[type]", "[path]")) \ No newline at end of file + SSblackbox.record_feedback("nested tally", "item_printed", amount, list("[type]", "[path]")) diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 0c468b184a..0b9453a62d 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -45,6 +45,7 @@ doesn't have toxins access. var/disk_slot_selected var/searchstring = "" var/searchtype = "" + var/ui_mode = RDCONSOLE_UI_MODE_NORMAL var/research_control = TRUE @@ -216,13 +217,11 @@ doesn't have toxins access. /obj/machinery/computer/rdconsole/proc/ui_header() var/list/l = list() - l += "

    Nanotrasen Research and Development

    [RDSCREEN_NOBREAK]" - l += "
    Connected Technology database: [stored_research == SSresearch.science_tech? "Nanotrasen" : "Third Party"]" - l += "Available Points: [stored_research.research_points]" + l += "
    [stored_research.organization] Research and Development Network" + l += "Available points: [round(stored_research.research_points)] (+[round(stored_research.last_bitcoins * 60)] / minute)" l += "Security protocols: [emagged? "Disabled" : "Enabled"]" - l += "Design Disk: [d_disk? "Loaded" : "Not Loaded"] | \ - Technology Disk: [t_disk? "Loaded" : "Not Loaded"]" l += "Main Menu | Back
    [RDSCREEN_NOBREAK]" + l += "[ui_mode == 1? "Normal View" : "Normal View"] | [ui_mode == 2? "Expert View" : "Expert View"] | [ui_mode == 3? "List View" : "List View"]" return l /obj/machinery/computer/rdconsole/proc/ui_main_menu() @@ -234,7 +233,7 @@ doesn't have toxins access. if(t_disk) l += "
    Tech Disk" if(linked_destroy) - l += "
    Deconstructive Analyzer" + l += "
    Destructive Analyzer" if(linked_lathe) l += "
    Protolathe" if(linked_imprinter) @@ -540,122 +539,214 @@ doesn't have toxins access. RDSCREEN_UI_DECONSTRUCT_CHECK var/list/l = list() if(!linked_destroy.loaded_item) - l += "
    No Item Loaded. Standing-by...
    " + l += "
    No item loaded. Standing-by...
    " else - l += "

    Deconstruction Menu

    " - l += "Eject Item" - l += "Name: [linked_destroy.loaded_item.name]" - l += "Select a node to boost by deconstructing this item." - l += "This item is able to boost:" - var/list/listin = techweb_item_boost_check(linked_destroy.loaded_item) - for(var/node_id in listin) - var/datum/techweb_node/N = get_techweb_node_by_id(node_id) - var/worth = listin[N.id] - if(!stored_research.researched_nodes[N.id] && !stored_research.boosted_nodes[N.id]) - l += "[N.display_name]: [worth] points" - else - l += "[RDSCREEN_NOBREAK]" + l += "
    Brothers
    [icon2html(linked_destroy.loaded_item, usr)][linked_destroy.loaded_item.name] Eject
    [RDSCREEN_NOBREAK]" + l += "Select a node to boost by deconstructing this item. This item can boost:" + + var/anything = FALSE + var/list/boostable_nodes = techweb_item_boost_check(linked_destroy.loaded_item) + for(var/id in boostable_nodes) + anything = TRUE + var/worth = boostable_nodes[id] + var/datum/techweb_node/N = get_techweb_node_by_id(id) + + l += "
    [RDSCREEN_NOBREAK]" + if (stored_research.researched_nodes[N.id]) // already researched + l += "[N.display_name]" + l += "This node has already been researched." + else if (worth == 0) // reveal only + if (stored_research.hidden_nodes[N.id]) + l += "[N.display_name]" + l += "This node will be revealed." + else + l += "[N.display_name]" + l += "This node has already been revealed." + else // boost by the difference + var/difference = min(worth, N.research_cost) - stored_research.boosted_nodes[N.id] + if (difference > 0) + l += "[N.display_name]" + l += "This node will be boosted by [difference] points." + else + l += "[N.display_name]" + l += "This node has already been boosted." + l += "
    [RDSCREEN_NOBREAK]" + + // point deconstruction and material reclamation use the same ID to prevent accidentally missing the points var/point_value = techweb_item_point_check(linked_destroy.loaded_item) - if(point_value && isnull(stored_research.deconstructed_items[linked_destroy.loaded_item.type])) - l += "Generic Point Deconstruction - [point_value] points" - l += "Material Reclaimation Deconstruction" + if(point_value) + anything = TRUE + l += "
    [RDSCREEN_NOBREAK]" + if (stored_research.deconstructed_items[linked_destroy.loaded_item.type]) + l += "Point Deconstruction" + l += "This item's [point_value] point\s have already been claimed." + else + l += "Point Deconstruction" + l += "This item is worth [point_value] point\s!" + l += "
    [RDSCREEN_NOBREAK]" + + var/list/materials = linked_destroy.loaded_item.materials + if (materials.len) + l += "
    Material Reclamation" + for (var/M in materials) + l += "* [CallMaterialName(M)] x [materials[M]]" + l += "
    [RDSCREEN_NOBREAK]" + anything = TRUE + + if (!anything) + l += "Nothing!" + l += "
    " return l -/obj/machinery/computer/rdconsole/proc/ui_techweb() //Legacy code. +/obj/machinery/computer/rdconsole/proc/ui_techweb() var/list/l = list() - var/list/avail = list() //This could probably be optimized a bit later. - var/list/unavail = list() - var/list/res = list() - for(var/v in stored_research.researched_nodes) - res += stored_research.researched_nodes[v] - for(var/v in stored_research.available_nodes) - if(stored_research.researched_nodes[v]) - continue - avail += stored_research.available_nodes[v] - for(var/v in stored_research.visible_nodes) - if(stored_research.available_nodes[v]) - continue - unavail += stored_research.visible_nodes[v] - l += "

    Technology Nodes:

    [RDSCREEN_NOBREAK]" - l += "

    Available for Research:

    " - for(var/datum/techweb_node/N in avail) - var/not_unlocked = (stored_research.available_nodes[N.id] && !stored_research.researched_nodes[N.id]) - var/has_points = (stored_research.research_points >= N.get_price(stored_research)) - var/research_href = not_unlocked? (has_points? "Research" : "Not Enough Points") : null - l += "[N.display_name][research_href]" - l += "

    Locked Nodes:

    " - for(var/datum/techweb_node/N in unavail) - l += "[N.display_name]" - l += "

    Researched Nodes:

    " - for(var/datum/techweb_node/N in res) - l += "[N.display_name]" + if(ui_mode != RDCONSOLE_UI_MODE_LIST) + var/list/columns = list() + var/max_tier = 0 + for (var/node_ in stored_research.tiers) + var/datum/techweb_node/node = node_ + var/tier = stored_research.tiers[node] + LAZYINITLIST(columns["[tier]"]) // String hackery to make the numbers associative + columns["[tier]"] += ui_techweb_single_node(node, minimal=(tier != 1)) + max_tier = max(max_tier, tier) + + l += "[RDSCREEN_NOBREAK]" + for(var/tier in 0 to max_tier) + l += "[RDSCREEN_NOBREAK]" + l += "
    ResearchedAvailableFuture
    [RDSCREEN_NOBREAK]" + l += columns["[tier]"] + l += "
    [RDSCREEN_NOBREAK]" + else + var/list/avail = list() //This could probably be optimized a bit later. + var/list/unavail = list() + var/list/res = list() + for(var/v in stored_research.researched_nodes) + res += stored_research.researched_nodes[v] + for(var/v in stored_research.available_nodes) + if(stored_research.researched_nodes[v]) + continue + avail += stored_research.available_nodes[v] + for(var/v in stored_research.visible_nodes) + if(stored_research.available_nodes[v]) + continue + unavail += stored_research.visible_nodes[v] + l += "

    Technology Nodes:

    [RDSCREEN_NOBREAK]" + l += "

    Available for Research:

    " + for(var/datum/techweb_node/N in avail) + var/not_unlocked = (stored_research.available_nodes[N.id] && !stored_research.researched_nodes[N.id]) + var/has_points = (stored_research.research_points >= N.get_price(stored_research)) + var/research_href = not_unlocked? (has_points? "Research" : "Not Enough Points") : null + l += "[N.display_name][research_href]" + l += "

    Locked Nodes:

    " + for(var/datum/techweb_node/N in unavail) + l += "[N.display_name]" + l += "

    Researched Nodes:

    " + for(var/datum/techweb_node/N in res) + l += "[N.display_name]" + l += "
    [RDSCREEN_NOBREAK]" + return l + +/obj/machinery/computer/rdconsole/proc/machine_icon(atom/item) + return icon2html(initial(item.icon), usr, initial(item.icon_state), SOUTH) + +/obj/machinery/computer/rdconsole/proc/ui_techweb_single_node(datum/techweb_node/node, selflink=TRUE, minimal=FALSE) + var/list/l = list() + if (stored_research.hidden_nodes[node.id]) + return l + var/price = node.get_price(stored_research) + var/display_name = node.display_name + if (selflink) + display_name = "[display_name]" + l += "
    [display_name] [RDSCREEN_NOBREAK]" + if(minimal) + l += "
    [node.description]" + else + if(stored_research.researched_nodes[node.id]) + l += "Researched" + else if(stored_research.available_nodes[node.id]) + if(stored_research.research_points >= price) + l += "[price]" + else + l += "[price]" // gray - too expensive + else + l += "[price]" // red - missing prereqs + if(ui_mode == RDCONSOLE_UI_MODE_NORMAL) + l += "[node.description]" + for(var/i in node.designs) + var/datum/design/D = node.designs[i] + l += "[D.icon_html(usr)][RDSCREEN_NOBREAK]" l += "
    [RDSCREEN_NOBREAK]" return l -/obj/machinery/computer/rdconsole/proc/ui_techweb_nodeview() //Legacy code +/obj/machinery/computer/rdconsole/proc/ui_techweb_nodeview() RDSCREEN_UI_SNODE_CHECK var/list/l = list() if(stored_research.hidden_nodes[selected_node.id]) l += "

    ERROR: RESEARCH NODE UNKNOWN.

    " - l += "

    [selected_node.display_name]

    " - l += "Description: [selected_node.description]" - l += "Status: [stored_research.researched_nodes[selected_node.id]? "Researched" : "Locked"]" - l += "Point Cost: [selected_node.get_price(stored_research)].
    [RDSCREEN_NOBREAK]" - if(stored_research.researched_nodes[selected_node.id]) - l += "

    Already Researched

    [RDSCREEN_NOBREAK]" - else if(stored_research.available_nodes[selected_node.id]) - if(stored_research.research_points >= selected_node.get_price(stored_research)) - l += "

    Research

    [RDSCREEN_NOBREAK]" - else - l += "

    Not Enough Points

    [RDSCREEN_NOBREAK]" - else if(stored_research.visible_nodes[selected_node.id]) - l += "

    Prerequisites not met!

    [RDSCREEN_NOBREAK]" - else - l += "

    ERROR

    [RDSCREEN_NOBREAK]" - l += "

    Designs:

    [RDSCREEN_NOBREAK]" - for(var/i in selected_node.designs) - var/datum/design/D = selected_node.designs[i] - l += "[D.name]" - l += "

    Prerequisites:

    [RDSCREEN_NOBREAK]" - for(var/i in selected_node.prerequisites) - var/datum/techweb_node/prereq = selected_node.prerequisites[i] - var/sc = stored_research.researched_nodes[prereq.id] - var/begin - var/end - if(sc) - begin = "" - end = "" - else - begin = "" - end = "" - l += "[begin][prereq.display_name][end]" - l += "

    Unlocks:

    [RDSCREEN_NOBREAK]" - for(var/i in selected_node.unlocks) - var/datum/techweb_node/unlock = selected_node.unlocks[i] - l += "[unlock.display_name]" + return - l += "
    [RDSCREEN_NOBREAK]" + l += "[RDSCREEN_NOBREAK]" + if (length(selected_node.prerequisites)) + l += "[RDSCREEN_NOBREAK]" + l += "[RDSCREEN_NOBREAK]" + if (length(selected_node.unlocks)) + l += "[RDSCREEN_NOBREAK]" + + l += "[RDSCREEN_NOBREAK]" + if (length(selected_node.prerequisites)) + l += "[RDSCREEN_NOBREAK]" + l += "[RDSCREEN_NOBREAK]" + if (length(selected_node.unlocks)) + l += "[RDSCREEN_NOBREAK]" + + l += "
    RequiresCurrent NodeUnlocks
    [RDSCREEN_NOBREAK]" + for (var/i in selected_node.prerequisites) + l += ui_techweb_single_node(selected_node.prerequisites[i]) + l += "[RDSCREEN_NOBREAK]" + l += ui_techweb_single_node(selected_node, selflink=FALSE) + l += "[RDSCREEN_NOBREAK]" + for (var/i in selected_node.unlocks) + l += ui_techweb_single_node(selected_node.unlocks[i]) + l += "
    [RDSCREEN_NOBREAK]" return l /obj/machinery/computer/rdconsole/proc/ui_techweb_designview() //Legacy code RDSCREEN_UI_SDESIGN_CHECK var/list/l = list() var/datum/design/D = selected_design - l += "
    Name: [D.name]" + l += "
    [D.icon_html(usr)][D.name]
    [RDSCREEN_NOBREAK]" if(D.build_type) - l += "Lathe Types:" - if(D.build_type & IMPRINTER) l += "Circuit Imprinter" - if(D.build_type & PROTOLATHE) l += "Protolathe" - if(D.build_type & AUTOLATHE) l += "Autolathe" - if(D.build_type & MECHFAB) l += "Exosuit Fabricator" - if(D.build_type & BIOGENERATOR) l += "Biogenerator" - if(D.build_type & LIMBGROWER) l += "Limbgrower" - if(D.build_type & SMELTER) l += "Smelter" - l += "Required Materials:" + var/lathes = list() + if(D.build_type & IMPRINTER) + lathes += "[machine_icon(/obj/machinery/rnd/circuit_imprinter)][RDSCREEN_NOBREAK]" + if (linked_imprinter && D.id in stored_research.researched_designs) + l += "Imprint" + if(D.build_type & PROTOLATHE) + lathes += "[machine_icon(/obj/machinery/rnd/protolathe)][RDSCREEN_NOBREAK]" + if (linked_lathe && D.id in stored_research.researched_designs) + l += "Construct" + if(D.build_type & AUTOLATHE) + lathes += "[machine_icon(/obj/machinery/autolathe)][RDSCREEN_NOBREAK]" + if(D.build_type & MECHFAB) + lathes += "[machine_icon(/obj/machinery/mecha_part_fabricator)][RDSCREEN_NOBREAK]" + if(D.build_type & BIOGENERATOR) + lathes += "[machine_icon(/obj/machinery/biogenerator)][RDSCREEN_NOBREAK]" + if(D.build_type & LIMBGROWER) + lathes += "[machine_icon(/obj/machinery/limbgrower)][RDSCREEN_NOBREAK]" + if(D.build_type & SMELTER) + lathes += "[machine_icon(/obj/machinery/mineral/processing_unit)][RDSCREEN_NOBREAK]" + l += "Construction types:" + l += lathes + l += "" + l += "Required materials:" var/all_mats = D.materials + D.reagents_list for(var/M in all_mats) l += "* [CallMaterialName(M)] x [all_mats[M]]" + l += "Unlocked by:" + for (var/node in D.unlocked_by) + l += ui_techweb_single_node(node) l += "[RDSCREEN_NOBREAK]
    " return l @@ -721,6 +812,8 @@ doesn't have toxins access. if(ls["switch_screen"]) back = screen screen = text2num(ls["switch_screen"]) + if(ls["ui_mode"]) + ui_mode = text2num(ls["ui_mode"]) if(ls["lock_console"]) if(allowed(usr)) lock_console(usr) @@ -873,7 +966,8 @@ doesn't have toxins access. /obj/machinery/computer/rdconsole/interact(mob/user) user.set_machine(src) - var/datum/browser/popup = new(user, "rndconsole", name, 460, 550) + var/datum/browser/popup = new(user, "rndconsole", name, 900, 600) + popup.add_stylesheet("techwebs", 'html/browser/techwebs.css') popup.set_content(generate_ui()) popup.open() diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index 663d3fc806..eea79f77e6 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -1,5 +1,4 @@ - //All devices that link into the R&D console fall into thise type for easy identification and some shared procs. @@ -11,12 +10,14 @@ use_power = IDLE_POWER_USE var/busy = FALSE var/hacked = FALSE + var/console_link = TRUE //allow console link. + var/requires_console = TRUE var/disabled = FALSE var/shocked = FALSE var/obj/machinery/computer/rdconsole/linked_console var/obj/item/loaded_item = null //the item loaded inside the machine (currently only used by experimentor and destructive analyzer) var/allowed_department_flags = ALL - + /obj/machinery/rnd/proc/reset_busy() busy = FALSE @@ -79,28 +80,26 @@ /obj/machinery/rnd/proc/is_insertion_ready(mob/user) if(panel_open) to_chat(user, "You can't load [src] while it's opened!") - return - if (disabled) - return - if (!linked_console) // Try to auto-connect to new RnD consoles nearby. - if(!linked_console) - to_chat(user, "[src] must be linked to an R&D console first!") - return - if (busy) + return FALSE + if(disabled) + return FALSE + if(requires_console && !linked_console) + to_chat(user, "[src] must be linked to an R&D console first!") + return FALSE + if(busy) to_chat(user, "[src] is busy right now.") - return + return FALSE if(stat & BROKEN) to_chat(user, "[src] is broken.") - return + return FALSE if(stat & NOPOWER) to_chat(user, "[src] has no power.") - return + return FALSE if(loaded_item) to_chat(user, "[src] is already loaded.") - return + return FALSE return TRUE - //we eject the loaded item when deconstructing the machine /obj/machinery/rnd/on_deconstruction() if(loaded_item) diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm index af1dc853d8..0e2e788b8f 100644 --- a/code/modules/research/stock_parts.dm +++ b/code/modules/research/stock_parts.dm @@ -82,7 +82,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi //Rating 1 - /obj/item/stock_parts/capacitor name = "capacitor" desc = "A basic capacitor used in the construction of a variety of devices." diff --git a/code/modules/research/techweb/__techweb_helpers.dm b/code/modules/research/techweb/__techweb_helpers.dm index adfa5c78d0..af4fe7480b 100644 --- a/code/modules/research/techweb/__techweb_helpers.dm +++ b/code/modules/research/techweb/__techweb_helpers.dm @@ -130,6 +130,9 @@ CHECK_TICK /proc/calculate_techweb_nodes() + for(var/design_id in SSresearch.techweb_designs) + var/datum/design/D = SSresearch.techweb_designs[design_id] + D.unlocked_by.Cut() for(var/node_id in SSresearch.techweb_nodes) var/datum/techweb_node/node = SSresearch.techweb_nodes[node_id] node.prerequisites = list() @@ -138,7 +141,9 @@ for(var/i in node.prereq_ids) node.prerequisites[i] = SSresearch.techweb_nodes[i] for(var/i in node.design_ids) - node.designs[i] = SSresearch.techweb_designs[i] + var/datum/design/D = SSresearch.techweb_designs[i] + node.designs[i] = D + D.unlocked_by += node if(node.hidden) SSresearch.techweb_nodes_hidden[node.id] = node CHECK_TICK diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index 74ace7e4c2..d59dea55d3 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -17,6 +17,9 @@ var/id = "generic" var/list/research_logs = list() //IC logs. var/max_bomb_value = 0 + var/organization = "Third-Party" //Organization name, used for display. + var/last_bitcoins = 0 //Current per-second production, used for display only. + var/list/tiers = list() //Assoc list, datum = number, 1 is available, 2 is all reqs are 1, so on /datum/techweb/New() for(var/i in SSresearch.techweb_nodes_starting) @@ -28,6 +31,7 @@ /datum/techweb/admin research_points = INFINITY //KEKKLES. id = "ADMIN" + organization = "CentCom" /datum/techweb/admin/New() //All unlocked. . = ..() @@ -38,6 +42,7 @@ /datum/techweb/science //Global science techweb for RND consoles. id = "SCIENCE" + organization = "Nanotrasen" /datum/techweb/Destroy() researched_nodes = null @@ -148,15 +153,31 @@ recalculate_nodes(TRUE) //Fully rebuild the tree. /datum/techweb/proc/boost_with_path(datum/techweb_node/N, itempath) - if(!istype(N)||!ispath(itempath)) + if(!istype(N) || !ispath(itempath)) return FALSE - var/boost = N.boost_item_paths[itempath] - if(!boosted_nodes[N]) - boosted_nodes[N] = boost - if(N.autounlock_by_boost) - hidden_nodes -= N.id + boosted_nodes[N] = max(boosted_nodes[N], N.boost_item_paths[itempath]) + if(N.autounlock_by_boost) + hidden_nodes -= N.id return TRUE +/datum/techweb/proc/update_tiers(datum/techweb_node/base) + var/list/current = list(base) + while (current.len) + var/list/next = list() + for (var/node_ in current) + var/datum/techweb_node/node = node_ + var/tier = 0 + if (!researched_nodes[node.id]) // researched is tier 0 + for (var/id in node.prereq_ids) + var/prereq_tier = tiers[node.prerequisites[id]] + tier = max(tier, prereq_tier + 1) + + if (tier != tiers[node]) + tiers[node] = tier + for (var/id in node.unlocks) + next += node.unlocks[id] + current = next + /datum/techweb/proc/update_node_status(datum/techweb_node/node, autoupdate_consoles = TRUE) var/researched = FALSE var/available = FALSE @@ -185,6 +206,7 @@ else if(visible) visible_nodes[node.id] = node + update_tiers(node) if(autoupdate_consoles) for(var/v in consoles_accessing) var/obj/machinery/computer/rdconsole/V = v diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm index 75faf07bf1..3ec6c4cf9d 100644 --- a/code/modules/research/techweb/_techweb_node.dm +++ b/code/modules/research/techweb/_techweb_node.dm @@ -23,8 +23,6 @@ actual_cost = research_cost /datum/techweb_node/proc/get_price(datum/techweb/host) - if(!host) - return actual_cost - var/discount = boost_item_paths[host.boosted_nodes[src]] - actual_cost = research_cost - discount + if(host) + actual_cost = research_cost - host.boosted_nodes[src] return actual_cost diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 96b252854b..ba43a1c24b 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -1,6 +1,6 @@ //Current rate: 132500 research points in 90 minutes -//Current cargo price: 250000 points for fullmaxed R&D. +//Current cargo price: 280000 points for fullmaxed R&D. //Base Node /datum/techweb_node/base @@ -9,7 +9,7 @@ display_name = "Basic Research Technology" description = "NT default research technologies." design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", - "destructive_analyzer", "protolathe", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", + "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", "space_heater") //Default research tech, prevents bricking /////////////////////////Biotech///////////////////////// @@ -18,7 +18,7 @@ display_name = "Biological Technology" description = "What makes us tick." //the MC, silly! prereq_ids = list("base") - design_ids = list("mass_spectrometer", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "pandemic") + design_ids = list("chem_heater", "chem_master", "chem_dispenser", "sleeper", "pandemic") research_cost = 2500 export_price = 10000 @@ -27,7 +27,16 @@ display_name = "Advanced Biotechnology" description = "Advanced Biotechnology" prereq_ids = list("biotech") - design_ids = list("piercesyringe", "adv_mass_spectrometer", "plasmarefiller", "limbgrower") + design_ids = list("piercesyringe", "plasmarefiller", "limbgrower") + research_cost = 2500 + export_price = 10000 + +/datum/techweb_node/bio_process + id = "bio_process" + display_name = "Biological Processing" + description = "From slimes to kitchens." + prereq_ids = list("biotech") + design_ids = list("smartfridge", "gibber", "deepfryer", "monkey_recycler", "processor", "gibber", "microwave") research_cost = 2500 export_price = 10000 @@ -52,8 +61,8 @@ /////////////////////////engineering tech///////////////////////// /datum/techweb_node/engineering id = "engineering" - description = "Modern Engineering Technology." display_name = "Industrial Engineering" + description = "A refresher course on modern engineering technology." prereq_ids = list("base") design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin", "atmosalerts", "atmos_control", "recycler", "autolathe", "high_micro_laser", "nano_mani", "weldingmask", "mesons", "thermomachine", "tesla_coil", "grounding_rod", "apc_control") @@ -62,13 +71,31 @@ /datum/techweb_node/adv_engi id = "adv_engi" - description = "Advanced Engineering research" display_name = "Advanced Engineering" + description = "Pushing the boundaries of physics, one chainsaw-fist at a time." prereq_ids = list("engineering", "emp_basic") design_ids = list("engine_goggles", "diagnostic_hud", "magboots") research_cost = 2500 export_price = 10000 +/datum/techweb_node/high_efficiency + id = "high_efficiency" + display_name = "High Efficiency Parts" + description = "Finely-tooled manufacturing techniques allowing for picometer-perfect precision levels." + prereq_ids = list("engineering", "datatheory") + design_ids = list("pico_mani", "super_matter_bin") + research_cost = 2500 + export_price = 10000 + +/datum/techweb_node/adv_power + id = "adv_power" + display_name = "Advanced Power Manipulation" + description = "How to get more zap." + prereq_ids = list("engineering") + design_ids = list("smes", "super_cell", "hyper_cell", "super_capacitor", "superpacman", "mrspacman", "power_turbine", "power_turbine_console", "power_compressor") + research_cost = 2500 + export_price = 10000 + /////////////////////////Bluespace tech///////////////////////// /datum/techweb_node/bluespace_basic //Bluespace-memery id = "bluespace_basic" @@ -89,6 +116,26 @@ research_cost = 2500 export_price = 10000 +/datum/techweb_node/practical_bluespace + id = "practical_bluespace" + display_name = "Applied Bluespace Research" + description = "Using bluespace to make things faster and better." + prereq_ids = list("bluespace_basic", "engineering") + design_ids = list("bs_rped","minerbag_holding", "telesci_gps", "bluespacebeaker", "bluespacesyringe", "bluespacebodybag", "phasic_scanning") + research_cost = 2500 + export_price = 10000 + + +/datum/techweb_node/bluespace_power + id = "bluespace_power" + display_name = "Bluespace Power Technology" + description = "Even more powerful.. power!" + prereq_ids = list("adv_power", "adv_bluespace") + design_ids = list("bluespace_cell", "quadratic_capacitor") + research_cost = 2500 + export_price = 10000 + + /////////////////////////plasma tech///////////////////////// /datum/techweb_node/basic_plasma id = "basic_plasma" @@ -127,112 +174,6 @@ research_cost = 2500 export_price = 10000 -/////////////////////////EMP tech///////////////////////// -/datum/techweb_node/emp_basic //EMP tech for some reason - id = "emp_basic" - display_name = "Electromagnetic Theory" - description = "Study into usage of frequencies in the electromagnetic spectrum." - prereq_ids = list("base") - design_ids = list("holosign", "inducer", "tray_goggles", "holopad") - research_cost = 2500 - export_price = 10000 - -/datum/techweb_node/emp_adv - id = "emp_adv" - display_name = "Advanced Electromagnetic Theory" - prereq_ids = list("emp_basic") - design_ids = list("ultra_micro_laser") - research_cost = 2500 - export_price = 10000 - -/datum/techweb_node/emp_super - id = "emp_super" - display_name = "Quantum Electromagnetic Technology" //bs - description = "Even better electromagnetic technology" - prereq_ids = list("emp_adv") - design_ids = list("quadultra_micro_laser") - research_cost = 2500 - export_price = 10000 - -/////////////////////////Clown tech///////////////////////// -/datum/techweb_node/clown - id = "clown" - display_name = "Clown Technology" - description = "Honk?!" - prereq_ids = list("base") - design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm", - "honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone") - research_cost = 2500 - export_price = 10000 - -////////////////////////Computer tech//////////////////////// -/datum/techweb_node/comptech - id = "comptech" - display_name = "Computer Consoles" - description = "Computers and how they work." - prereq_ids = list("datatheory") - design_ids = list("cargo", "cargorequest", "stockexchange", "libraryconsole", "aifixer", "mining", "crewconsole", "comconsole", "idcardconsole", "operating", "seccamera") - research_cost = 2500 - export_price = 10000 - -/datum/techweb_node/computer_hardware_basic //Modular computers are shitty and nearly useless so until someone makes them actually useful this can be easy to get. - id = "computer_hardware_basic" - display_name = "Computer Hardware" - description = "How computer hardware are made." - prereq_ids = list("comptech") - research_cost = 2500 - export_price = 10000 - design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired", - "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced", - "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small") - -/datum/techweb_node/computer_board_gaming - id = "computer_board_gaming" - display_name = "Arcade Games" - description = "For the slackers on the station." - prereq_ids = list("comptech") - design_ids = list("arcade_battle", "arcade_orion", "slotmachine") - research_cost = 2500 - export_price = 10000 - -/datum/techweb_node/comp_recordkeeping - id = "comp_recordkeeping" - display_name = "Computerized Recordkeeping" - description = "Organized record databases and how they're used." - prereq_ids = list("comptech") - design_ids = list("secdata", "med_data", "prisonmanage", "vendor", "automated_announcement") - research_cost = 2500 - export_price = 10000 - -/datum/techweb_node/telecomms - id = "telecomms" - display_name = "Telecommunications Technology" - description = "Subspace transmission technology for near-instant communications devices." - prereq_ids = list("comptech", "bluespace_basic") - research_cost = 2500 - export_price = 10000 - design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server", - "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter") - -/datum/techweb_node/integrated_HUDs - id = "integrated_HUDs" - display_name = "Integrated HUDs" - description = "The usefulness of computerized records, projected straight onto your eyepiece!" - prereq_ids = list("comp_recordkeeping", "emp_basic") - design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles") - research_cost = 2500 - export_price = 10000 - -/datum/techweb_node/NVGtech - id = "NVGtech" - display_name = "Night Vision Technology" - description = "Allows seeing in the dark without actual light!" - prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv") - design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons") - research_cost = 2500 - export_price = 10000 - -////////////////////////AI & Cyborg tech//////////////////////// /datum/techweb_node/neural_programming id = "neural_programming" display_name = "Neural Programming" @@ -281,7 +222,7 @@ /datum/techweb_node/cyborg_upg_med id = "cyborg_upg_med" display_name = "Cyborg Upgrades: Medical" - description = "Medical upgrades for cyborgs" + description = "Medical upgrades for cyborgs." prereq_ids = list("adv_biotech", "cyborg") design_ids = list("borg_upgrade_defibrillator", "borg_upgrade_piercinghypospray", "borg_upgrade_highstrengthsynthesiser", "borg_upgrade_expandedsynthesiser") research_cost = 2500 @@ -291,7 +232,7 @@ id = "cyborg_upg_combat" display_name = "Cyborg Upgrades: Combat" description = "Military grade upgrades for cyborgs." - prereq_ids = list("adv_robotics", "adv_engi") + prereq_ids = list("adv_robotics", "adv_engi" , "weaponry") design_ids = list("borg_upgrade_vtec", "borg_upgrade_disablercooler") research_cost = 2500 export_price = 10000 @@ -307,6 +248,112 @@ research_cost = 2500 export_price = 10000 +/////////////////////////EMP tech///////////////////////// +/datum/techweb_node/emp_basic //EMP tech for some reason + id = "emp_basic" + display_name = "Electromagnetic Theory" + description = "Study into usage of frequencies in the electromagnetic spectrum." + prereq_ids = list("base") + design_ids = list("holosign", "inducer", "tray_goggles", "holopad") + research_cost = 2500 + export_price = 10000 + +/datum/techweb_node/emp_adv + id = "emp_adv" + display_name = "Advanced Electromagnetic Theory" + description = "Determining whether reversing the polarity will actually help in a given situation." + prereq_ids = list("emp_basic") + design_ids = list("ultra_micro_laser") + research_cost = 2500 + export_price = 10000 + +/datum/techweb_node/emp_super + id = "emp_super" + display_name = "Quantum Electromagnetic Technology" //bs + description = "Even better electromagnetic technology." + prereq_ids = list("emp_adv") + design_ids = list("quadultra_micro_laser") + research_cost = 2500 + export_price = 10000 + +/////////////////////////Clown tech///////////////////////// +/datum/techweb_node/clown + id = "clown" + display_name = "Clown Technology" + description = "Honk?!" + prereq_ids = list("base") + design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm", + "honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone") + research_cost = 2500 + export_price = 10000 + +////////////////////////Computer tech//////////////////////// +/datum/techweb_node/comptech + id = "comptech" + display_name = "Computer Consoles" + description = "Computers and how they work." + prereq_ids = list("datatheory") + design_ids = list("cargo", "cargorequest", "stockexchange", "libraryconsole", "aifixer", "mining", "crewconsole", "comconsole", "idcardconsole", "operating", "seccamera") + research_cost = 2500 + export_price = 10000 + +/datum/techweb_node/computer_hardware_basic //Modular computers are shitty and nearly useless so until someone makes them actually useful this can be easy to get. + id = "computer_hardware_basic" + display_name = "Computer Hardware" + description = "How computer hardware are made." + prereq_ids = list("comptech") + research_cost = 2500 + export_price = 10000 + design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired", + "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced", + "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small") + +/datum/techweb_node/computer_board_gaming + id = "computer_board_gaming" + display_name = "Arcade Games" + description = "For the slackers on the station." + prereq_ids = list("comptech") + design_ids = list("arcade_battle", "arcade_orion", "slotmachine") + research_cost = 1000 + export_price = 10000 + +/datum/techweb_node/comp_recordkeeping + id = "comp_recordkeeping" + display_name = "Computerized Recordkeeping" + description = "Organized record databases and how they're used." + prereq_ids = list("comptech") + design_ids = list("secdata", "med_data", "prisonmanage", "vendor", "automated_announcement") + research_cost = 2500 + export_price = 10000 + +/datum/techweb_node/telecomms + id = "telecomms" + display_name = "Telecommunications Technology" + description = "Subspace transmission technology for near-instant communications devices." + prereq_ids = list("comptech", "bluespace_basic") + research_cost = 2500 + export_price = 10000 + design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server", + "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter") + +/datum/techweb_node/integrated_HUDs + id = "integrated_HUDs" + display_name = "Integrated HUDs" + description = "The usefulness of computerized records, projected straight onto your eyepiece!" + prereq_ids = list("comp_recordkeeping", "emp_basic") + design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles") + research_cost = 2500 + export_price = 10000 + +/datum/techweb_node/NVGtech + id = "NVGtech" + display_name = "Night Vision Technology" + description = "Allows seeing in the dark without actual light!" + prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv") + design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons") + research_cost = 2500 + export_price = 10000 + ////////////////////////Medical//////////////////////// /datum/techweb_node/cloning id = "cloning" @@ -323,7 +370,7 @@ description = "Smart freezing of objects to preserve them!" prereq_ids = list("adv_engi", "emp_basic", "biotech") design_ids = list("splitbeaker", "noreactsyringe", "cryotube", "cryo_Grenade") - research_cost = 2500 + research_cost = 2000 export_price = 10000 /datum/techweb_node/subdermal_implants @@ -357,7 +404,7 @@ id = "adv_cyber_implants" display_name = "Advanced Cybernetic Implants" description = "Upgraded and more powerful cybernetic implants." - prereq_ids = list("neural_programming", "cyber_implants") + prereq_ids = list("neural_programming", "cyber_implants","integrated_HUDs") design_ids = list("ci-toolset", "ci-surgery", "ci-reviver") research_cost = 2500 export_price = 10000 @@ -366,40 +413,11 @@ id = "combat_cyber_implants" display_name = "Combat Cybernetic Implants" description = "Military grade combat implants to improve performance." - prereq_ids = list("adv_cyber_implants") //Needs way more reqs. + prereq_ids = list("adv_cyber_implants","weaponry","NVGtech","high_efficiency") design_ids = list("ci-xray", "ci-thermals", "ci-antidrop", "ci-antistun", "ci-thrusters") research_cost = 2500 export_price = 10000 -////////////////////////generic biotech//////////////////////// -/datum/techweb_node/bio_process - id = "bio_process" - display_name = "Biological Processing" - description = "From slimes to kitchens." - prereq_ids = list("biotech") - design_ids = list("smartfridge", "gibber", "deepfryer", "monkey_recycler", "processor", "gibber", "microwave") - research_cost = 2500 - export_price = 10000 - -////////////////////////generic engineering//////////////////////// -/datum/techweb_node/high_efficiency - id = "high_efficiency" - display_name = "High Efficiency Parts" - description = "High Efficiency Parts" - prereq_ids = list("engineering", "datatheory") - design_ids = list("pico_mani", "super_matter_bin") - research_cost = 2500 - export_price = 10000 - -/datum/techweb_node/adv_power - id = "adv_power" - display_name = "Advanced Power Manipulation" - description = "How to get more zap." - prereq_ids = list("engineering") - design_ids = list("smes", "super_cell", "hyper_cell", "super_capacitor", "superpacman", "mrspacman", "power_turbine", "power_turbine_console", "power_compressor") - research_cost = 2500 - export_price = 10000 - ////////////////////////Tools//////////////////////// /datum/techweb_node/basic_mining id = "basic_mining" @@ -419,15 +437,6 @@ research_cost = 2500 export_price = 10000 -/datum/techweb_node/practical_bluespace - id = "practical_bluespace" - display_name = "Applied Bluespace Research" - description = "Using bluespace to make things faster and better." - prereq_ids = list("bluespace_basic", "engineering") - design_ids = list("bs_rped","minerbag_holding", "telesci_gps", "bluespacebeaker", "bluespacesyringe", "bluespacebodybag", "phasic_scanning") - research_cost = 2500 - export_price = 10000 - /datum/techweb_node/janitor id = "janitor" display_name = "Advanced Sanitation Technology" @@ -455,22 +464,13 @@ research_cost = 2500 export_price = 10000 -/datum/techweb_node/exp_equipment - id = "exp_equipment" +/datum/techweb_node/exp_flight + id = "exp_flight" display_name = "Experimental Flight Equipment" description = "Highly advanced construction tools." design_ids = list("flightshoes", "flightpack", "flightsuit") - prereq_ids = list("adv_engi") - research_cost = 2500 - export_price = 10000 - -/datum/techweb_node/bluespace_power - id = "bluespace_power" - display_name = "Bluespace Power Technology" - description = "Even more powerful.. power!" - prereq_ids = list("adv_power", "adv_bluespace") - design_ids = list("bluespace_cell", "quadratic_capacitor") - research_cost = 2500 + prereq_ids = list("adv_engi","integrated_HUDs", "adv_power" , "high_efficiency") + research_cost = 5000 export_price = 10000 /////////////////////////weaponry tech///////////////////////// @@ -496,7 +496,7 @@ id = "electronic_weapons" display_name = "Electric Weapons" description = "Weapons using electric technology" - prereq_ids = list("weaponry", "adv_power") + prereq_ids = list("weaponry", "adv_power" , "emp_basic") design_ids = list("stunrevolver", "stunshell", "tele_shield") research_cost = 2500 export_price = 10000 @@ -506,7 +506,7 @@ display_name = "Radioactive Weaponry" description = "Weapons using radioactive technology." prereq_ids = list("adv_engi", "adv_weaponry") - design_ids = list("nuclear_gun", "decloner") + design_ids = list("nuclear_gun") research_cost = 2500 export_price = 10000 @@ -586,8 +586,8 @@ /datum/techweb_node/adv_mecha id = "adv_mecha" - display_name = "Mechanical Exosuits" - description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human." + display_name = "Advanced Exosuits" + description = "For when you just aren't Gundam enough." prereq_ids = list("adv_robotics", "mecha") design_ids = list("mech_repair_droid") research_cost = 2500 @@ -627,7 +627,7 @@ id = "mecha_phazon" display_name = "EXOSUIT: Phazon" description = "Phazon exosuit designs" - prereq_ids = list("adv_mecha", "weaponry") + prereq_ids = list("adv_mecha", "weaponry" , "adv_bluespace") design_ids = list("phazon_chassis", "phazon_torso", "phazon_head", "phazon_left_arm", "phazon_right_arm", "phazon_left_leg", "phazon_right_leg", "phazon_main", "phazon_peri", "phazon_targ", "phazon_armor") research_cost = 2500 @@ -637,7 +637,7 @@ id = "mech_tools" display_name = "Basic Exosuit Equipment" description = "Various tools fit for basic mech units" - prereq_ids = list("mecha", "engineering") + prereq_ids = list("mecha") design_ids = list("mech_drill", "mech_mscanner", "mech_extinguisher", "mech_cable_layer") research_cost = 2500 export_price = 10000 @@ -646,7 +646,7 @@ id = "adv_mecha_tools" display_name = "Advanced Exosuit Equipment" description = "Tools for high level mech suits" - prereq_ids = list("adv_mecha", "mech_tools", "adv_engi") + prereq_ids = list("adv_mecha", "mech_tools") design_ids = list("mech_rcd") research_cost = 2500 export_price = 10000 @@ -662,9 +662,9 @@ /datum/techweb_node/mech_modules id = "adv_mecha_modules" - display_name = "Basic Exosuit Modules" + display_name = "Simple Exosuit Modules" description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_mecha", "adv_power") + prereq_ids = list("adv_mecha", "bluespace_power") design_ids = list("mech_energy_relay", "mech_ccw_armor", "mech_proj_armor", "mech_generator_nuclear") research_cost = 2500 export_price = 10000 @@ -779,7 +779,7 @@ /datum/techweb_node/mech_lmg id = "mech_lmg" - display_name = "Exosuit Weapon (PBT \"Pacifier\" Mounted Taser)" + display_name = "Exosuit Weapon (\"Ultra AC 2\" LMG)" description = "An advanced piece of mech weaponry" prereq_ids = list("adv_mecha", "adv_weaponry", "ballistic_weapons") design_ids = list("mech_lmg") @@ -800,12 +800,12 @@ id = "alientech" display_name = "Alien Technology" description = "Things used by the greys." - prereq_ids = list("base") + prereq_ids = list("biotech","engineering") boost_item_paths = list(/obj/item/gun/energy/alien = 0, /obj/item/scalpel/alien = 0, /obj/item/hemostat/alien = 0, /obj/item/retractor/alien = 0, /obj/item/circular_saw/alien = 0, /obj/item/cautery/alien = 0, /obj/item/surgicaldrill/alien = 0, /obj/item/screwdriver/abductor = 0, /obj/item/wrench/abductor = 0, /obj/item/crowbar/abductor = 0, /obj/item/device/multitool/abductor = 0, /obj/item/weldingtool/abductor = 0, /obj/item/wirecutters/abductor = 0, /obj/item/circuitboard/machine/abductor = 0, /obj/item/abductor_baton = 0, /obj/item/device/abductor = 0) - research_cost = 2500 - export_price = 10000 + research_cost = 5000 + export_price = 20000 hidden = TRUE design_ids = list("alienalloy") @@ -813,13 +813,13 @@ id = "alien_bio" display_name = "Alien Biological Tools" description = "Advanced biological tools." - prereq_ids = list("alientech", "biotech") + prereq_ids = list("alientech", "adv_biotech") design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery") boost_item_paths = list(/obj/item/gun/energy/alien = 0, /obj/item/scalpel/alien = 0, /obj/item/hemostat/alien = 0, /obj/item/retractor/alien = 0, /obj/item/circular_saw/alien = 0, /obj/item/cautery/alien = 0, /obj/item/surgicaldrill/alien = 0, /obj/item/screwdriver/abductor = 0, /obj/item/wrench/abductor = 0, /obj/item/crowbar/abductor = 0, /obj/item/device/multitool/abductor = 0, /obj/item/weldingtool/abductor = 0, /obj/item/wirecutters/abductor = 0, /obj/item/circuitboard/machine/abductor = 0, /obj/item/abductor_baton = 0, /obj/item/device/abductor = 0) research_cost = 2500 - export_price = 10000 + export_price = 20000 hidden = TRUE /datum/techweb_node/alien_engi @@ -831,9 +831,38 @@ /obj/item/weldingtool/abductor = 0, /obj/item/wirecutters/abductor = 0, /obj/item/circuitboard/machine/abductor = 0, /obj/item/abductor_baton = 0, /obj/item/device/abductor = 0) design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool") research_cost = 2500 + export_price = 20000 + hidden = TRUE + +/datum/techweb_node/syndicate_basic + id = "syndicate_basic" + display_name = "Illegal Technology" + description = "Dangerous research used to create dangerous objects." + prereq_ids = list("adv_engi", "adv_weaponry", "explosive_weapons") + design_ids = list("decloner", "borg_syndicate_module", "suppressor", "largecrossbow") + research_cost = 10000 export_price = 10000 hidden = TRUE +/datum/techweb_node/syndicate_basic/New() //Crappy way of making syndicate gear decon supported until there's another way. + . = ..() + boost_item_paths = list() + for(var/cat in GLOB.uplink_items) + var/list/l = cat + for(var/i in l) + var/datum/uplink_item/UI = i + boost_item_paths[UI.item] = 0 //allows deconning to unlock. + +//HELPERS +/proc/total_techweb_exports() + var/list/datum/techweb_node/processing = list() + for(var/i in subtypesof(/datum/techweb_node)) + processing += new i + . = 0 + for(var/i in processing) + var/datum/techweb_node/TN = i + . += TN.export_price + /proc/total_techweb_points() var/list/datum/techweb_node/processing = list() for(var/i in subtypesof(/datum/techweb_node)) @@ -842,19 +871,3 @@ for(var/i in processing) var/datum/techweb_node/TN = i . += TN.research_cost - -/* -/datum/design/borg_syndicate_module - name = "Cyborg Upgrade (Illegal Modules)" - id = "borg_syndicate_module" - construction_time = 120 - -/datum/design/suppressor - name = "Universal Suppressor" - id = "suppressor" - -/datum/design/largecrossbow - name = "Energy Crossbow" - id = "largecrossbow" - build_path = /obj/item/gun/energy/kinetic_accelerator/crossbow/large -*/ \ No newline at end of file diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 061bb0bdda..8e2ce4b7a0 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -472,7 +472,7 @@ desc = "A golem's head." resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF flags_1 = ABSTRACT_1 | NODROP_1 - + /obj/item/stack/tile/bluespace name = "bluespace floor tile" singular_name = "floor tile" diff --git a/html/browser/techwebs.css b/html/browser/techwebs.css new file mode 100644 index 0000000000..889196cc28 --- /dev/null +++ b/html/browser/techwebs.css @@ -0,0 +1,20 @@ +[data-tooltip] { + position: relative; +} + +[data-tooltip]:hover::before { + position: absolute; + z-index: 1; + top: 100%; + padding: 0 4px; + margin-top: 1px; + border: 1px solid #40628a; + background: black; + color: white; + content: attr(data-tooltip); + min-width: 160px; +} + +.technode { + width: 256px; +} diff --git a/tgstation.dme b/tgstation.dme index 139d4d00e3..aadf2bf1b8 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -346,9 +346,9 @@ #include "code\datums\components\caltrop.dm" #include "code\datums\components\chasm.dm" #include "code\datums\components\decal.dm" -#include "code\datums\components\knockoff.dm" #include "code\datums\components\infective.dm" #include "code\datums\components\jousting.dm" +#include "code\datums\components\knockoff.dm" #include "code\datums\components\material_container.dm" #include "code\datums\components\ntnet_interface.dm" #include "code\datums\components\paintable.dm" From 3af83a898ddb48dd8501bfbb9310e36c99f803b5 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Fri, 22 Dec 2017 13:41:26 -0600 Subject: [PATCH 92/96] cl --- html/changelogs/AutoChangeLog-pr-3639.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3731.yml | 5 ----- html/changelogs/AutoChangeLog-pr-3747.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3818.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3858.yml | 8 -------- html/changelogs/AutoChangeLog-pr-3864.yml | 5 ----- html/changelogs/AutoChangeLog-pr-3871.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3879.yml | 8 -------- html/changelogs/AutoChangeLog-pr-3881.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3884.yml | 5 ----- html/changelogs/AutoChangeLog-pr-3886.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3887.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3889.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3892.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3900.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3901.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3908.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3912.yml | 9 --------- html/changelogs/AutoChangeLog-pr-3913.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3916.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3919.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3920.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3951.yml | 6 ------ html/changelogs/AutoChangeLog-pr-3959.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3960.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3961.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3964.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3966.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3967.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3968.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3969.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3975.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3976.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3977.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3978.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3979.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3980.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3981.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3983.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3988.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3992.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3993.yml | 5 ----- html/changelogs/AutoChangeLog-pr-3994.yml | 5 ----- html/changelogs/AutoChangeLog-pr-3995.yml | 20 -------------------- html/changelogs/AutoChangeLog-pr-4000.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4001.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4005.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4008.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4010.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4012.yml | 6 ------ html/changelogs/AutoChangeLog-pr-4013.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4014.yml | 8 -------- html/changelogs/AutoChangeLog-pr-4022.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4026.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4027.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4028.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4030.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4031.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4032.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4033.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4034.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4036.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4038.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4043.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4049.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4050.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4051.yml | 8 -------- html/changelogs/AutoChangeLog-pr-4052.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4053.yml | 6 ------ html/changelogs/AutoChangeLog-pr-4055.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4059.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4060.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4064.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4066.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4067.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4069.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4072.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4075.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4076.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4077.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4080.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4084.yml | 8 -------- html/changelogs/AutoChangeLog-pr-4095.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4099.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4100.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4105.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4106.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4110.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4111.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4112.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4116.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4117.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4121.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4124.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4125.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4126.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4127.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4129.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4133.yml | 14 -------------- html/changelogs/AutoChangeLog-pr-4136.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4143.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4144.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4145.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4149.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4150.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4152.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4155.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4162.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4170.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4171.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4172.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4175.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4176.yml | 8 -------- html/changelogs/AutoChangeLog-pr-4177.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4180.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4182.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4184.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4186.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4191.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4196.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4198.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4200.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4201.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4207.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4209.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4215.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4216.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4218.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4220.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4234.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4235.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4240.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4241.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4243.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4244.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4246.yml | 16 ---------------- html/changelogs/AutoChangeLog-pr-4250.yml | 16 ---------------- html/changelogs/AutoChangeLog-pr-4254.yml | 6 ------ html/changelogs/AutoChangeLog-pr-4259.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4260.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4261.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4264.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4266.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4267.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4270.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4272.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4274.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4279.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4283.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4286.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4287.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4289.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4290.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4292.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4296.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4305.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4306.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4308.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4312.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4313.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4314.yml | 7 ------- html/changelogs/AutoChangeLog-pr-4315.yml | 10 ---------- html/changelogs/AutoChangeLog-pr-4319.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4331.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4338.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4339.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4340.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4341.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4344.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4346.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4349.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4350.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4351.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4353.yml | 7 ------- html/changelogs/AutoChangeLog-pr-4354.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4359.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4361.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4363.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4365.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4372.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4375.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4377.yml | 7 ------- html/changelogs/AutoChangeLog-pr-4378.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4382.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4383.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4384.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4389.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4390.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4394.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4412.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4416.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4417.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4420.yml | 10 ---------- html/changelogs/AutoChangeLog-pr-4433.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4437.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4442.yml | 8 -------- html/changelogs/AutoChangeLog-pr-4445.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4446.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4453.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4458.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4464.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4466.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4467.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4475.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4477.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4479.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4487.yml | 4 ---- html/changelogs/AutoChangeLog-pr-4488.yml | 5 ----- html/changelogs/AutoChangeLog-pr-4490.yml | 5 ----- 209 files changed, 981 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-3639.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3731.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3747.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3818.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3858.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3864.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3871.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3879.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3881.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3884.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3886.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3887.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3889.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3892.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3900.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3901.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3908.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3912.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3913.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3916.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3919.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3920.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3951.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3959.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3960.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3961.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3964.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3966.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3967.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3968.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3969.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3975.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3976.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3977.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3978.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3979.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3980.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3981.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3983.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3988.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3992.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3993.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3994.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3995.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4000.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4001.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4005.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4008.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4010.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4012.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4013.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4014.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4022.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4026.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4027.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4028.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4030.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4031.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4032.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4033.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4034.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4036.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4038.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4043.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4049.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4050.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4051.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4052.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4053.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4055.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4059.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4060.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4064.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4066.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4067.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4069.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4072.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4075.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4076.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4077.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4080.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4084.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4095.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4099.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4100.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4105.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4106.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4110.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4111.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4112.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4116.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4117.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4121.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4124.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4125.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4126.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4127.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4129.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4133.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4136.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4143.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4144.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4145.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4149.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4150.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4152.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4155.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4162.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4170.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4171.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4172.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4175.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4176.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4177.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4180.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4182.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4184.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4186.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4191.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4196.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4198.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4200.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4201.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4207.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4209.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4215.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4216.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4218.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4220.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4234.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4235.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4240.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4241.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4243.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4244.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4246.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4250.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4254.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4259.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4260.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4261.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4264.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4266.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4267.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4270.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4272.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4274.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4279.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4283.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4286.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4287.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4289.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4290.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4292.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4296.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4305.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4306.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4308.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4312.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4313.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4314.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4315.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4319.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4331.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4338.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4339.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4340.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4341.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4344.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4346.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4349.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4350.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4351.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4353.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4354.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4359.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4361.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4363.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4365.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4372.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4375.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4377.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4378.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4382.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4383.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4384.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4389.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4390.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4394.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4412.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4416.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4417.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4420.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4433.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4437.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4442.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4445.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4446.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4453.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4458.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4464.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4466.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4467.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4475.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4477.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4479.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4487.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4488.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4490.yml diff --git a/html/changelogs/AutoChangeLog-pr-3639.yml b/html/changelogs/AutoChangeLog-pr-3639.yml deleted file mode 100644 index 3625dfce90..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3639.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "deathride58" -delete-after: True -changes: - - bugfix: "Antags are able to greentext again" diff --git a/html/changelogs/AutoChangeLog-pr-3731.yml b/html/changelogs/AutoChangeLog-pr-3731.yml deleted file mode 100644 index 9486c7e793..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3731.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "ninjanomnom" -delete-after: True -changes: - - bugfix: "Singularity objects no longer become contaminated by radiation." - - admin: "Removed the radiation message admin spam and moved it to an investigation log." diff --git a/html/changelogs/AutoChangeLog-pr-3747.yml b/html/changelogs/AutoChangeLog-pr-3747.yml deleted file mode 100644 index 46ad021439..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3747.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ACCount" -delete-after: True -changes: - - tweak: "\"Tail removal\" and \"tail attachment\" surgeries are merged with \"organ manipulation\"." diff --git a/html/changelogs/AutoChangeLog-pr-3818.yml b/html/changelogs/AutoChangeLog-pr-3818.yml deleted file mode 100644 index 1be3ec57f4..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3818.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Swindly" -delete-after: True -changes: - - bugfix: "You can now cancel a cavity implant during the implanting/removing step by using drapes while holding the appropriate tool in your inactive hand. Cyborgs can cancel the surgery by using drapes alone." diff --git a/html/changelogs/AutoChangeLog-pr-3858.yml b/html/changelogs/AutoChangeLog-pr-3858.yml deleted file mode 100644 index 2243f683c0..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3858.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: "deathride58 & TGstation contributors" -delete-after: True -changes: - - bugfix: "Fixed various area issues in Boxstation. The theatre no longer has an air alarm for space, and Security no longer has a line of walls with broken lighting." - - tweak: "Added more lights to Boxstation's security" - - rscadd: "(Upstream) Added a new white ship to Deltastation" - - tweak: "(Upstream) Replaced the reinforced glass in Atmos' gas tanks with reinforced plasma glass" - - tweak: "(Upstream) Atmos can no longer burn itself down via the waste loop outlet" diff --git a/html/changelogs/AutoChangeLog-pr-3864.yml b/html/changelogs/AutoChangeLog-pr-3864.yml deleted file mode 100644 index 2ff6cc010e..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3864.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - tweak: "Cooldown on the Ripley's mining drills has been halved." - - tweak: "The frequency of the Ripley's ore pulse has been doubled." diff --git a/html/changelogs/AutoChangeLog-pr-3871.yml b/html/changelogs/AutoChangeLog-pr-3871.yml deleted file mode 100644 index 910a5893eb..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3871.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Bluespace shelter walls no longer smooth with non-shelter walls and windows." diff --git a/html/changelogs/AutoChangeLog-pr-3879.yml b/html/changelogs/AutoChangeLog-pr-3879.yml deleted file mode 100644 index 440ea3e616..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3879.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: "as334" -delete-after: True -changes: - - rscadd: "Pluoxium can now be formed by irradiating tiles with CO2 in the air." - - rscadd: "Rad collectors now steadily form Tritium at a slow pace." - - balance: "Nerfs fusion by making it slower, and produce radioactivity." - - balance: "Noblium formation now requires significantly more energy input." - - balance: "Tanks now melt if their temperature is above 1 Million Kelvin." diff --git a/html/changelogs/AutoChangeLog-pr-3881.yml b/html/changelogs/AutoChangeLog-pr-3881.yml deleted file mode 100644 index da5bf113eb..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3881.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Mark9013100" -delete-after: True -changes: - - tweak: "Charcoal bottles have been renamed, and have been given a more informative description." diff --git a/html/changelogs/AutoChangeLog-pr-3884.yml b/html/changelogs/AutoChangeLog-pr-3884.yml deleted file mode 100644 index cccc830fa8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3884.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "deathride58" -delete-after: True -changes: - - bugfix: "You can no longer delete girders, lattices, or catwalks with the RPD" - - bugfix: "Fixes runtimes that occur when clicking girders, lattices, catwalks, or disposal pipes with the RPD in paint mode" diff --git a/html/changelogs/AutoChangeLog-pr-3886.yml b/html/changelogs/AutoChangeLog-pr-3886.yml deleted file mode 100644 index df6baaf9e8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3886.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Clockwork slabs no longer refer to components" diff --git a/html/changelogs/AutoChangeLog-pr-3887.yml b/html/changelogs/AutoChangeLog-pr-3887.yml deleted file mode 100644 index 6abe71ce5d..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3887.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "DaxDupont" -delete-after: True -changes: - - bugfix: "Medbots can inject from one tile away again." diff --git a/html/changelogs/AutoChangeLog-pr-3889.yml b/html/changelogs/AutoChangeLog-pr-3889.yml deleted file mode 100644 index 0dbe1a4a54..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3889.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "The detective and heads of staff are no longer attacked by portable turrets." diff --git a/html/changelogs/AutoChangeLog-pr-3892.yml b/html/changelogs/AutoChangeLog-pr-3892.yml deleted file mode 100644 index d56a3291ca..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3892.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ninjanomnom" -delete-after: True -changes: - - bugfix: "Fixes ruin cable spawning and probably some other bugs" diff --git a/html/changelogs/AutoChangeLog-pr-3900.yml b/html/changelogs/AutoChangeLog-pr-3900.yml deleted file mode 100644 index aea022be12..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3900.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Qbopper and JJRcop" -delete-after: True -changes: - - tweak: "The default internet sound volume was changed from 100 to 25. Stop complaining in OOC about your ears!" diff --git a/html/changelogs/AutoChangeLog-pr-3901.yml b/html/changelogs/AutoChangeLog-pr-3901.yml deleted file mode 100644 index ac91a766d7..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3901.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "nicn" -delete-after: True -changes: - - balance: "Damage from low pressure has been doubled." diff --git a/html/changelogs/AutoChangeLog-pr-3908.yml b/html/changelogs/AutoChangeLog-pr-3908.yml deleted file mode 100644 index bd69080a7d..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3908.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Posters may no longer be placed on diagonal wall corners." diff --git a/html/changelogs/AutoChangeLog-pr-3912.yml b/html/changelogs/AutoChangeLog-pr-3912.yml deleted file mode 100644 index 85cf3a8454..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3912.yml +++ /dev/null @@ -1,9 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - rscadd: "Deep fryers now have sound." - - tweak: "Deep fryers now use cooking oil, a specialized reagent that becomes highly damaging at high temperatures. You can get it from grinding soybeans and meat." - - tweak: "Deep fryers now become more efficient with higher-level micro lasers, using less oil and frying faster." - - tweak: "Deep fryers now slowly use oil as it fries objects, instead of all at once." - - bugfix: "You can now correctly refill deep fryers with syringes and pills." - - rscadd: "Microwaves have new sounds!" diff --git a/html/changelogs/AutoChangeLog-pr-3913.yml b/html/changelogs/AutoChangeLog-pr-3913.yml deleted file mode 100644 index c2a59fe367..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3913.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Cobby" -delete-after: True -changes: - - rscadd: "The Xray now only hits the first mob it comes into contact with instead of being outright removed from the game." diff --git a/html/changelogs/AutoChangeLog-pr-3916.yml b/html/changelogs/AutoChangeLog-pr-3916.yml deleted file mode 100644 index e61e4d044c..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3916.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Frozenguy5" -delete-after: True -changes: - - bugfix: "Broken cable cuffs no longer has an invisible sprite." diff --git a/html/changelogs/AutoChangeLog-pr-3919.yml b/html/changelogs/AutoChangeLog-pr-3919.yml deleted file mode 100644 index ab0e21a5d3..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3919.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Floyd / Qustinnus" -delete-after: True -changes: - - soundadd: "Reebe now has ambience sounds" diff --git a/html/changelogs/AutoChangeLog-pr-3920.yml b/html/changelogs/AutoChangeLog-pr-3920.yml deleted file mode 100644 index 8111335f02..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3920.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "LetterJay" -delete-after: True -changes: - - bugfix: "Flavor text can be examined again" diff --git a/html/changelogs/AutoChangeLog-pr-3951.yml b/html/changelogs/AutoChangeLog-pr-3951.yml deleted file mode 100644 index 6dcac4a2d3..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3951.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "SpiderPsycho" -delete-after: True -changes: - - rscadd: "Added insects without fuzz" - - rscdel: "Removed fuzz" - - tweak: "changed the name of the fuzzless sprites to insects so the character creation can call them properly." diff --git a/html/changelogs/AutoChangeLog-pr-3959.yml b/html/changelogs/AutoChangeLog-pr-3959.yml deleted file mode 100644 index f89f2489dd..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3959.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "disable_warning wasn't getting checked and the chat was being spammed" diff --git a/html/changelogs/AutoChangeLog-pr-3960.yml b/html/changelogs/AutoChangeLog-pr-3960.yml deleted file mode 100644 index dd9ab1e232..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3960.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "cell chargers weren't animating properly" diff --git a/html/changelogs/AutoChangeLog-pr-3961.yml b/html/changelogs/AutoChangeLog-pr-3961.yml deleted file mode 100644 index 52f66a3b46..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3961.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ike709" -delete-after: True -changes: - - imageadd: "Added new vent and scrubber sprites by Partheo." diff --git a/html/changelogs/AutoChangeLog-pr-3964.yml b/html/changelogs/AutoChangeLog-pr-3964.yml deleted file mode 100644 index 6061524af8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3964.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "Atmos scrubbers (vent and portable) can now filter any and all gases." diff --git a/html/changelogs/AutoChangeLog-pr-3966.yml b/html/changelogs/AutoChangeLog-pr-3966.yml deleted file mode 100644 index 40cdd5ec13..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3966.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Naksu" -delete-after: True -changes: - - bugfix: "Sped up saycode to remove free lag from highpop" diff --git a/html/changelogs/AutoChangeLog-pr-3967.yml b/html/changelogs/AutoChangeLog-pr-3967.yml deleted file mode 100644 index 28378bcc30..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3967.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "DaxDupont" -delete-after: True -changes: - - tweak: "CentCom has issued a firmware updated for the operating computers. It is no longer needed to manually refresh the procedure and patient status." diff --git a/html/changelogs/AutoChangeLog-pr-3968.yml b/html/changelogs/AutoChangeLog-pr-3968.yml deleted file mode 100644 index 3430a1e8cb..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3968.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "JJRcop" -delete-after: True -changes: - - bugfix: "Fixes changeling eggs not putting the changeling in control if the brainslug is destroyed before hatching." diff --git a/html/changelogs/AutoChangeLog-pr-3969.yml b/html/changelogs/AutoChangeLog-pr-3969.yml deleted file mode 100644 index 7f53c200d6..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3969.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "HUDs from mechs and helmets no longer conflict with HUD glasses and no longer inappropriately remove implanted HUDs." diff --git a/html/changelogs/AutoChangeLog-pr-3975.yml b/html/changelogs/AutoChangeLog-pr-3975.yml deleted file mode 100644 index 450706db1f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3975.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "DaxDupont" -delete-after: True -changes: - - bugfix: "Proximity sensors no longer beep when unarmed." diff --git a/html/changelogs/AutoChangeLog-pr-3976.yml b/html/changelogs/AutoChangeLog-pr-3976.yml deleted file mode 100644 index b3d144e1de..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3976.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Iamgoofball" -delete-after: True -changes: - - spellcheck: "fixed grammar on output circuits" diff --git a/html/changelogs/AutoChangeLog-pr-3977.yml b/html/changelogs/AutoChangeLog-pr-3977.yml deleted file mode 100644 index a4916a713e..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3977.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Iamgoofball" -delete-after: True -changes: - - spellcheck: "fixes grammar on list circuits" diff --git a/html/changelogs/AutoChangeLog-pr-3978.yml b/html/changelogs/AutoChangeLog-pr-3978.yml deleted file mode 100644 index 0840869b16..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3978.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Iamgoofball" -delete-after: True -changes: - - spellcheck: "fixes grammar on logic gate descriptions" diff --git a/html/changelogs/AutoChangeLog-pr-3979.yml b/html/changelogs/AutoChangeLog-pr-3979.yml deleted file mode 100644 index e9a21ef984..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3979.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Iamgoofball" -delete-after: True -changes: - - bugfix: "fixes grammar on trig circuits" diff --git a/html/changelogs/AutoChangeLog-pr-3980.yml b/html/changelogs/AutoChangeLog-pr-3980.yml deleted file mode 100644 index 09e3ebe5ef..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3980.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "MMMiracles" -delete-after: True -changes: - - balance: "Power regen on the regular tesla relay has been reduced to 50, from 150." diff --git a/html/changelogs/AutoChangeLog-pr-3981.yml b/html/changelogs/AutoChangeLog-pr-3981.yml deleted file mode 100644 index 0670048ed3..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3981.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "nicbn" -delete-after: True -changes: - - soundadd: "Now rolling beds and office chairs have a sound!" diff --git a/html/changelogs/AutoChangeLog-pr-3983.yml b/html/changelogs/AutoChangeLog-pr-3983.yml deleted file mode 100644 index 0e3a681757..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3983.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "oranges" -delete-after: True -changes: - - rscdel: "Removed the shocker circuit" diff --git a/html/changelogs/AutoChangeLog-pr-3988.yml b/html/changelogs/AutoChangeLog-pr-3988.yml deleted file mode 100644 index 743551eaaa..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3988.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "DaxDupont" -delete-after: True -changes: - - bugfix: "Plant trays will now properly process fluorine and adjust toxins and water contents." diff --git a/html/changelogs/AutoChangeLog-pr-3992.yml b/html/changelogs/AutoChangeLog-pr-3992.yml deleted file mode 100644 index b60be8068c..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3992.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "JJRcop" -delete-after: True -changes: - - tweak: "The silicon airlock menu looks a little more like it used to." diff --git a/html/changelogs/AutoChangeLog-pr-3993.yml b/html/changelogs/AutoChangeLog-pr-3993.yml deleted file mode 100644 index 14c4d31514..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3993.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "purple bartender suit and apron added to clothesmates!" - - rscadd: "long hair 3 added, check it out. both have sprites from okand!" diff --git a/html/changelogs/AutoChangeLog-pr-3994.yml b/html/changelogs/AutoChangeLog-pr-3994.yml deleted file mode 100644 index 2ff513ddf5..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3994.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "The RPD has a shiny new UI!" - - rscadd: "The RPD can now paint pipes as it lays them, for quicker piping projects." diff --git a/html/changelogs/AutoChangeLog-pr-3995.yml b/html/changelogs/AutoChangeLog-pr-3995.yml deleted file mode 100644 index 77d6c658da..0000000000 --- a/html/changelogs/AutoChangeLog-pr-3995.yml +++ /dev/null @@ -1,20 +0,0 @@ -author: "ShizCalev (Upstream), WJohnston (Upstream), Okand37 (Upstream), deathride58" -delete-after: True -changes: - - tweak: "(Upstream) The computers on all maps have have been updated for the latest directional sprite changes. Please report any computers facing in strange directions to your nearest mapper." - - rscadd: "(Upstream) Updated the Test Map debugging verb to report more issues regarding APCs. -DELTASTATION" - - bugfix: "(Upstream) Reverted Okand37's morgue changes which broke power in the area." - - bugfix: "(Upstream) Corrected wrong area on the Southern airlock leading into electrical maintenance. -ALL STATIONS" - - bugfix: "(Upstream) Corrected numerous duplicate APCs in areas which led to power issues." - - rscdel: "(Upstream) Removes stationary docking ports for syndicate infiltrator ships on all maps. Use the docking navigator computer instead! This gives the white ship and syndicate infiltrator more room to navigate and place custom locations that are otherwise occupied by fixed shuttle landing zones that are rarely used." - - rscadd: "(Upstream, Deltastation) Tweaked Atmospherics" - - bugfix: "(Upstream, Deltastation) Fixed the Incinerator air injector" - - rscadd: "(Upstream, Deltastation) Tweaked Engineering" - - rscadd: "(Upstream, Deltastation) Added logs to the Chaplain's closet for gimmicks (bonfires)" - - rscadd: "(Upstream, Deltastation) Tweaked Security" - - bugfix: "(Upstream, Deltastation) Fixed medical morgue maintenance not providing radiation shielding and exterior chemistry windoor" - - rscadd: "(Upstream, Deltastation) Bar now has a door from the backroom to the theatre stage" - - rscadd: "(Upstream, Deltastation) Tweaked Locker Room/Dormitories" - - bugfix: "The armory no longer has a deep frying oil vat in place of dragnets." diff --git a/html/changelogs/AutoChangeLog-pr-4000.yml b/html/changelogs/AutoChangeLog-pr-4000.yml deleted file mode 100644 index bfd91f572d..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4000.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - imageadd: "The Nanotrasen logo on modular computers has been fixed, rejoice!" diff --git a/html/changelogs/AutoChangeLog-pr-4001.yml b/html/changelogs/AutoChangeLog-pr-4001.yml deleted file mode 100644 index 578f211e20..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4001.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Pizza box stacking works again." diff --git a/html/changelogs/AutoChangeLog-pr-4005.yml b/html/changelogs/AutoChangeLog-pr-4005.yml deleted file mode 100644 index cf136090a6..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4005.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "now lists should work properly" diff --git a/html/changelogs/AutoChangeLog-pr-4008.yml b/html/changelogs/AutoChangeLog-pr-4008.yml deleted file mode 100644 index 6d6b7d53b8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4008.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "zennerx" -delete-after: True -changes: - - bugfix: "fixed a bug that made you try and scream while unconscious due to a fire" diff --git a/html/changelogs/AutoChangeLog-pr-4010.yml b/html/changelogs/AutoChangeLog-pr-4010.yml deleted file mode 100644 index b413fb1671..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4010.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Kor" -delete-after: True -changes: - - bugfix: "Blobbernauts will no longer spawn if a player is not selected to control it, preventing AI blobbernauts from running off the blob and to their deaths." diff --git a/html/changelogs/AutoChangeLog-pr-4012.yml b/html/changelogs/AutoChangeLog-pr-4012.yml deleted file mode 100644 index 18b4c3dfd2..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4012.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Toriate" -delete-after: True -changes: - - tweak: "Mag Pistol and Mag Rifle no longer spawn with magazines when built in protolathe" - - balance: "Nerf guns no longer max out science in five seconds flat" - - bugfix: "Nerf gun magazines no longer give infinite metal and glass" diff --git a/html/changelogs/AutoChangeLog-pr-4013.yml b/html/changelogs/AutoChangeLog-pr-4013.yml deleted file mode 100644 index 0507fafc72..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4013.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Fix some permanent-on and permanent-off bugs caused by the HUD stacking change." diff --git a/html/changelogs/AutoChangeLog-pr-4014.yml b/html/changelogs/AutoChangeLog-pr-4014.yml deleted file mode 100644 index 1a1698767d..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4014.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: "Skylar Lineman, your local R&D moonlighter" -delete-after: True -changes: - - rscadd: "Research has been completely overhauled into the techweb system! No more levels, the station now unlocks research \"nodes\" with research points passively generated when there is atleast one research server properly cooled, powered, and online." - - rscadd: "R&D lab has been replaced by the departmental lathe system on the three major maps. Each department gets a lathe and possibly a circuit imprinter that only have designs assigned by that department." - - rscadd: "The ore redemption machine has been moved into cargo bay on maps with decentralized research to prevent the hallways from becoming a free for all. Honk!" - - balance: "You shouldn't expect balance as this is the initial merge. Please put all feedback and concerns on the forum so we can revise the system over the days, weeks, and months, to make this enjoyable for everyone. Heavily wanted are ideas of how to add more ways of generating points." - - balance: "You can get techweb points by setting off bombs with an active science doppler array listening. The bombs have to have a theoretical radius far above maxcap to make a difference. You can only go up, not down, in radius, so you can't get 6 times the points with 6 TTVs. The algorithm is exponentially/logarithmically scaled to prevent \"world destroyer\" bombs from instantly finishing research." diff --git a/html/changelogs/AutoChangeLog-pr-4022.yml b/html/changelogs/AutoChangeLog-pr-4022.yml deleted file mode 100644 index 295229de2b..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4022.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "Chairs, PA parts, infrared emitters, and doppler arrays will now rotate clockwise." diff --git a/html/changelogs/AutoChangeLog-pr-4026.yml b/html/changelogs/AutoChangeLog-pr-4026.yml deleted file mode 100644 index 3424fdd501..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4026.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Naksu" -delete-after: True -changes: - - bugfix: "Using a chameleon projector will now dismount you from any vehicles you are riding, in order to prevent wacky space glitches and being sent to a realm outside space and time." diff --git a/html/changelogs/AutoChangeLog-pr-4027.yml b/html/changelogs/AutoChangeLog-pr-4027.yml deleted file mode 100644 index 925f8d5256..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4027.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ike709" -delete-after: True -changes: - - bugfix: "Fixed some computers facing the wrong direction." diff --git a/html/changelogs/AutoChangeLog-pr-4028.yml b/html/changelogs/AutoChangeLog-pr-4028.yml deleted file mode 100644 index 1af9360833..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4028.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Code by Pyko, Ported by Frozenguy5" -delete-after: True -changes: - - rscadd: "Rat Kebabs and Double Rat Kebabs have been added!" diff --git a/html/changelogs/AutoChangeLog-pr-4030.yml b/html/changelogs/AutoChangeLog-pr-4030.yml deleted file mode 100644 index ca630fbfd8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4030.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "zennerx" -delete-after: True -changes: - - tweak: "Skateboard crashes now give slight brain damage!" - - rscadd: "Using a helmet prevents brain damage from the skateboard!" diff --git a/html/changelogs/AutoChangeLog-pr-4031.yml b/html/changelogs/AutoChangeLog-pr-4031.yml deleted file mode 100644 index 4907986852..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4031.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - code_imp: "Ladders have been refactored and should be far less buggy." - - bugfix: "Jacob's ladder actually works again." diff --git a/html/changelogs/AutoChangeLog-pr-4032.yml b/html/changelogs/AutoChangeLog-pr-4032.yml deleted file mode 100644 index 4969c5bcaf..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4032.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "PubbyStation - Unpowered air injectors in various locations have been fixed." diff --git a/html/changelogs/AutoChangeLog-pr-4033.yml b/html/changelogs/AutoChangeLog-pr-4033.yml deleted file mode 100644 index effc283b83..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4033.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "MetaStation - Air injector leading out of the incinerator has been fixed" - - bugfix: "MetaStation - Corrected a couple maintenance airlocks being powered by the wrong areas." diff --git a/html/changelogs/AutoChangeLog-pr-4034.yml b/html/changelogs/AutoChangeLog-pr-4034.yml deleted file mode 100644 index eff19f0cfa..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4034.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "Throwing drinking glasses and cartons will now consistently cause them to break!" diff --git a/html/changelogs/AutoChangeLog-pr-4036.yml b/html/changelogs/AutoChangeLog-pr-4036.yml deleted file mode 100644 index 820c726cea..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4036.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "Computers will no longer rotate incorrectly when being deconstructed." - - bugfix: "You can now rotate computer frames during construction." diff --git a/html/changelogs/AutoChangeLog-pr-4038.yml b/html/changelogs/AutoChangeLog-pr-4038.yml deleted file mode 100644 index 9500855d83..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4038.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "WJohnston" -delete-after: True -changes: - - bugfix: "Green banded default airlocks now have extended click area like all other airlocks." diff --git a/html/changelogs/AutoChangeLog-pr-4043.yml b/html/changelogs/AutoChangeLog-pr-4043.yml deleted file mode 100644 index b867396350..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4043.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Francinum" -delete-after: True -changes: - - tweak: "The shuttle build plate is now better sized for all stations." diff --git a/html/changelogs/AutoChangeLog-pr-4049.yml b/html/changelogs/AutoChangeLog-pr-4049.yml deleted file mode 100644 index f2d883ca0d..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4049.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "WJohnston" -delete-after: True -changes: - - imageadd: "A bunch of new turf decals for mappers to play with, coming in yellow, white, and red varieties!" diff --git a/html/changelogs/AutoChangeLog-pr-4050.yml b/html/changelogs/AutoChangeLog-pr-4050.yml deleted file mode 100644 index 85d49a56fe..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4050.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "Computers will no longer delete themselves when being built, whoops!" diff --git a/html/changelogs/AutoChangeLog-pr-4051.yml b/html/changelogs/AutoChangeLog-pr-4051.yml deleted file mode 100644 index ee3ed953c1..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4051.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: "ACCount" -delete-after: True -changes: - - refactor: "Old integrated circuit save file format is ditched in favor of JSON. Readability, both of save files and save code, is improved greatly." - - tweak: "Integrated circuit panels now open with screwdriver instead of crowbar, to match every single other thing on this server." - - tweak: "Integrated circuit printer now stores up to 25 metal sheets." - - bugfix: "Fixed integrated circuit rechargers not recharging guns properly and not updating icons." - - bugfix: "Fixed multiple bugs in integrated circuits UIs, improved overall usability." diff --git a/html/changelogs/AutoChangeLog-pr-4052.yml b/html/changelogs/AutoChangeLog-pr-4052.yml deleted file mode 100644 index ad7e91b332..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4052.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "Humans missing legs or are legcuffed will no longer move slower in areas without gravity." diff --git a/html/changelogs/AutoChangeLog-pr-4053.yml b/html/changelogs/AutoChangeLog-pr-4053.yml deleted file mode 100644 index 9f749a63a5..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4053.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Toriate" -delete-after: True -changes: - - rscadd: "Added recolourable clothes" - - tweak: "jumpsuits in mixed wardrobe replaced with recolourable clothes" - - imageadd: "greyscaled clothing sprites for colourable clothes" diff --git a/html/changelogs/AutoChangeLog-pr-4055.yml b/html/changelogs/AutoChangeLog-pr-4055.yml deleted file mode 100644 index 618a46b39c..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4055.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "The structures external to stations are now properly lit. Make sure you bring a flashlight." diff --git a/html/changelogs/AutoChangeLog-pr-4059.yml b/html/changelogs/AutoChangeLog-pr-4059.yml deleted file mode 100644 index 1742cf5805..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4059.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "psykzz" -delete-after: True -changes: - - rscadd: "Added TGUI for Turbine computer" diff --git a/html/changelogs/AutoChangeLog-pr-4060.yml b/html/changelogs/AutoChangeLog-pr-4060.yml deleted file mode 100644 index 7846d861f4..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4060.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Y0SH1 M4S73R" -delete-after: True -changes: - - spellcheck: "The R&D Server's name is now improper." - - spellcheck: "The R&D Server now has an explanation of what it does." diff --git a/html/changelogs/AutoChangeLog-pr-4064.yml b/html/changelogs/AutoChangeLog-pr-4064.yml deleted file mode 100644 index 90f52d39aa..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4064.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "jammer312" -delete-after: True -changes: - - bugfix: "fixed conjuration spells forgetting about conjured items" diff --git a/html/changelogs/AutoChangeLog-pr-4066.yml b/html/changelogs/AutoChangeLog-pr-4066.yml deleted file mode 100644 index 6858021004..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4066.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - code_imp: "Chasm code has been refactored to be more sane." - - bugfix: "Building lattices over chasms no longer sometimes deletes the chasm." diff --git a/html/changelogs/AutoChangeLog-pr-4067.yml b/html/changelogs/AutoChangeLog-pr-4067.yml deleted file mode 100644 index 103a03d08a..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4067.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "Space cats will no longer have a smashed helmet when they lay down." diff --git a/html/changelogs/AutoChangeLog-pr-4069.yml b/html/changelogs/AutoChangeLog-pr-4069.yml deleted file mode 100644 index c6832bbbf7..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4069.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - admin: "\"ahelp\" chat command can now accept a ticket number as opposed to a ckey" diff --git a/html/changelogs/AutoChangeLog-pr-4072.yml b/html/changelogs/AutoChangeLog-pr-4072.yml deleted file mode 100644 index 88296b7a45..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4072.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - code_imp: "Added round id to the status world topic" diff --git a/html/changelogs/AutoChangeLog-pr-4075.yml b/html/changelogs/AutoChangeLog-pr-4075.yml deleted file mode 100644 index d627c00d1f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4075.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "GupGup" -delete-after: True -changes: - - bugfix: "Fixes hostile mobs attacking surrounding tiles when trying to attack someone" diff --git a/html/changelogs/AutoChangeLog-pr-4076.yml b/html/changelogs/AutoChangeLog-pr-4076.yml deleted file mode 100644 index b40f213dd3..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4076.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "XDTM" -delete-after: True -changes: - - rscadd: "Added two new symptoms: one allows viruses to still work while dead, and allows infection of undead species, and one allows infection of inorganic species (such as plasmapeople or golems)." diff --git a/html/changelogs/AutoChangeLog-pr-4077.yml b/html/changelogs/AutoChangeLog-pr-4077.yml deleted file mode 100644 index 56e6ca4c9e..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4077.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "Aliens in soft-crit will now use the correct sprite." diff --git a/html/changelogs/AutoChangeLog-pr-4080.yml b/html/changelogs/AutoChangeLog-pr-4080.yml deleted file mode 100644 index d10288ec03..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4080.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "MrStonedOne and Jordie" -delete-after: True -changes: - - server: "As a late note, serverops be advise that mysql is no longer supported. existing mysql databases will need to be converted to mariadb" diff --git a/html/changelogs/AutoChangeLog-pr-4084.yml b/html/changelogs/AutoChangeLog-pr-4084.yml deleted file mode 100644 index ddd147e1e0..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4084.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: "deathride58" -delete-after: True -changes: - - bugfix: "The vault in boxstation now has power again." - - bugfix: "The gravity generator in boxstation now has power again." - - bugfix: "Various broken decals in boxstation have been fixed." - - bugfix: "The clown and mime offices no longer have APCs pointing to the wrong areas." - - rscadd: "Boxstation's secure cell has been readded to security." diff --git a/html/changelogs/AutoChangeLog-pr-4095.yml b/html/changelogs/AutoChangeLog-pr-4095.yml deleted file mode 100644 index dd5036cb59..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4095.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ACCount" -delete-after: True -changes: - - rscdel: "Removed \"console screen\" stock part. Just use glass sheets instead." diff --git a/html/changelogs/AutoChangeLog-pr-4099.yml b/html/changelogs/AutoChangeLog-pr-4099.yml deleted file mode 100644 index ac5424fd57..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4099.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ninjanomnom" -delete-after: True -changes: - - bugfix: "Custom shuttle dockers can no longer place docking regions inside other custom docker regions." diff --git a/html/changelogs/AutoChangeLog-pr-4100.yml b/html/changelogs/AutoChangeLog-pr-4100.yml deleted file mode 100644 index e8abc00b9e..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4100.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Fix water misters being inappropriately glued to hands in some cases." diff --git a/html/changelogs/AutoChangeLog-pr-4105.yml b/html/changelogs/AutoChangeLog-pr-4105.yml deleted file mode 100644 index 1ce922ad64..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4105.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "More Robust Than You" -delete-after: True -changes: - - tweak: "Spessmen are now smart enough to realize you don't need to turn around to pull cigarette butts" diff --git a/html/changelogs/AutoChangeLog-pr-4106.yml b/html/changelogs/AutoChangeLog-pr-4106.yml deleted file mode 100644 index 326d296e90..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4106.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Some misplaced decals in the Hotel brig have been corrected." diff --git a/html/changelogs/AutoChangeLog-pr-4110.yml b/html/changelogs/AutoChangeLog-pr-4110.yml deleted file mode 100644 index cd94f6dae7..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4110.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CosmicScientist" -delete-after: True -changes: - - bugfix: "bolas are back in tablecrafting!" diff --git a/html/changelogs/AutoChangeLog-pr-4111.yml b/html/changelogs/AutoChangeLog-pr-4111.yml deleted file mode 100644 index 1019538b17..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4111.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ninjanomnom" -delete-after: True -changes: - - bugfix: "Fixes thermite burning hotter than the boiling point of stone" diff --git a/html/changelogs/AutoChangeLog-pr-4112.yml b/html/changelogs/AutoChangeLog-pr-4112.yml deleted file mode 100644 index 12412931b6..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4112.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "AIs and cyborgs can interact with unscrewed airlocks and APCs." diff --git a/html/changelogs/AutoChangeLog-pr-4116.yml b/html/changelogs/AutoChangeLog-pr-4116.yml deleted file mode 100644 index 877ad76460..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4116.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Dorsisdwarf" -delete-after: True -changes: - - tweak: "Catpeople are now distracted instead of debilitated" - - rscadd: "Normal cats now go for laser pointers" diff --git a/html/changelogs/AutoChangeLog-pr-4117.yml b/html/changelogs/AutoChangeLog-pr-4117.yml deleted file mode 100644 index bb2c70bccc..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4117.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "You can no longer buckle people to roller beds from inside of a locker." diff --git a/html/changelogs/AutoChangeLog-pr-4121.yml b/html/changelogs/AutoChangeLog-pr-4121.yml deleted file mode 100644 index a226595420..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4121.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "zennerx" -delete-after: True -changes: - - bugfix: "Zombies don't reanimate with no head!" diff --git a/html/changelogs/AutoChangeLog-pr-4124.yml b/html/changelogs/AutoChangeLog-pr-4124.yml deleted file mode 100644 index e568f3e9df..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4124.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "WJohnston" -delete-after: True -changes: - - bugfix: "Fixed a case where items would sometimes be placed underneath racks." diff --git a/html/changelogs/AutoChangeLog-pr-4125.yml b/html/changelogs/AutoChangeLog-pr-4125.yml deleted file mode 100644 index a8f5bdbe86..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4125.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Naksu" -delete-after: True -changes: - - bugfix: "Hopefully fixed mesons granting the ability to hear people through walls." diff --git a/html/changelogs/AutoChangeLog-pr-4126.yml b/html/changelogs/AutoChangeLog-pr-4126.yml deleted file mode 100644 index 42689125e8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4126.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Cryo cells can now be properly rotated with a wrench." diff --git a/html/changelogs/AutoChangeLog-pr-4127.yml b/html/changelogs/AutoChangeLog-pr-4127.yml deleted file mode 100644 index b9f6abc58d..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4127.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "More Robust Than You" -delete-after: True -changes: - - bugfix: "Fixed cult leaders being de-culted upon election if they had a mindshield implant" diff --git a/html/changelogs/AutoChangeLog-pr-4129.yml b/html/changelogs/AutoChangeLog-pr-4129.yml deleted file mode 100644 index 16d3765876..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4129.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ninjanomnom" -delete-after: True -changes: - - rscadd: "You can now make a new tasty traditional treat: butterdogs. Watch out, they're slippery." diff --git a/html/changelogs/AutoChangeLog-pr-4133.yml b/html/changelogs/AutoChangeLog-pr-4133.yml deleted file mode 100644 index 2b50fbd4ea..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4133.yml +++ /dev/null @@ -1,14 +0,0 @@ -author: "XDTM" -delete-after: True -changes: - - balance: "Viruses' healing symptoms have been reworked!" - - rscdel: "All existing healing symptoms have been removed in favour of new ones." - - rscdel: "Weight Even and Weight Gain have been removed, so hunger can be used for balancing in symptoms." - - rscadd: "Starlight Condensation heals toxin damage if you're in space using starlight as a catalyst. Being up to two tiles away also works, as long as you can still see it, but slower." - - rscadd: "Toxolysis (level 7) rapidly cleanses all chemicals from the body, with no exception." - - rscadd: "Cellular Molding heals brute damage depending on your body temperature: the higher the temperature, the faster the healing. Requires above-average temperature to activate, and the speed heavily increases while on fire." - - rscadd: "Regenerative Coma (level 8) causes the virus to send you into a deep coma when you are heavily damaged (>70 brute+burn damage). While you are unconscious, either from the virus or from other sources, the virus will heal both brute and burn damage fairly quickly. Sleeping also works, but at reduced speed." - - rscadd: "Tissue Hydration heals burn damage if you are wet (negative fire stacks) or if you have water in your bloodstream." - - rscadd: "Plasma Fixation (level 8) stabilizes temperature and heals burns while plasma is in your body or while standing in a plasma cloud. Does not protect from the poisoning effects of plasma." - - rscadd: "Radioactive Resonance gives a mild constant brute and burn healing while irradiated. The healing becomes more intense if you reach higher levels of radiation, but is still less than the alternatives." - - rscadd: "Metabolic Boost (level 7) doubles the rate at which you process chemicals, good and bad, but also increases hunger tenfold." diff --git a/html/changelogs/AutoChangeLog-pr-4136.yml b/html/changelogs/AutoChangeLog-pr-4136.yml deleted file mode 100644 index 0737b28919..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4136.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "ACCount" -delete-after: True -changes: - - rscadd: "New integrated circuit components: list constructors/deconstructors. Useful for building lists and taking them apart." - - bugfix: "Fixed multiple bugs in integrated circuits UIs, improved overall usability." diff --git a/html/changelogs/AutoChangeLog-pr-4143.yml b/html/changelogs/AutoChangeLog-pr-4143.yml deleted file mode 100644 index dc1f281cec..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4143.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Naksu" -delete-after: True -changes: - - code_imp: "rejiggered botcode a little bit" diff --git a/html/changelogs/AutoChangeLog-pr-4144.yml b/html/changelogs/AutoChangeLog-pr-4144.yml deleted file mode 100644 index bcefc8437a..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4144.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "You can make many different types of office and comfy chairs with metal" - - tweak: "Stack menus use /datum/browser" diff --git a/html/changelogs/AutoChangeLog-pr-4145.yml b/html/changelogs/AutoChangeLog-pr-4145.yml deleted file mode 100644 index c7b269b20f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4145.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "improvedname" -delete-after: True -changes: - - tweak: "toolbelts can now carry geiger counters" diff --git a/html/changelogs/AutoChangeLog-pr-4149.yml b/html/changelogs/AutoChangeLog-pr-4149.yml deleted file mode 100644 index 909fc3e1b9..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4149.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "JJRcop" -delete-after: True -changes: - - admin: "Fixed the Make space ninja verb." diff --git a/html/changelogs/AutoChangeLog-pr-4150.yml b/html/changelogs/AutoChangeLog-pr-4150.yml deleted file mode 100644 index 943af018e5..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4150.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ACCount" -delete-after: True -changes: - - rscdel: "Mass-spectrometers are removed. Would anyone notice if not for this changelog entry?" diff --git a/html/changelogs/AutoChangeLog-pr-4152.yml b/html/changelogs/AutoChangeLog-pr-4152.yml deleted file mode 100644 index df1b1cd09f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4152.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ACCount" -delete-after: True -changes: - - rscdel: "\"Machine prototype\" is removed from the game." diff --git a/html/changelogs/AutoChangeLog-pr-4155.yml b/html/changelogs/AutoChangeLog-pr-4155.yml deleted file mode 100644 index 0f762fae2e..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4155.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "AI and observer diagnostic huds will now show the astar path of all bots, and Pai bots will be given a visible path to follow when called by the AI." diff --git a/html/changelogs/AutoChangeLog-pr-4162.yml b/html/changelogs/AutoChangeLog-pr-4162.yml deleted file mode 100644 index be4968592e..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4162.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - tweak: "The sloth no longer suspiciously moves fast when gliding between tiles." - - balance: "The sloth's movespeed when inhabited by a player has been lowered from once every 1/5 of a second to once every second." diff --git a/html/changelogs/AutoChangeLog-pr-4170.yml b/html/changelogs/AutoChangeLog-pr-4170.yml deleted file mode 100644 index f54be6c190..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4170.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ninjanomnom" -delete-after: True -changes: - - tweak: "Reduced the max volume of sm by 1/5th and made the upper bounds only play mid delamination." diff --git a/html/changelogs/AutoChangeLog-pr-4171.yml b/html/changelogs/AutoChangeLog-pr-4171.yml deleted file mode 100644 index 612f5ad379..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4171.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "psykzz" -delete-after: True -changes: - - bugfix: "Fixing the broken turbine computer" diff --git a/html/changelogs/AutoChangeLog-pr-4172.yml b/html/changelogs/AutoChangeLog-pr-4172.yml deleted file mode 100644 index a2dac53175..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4172.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Robustin" -delete-after: True -changes: - - tweak: "Damage examinations now include a \"moderate\" classification. Before minor was <30 and severe was anything 30 or above. Now minor is <25, moderate is 25 to <50, and severe is 50+." diff --git a/html/changelogs/AutoChangeLog-pr-4175.yml b/html/changelogs/AutoChangeLog-pr-4175.yml deleted file mode 100644 index 1eed117c43..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4175.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - imageadd: "Construct shells have a new animated sprite" diff --git a/html/changelogs/AutoChangeLog-pr-4176.yml b/html/changelogs/AutoChangeLog-pr-4176.yml deleted file mode 100644 index 76ccbf0925..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4176.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: "Toriate" -delete-after: True -changes: - - rscadd: "Added Lavaknights, a new ghost role of cat people in knight armor." - - rscadd: "Added Hypereutactic blades, NEBs on steroids." - - tweak: "Made NEBs alt click to recolor -wip: Added lavaknight spawners. Someone else needs to add it in to a map or ruin properly." - - imageadd: "added sprites for hypereutactic blades" diff --git a/html/changelogs/AutoChangeLog-pr-4177.yml b/html/changelogs/AutoChangeLog-pr-4177.yml deleted file mode 100644 index f6e65ed068..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4177.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Robustin" -delete-after: True -changes: - - balance: "Clockwork magicks will now prevent Bags of Holding from being combined on Reebe." diff --git a/html/changelogs/AutoChangeLog-pr-4180.yml b/html/changelogs/AutoChangeLog-pr-4180.yml deleted file mode 100644 index fb6248b653..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4180.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Robustin" -delete-after: True -changes: - - bugfix: "Flashes will now burn out AFTER flashing when they fail instead of being a ticking time bomb that waits to screw you over on your next attempt." diff --git a/html/changelogs/AutoChangeLog-pr-4182.yml b/html/changelogs/AutoChangeLog-pr-4182.yml deleted file mode 100644 index 6d0c949e11..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4182.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Frozenguy5" -delete-after: True -changes: - - tweak: "The Particle Accelerator's wires can no longer be EMP'd" diff --git a/html/changelogs/AutoChangeLog-pr-4184.yml b/html/changelogs/AutoChangeLog-pr-4184.yml deleted file mode 100644 index f97a70a206..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4184.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CosmicScientist" -delete-after: True -changes: - - rscadd: "You can make plushies kiss one another!" diff --git a/html/changelogs/AutoChangeLog-pr-4186.yml b/html/changelogs/AutoChangeLog-pr-4186.yml deleted file mode 100644 index 86951d81f1..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4186.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Naksu" -delete-after: True -changes: - - code_imp: "Cleans up some loc assignments" diff --git a/html/changelogs/AutoChangeLog-pr-4191.yml b/html/changelogs/AutoChangeLog-pr-4191.yml deleted file mode 100644 index 5904f70b86..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4191.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "BeeSting12" -delete-after: True -changes: - - spellcheck: "Occupand ---> Occupant on opened cryogenic pods." - - spellcheck: "Cyrogenic ---> Cryogenic on opened cryogenic pods." diff --git a/html/changelogs/AutoChangeLog-pr-4196.yml b/html/changelogs/AutoChangeLog-pr-4196.yml deleted file mode 100644 index 49ab9fdbd9..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4196.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "zennerx" -delete-after: True -changes: - - spellcheck: "fixed some typos in the weapon firing mechanism description" diff --git a/html/changelogs/AutoChangeLog-pr-4198.yml b/html/changelogs/AutoChangeLog-pr-4198.yml deleted file mode 100644 index 93e2f2212a..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4198.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - rscadd: "Light fixtures now turn an ominous, dim red color when they lose power, and draw from an internal power cell to maintain it until either the cell dies (usually after 10 minutes) or power is restored." - - rscadd: "You can override emergency light functionality from an APC. You can also click on individual lights as a cyborg or AI to override them individually. Traitor AIs also have a new ability that disables emergency lights across the entire station." diff --git a/html/changelogs/AutoChangeLog-pr-4200.yml b/html/changelogs/AutoChangeLog-pr-4200.yml deleted file mode 100644 index a2321590c7..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4200.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "You can now lay (buckle!) yourself to a bed to avoid being burnt to a crisp during \"the floor is lava\" event." diff --git a/html/changelogs/AutoChangeLog-pr-4201.yml b/html/changelogs/AutoChangeLog-pr-4201.yml deleted file mode 100644 index 127a8b26ed..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4201.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Robustin" -delete-after: True -changes: - - tweak: "Igniting plasma statues no longer ignores ignition temperature and only creates as much plasma as was used in its creation." diff --git a/html/changelogs/AutoChangeLog-pr-4207.yml b/html/changelogs/AutoChangeLog-pr-4207.yml deleted file mode 100644 index 692dca99ed..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4207.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - bugfix: "You now need fuel in your welder to repair mechs." diff --git a/html/changelogs/AutoChangeLog-pr-4209.yml b/html/changelogs/AutoChangeLog-pr-4209.yml deleted file mode 100644 index ee1613d170..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4209.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "You can now record and replay holopad messages using holodisks." - - rscadd: "Holodisks are printable in autolathes." diff --git a/html/changelogs/AutoChangeLog-pr-4215.yml b/html/changelogs/AutoChangeLog-pr-4215.yml deleted file mode 100644 index 6e4fe16805..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4215.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Dax Dupont" -delete-after: True -changes: - - rscadd: "Nanotrasen is happy to announce the pinnacle in plasma research! The Disco Inferno shuttle design is the result of decades of plasma research. Burn, baby, burn!" diff --git a/html/changelogs/AutoChangeLog-pr-4216.yml b/html/changelogs/AutoChangeLog-pr-4216.yml deleted file mode 100644 index 8b39d4aa94..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4216.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - tweak: "Stethoscopes now inform the user if the target can be defibrillated; the user will hear a \"faint, fluttery pulse.\"" diff --git a/html/changelogs/AutoChangeLog-pr-4218.yml b/html/changelogs/AutoChangeLog-pr-4218.yml deleted file mode 100644 index 334c16e021..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4218.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - spellcheck: "Energy values are now measured in joules. What was previously 1 unit is now 1 kJ." diff --git a/html/changelogs/AutoChangeLog-pr-4220.yml b/html/changelogs/AutoChangeLog-pr-4220.yml deleted file mode 100644 index 7287bee043..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4220.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - sounddel: "Reduced the volume of showers" diff --git a/html/changelogs/AutoChangeLog-pr-4234.yml b/html/changelogs/AutoChangeLog-pr-4234.yml deleted file mode 100644 index 3310bdb750..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4234.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Syndicate uplink implants now work again." diff --git a/html/changelogs/AutoChangeLog-pr-4235.yml b/html/changelogs/AutoChangeLog-pr-4235.yml deleted file mode 100644 index 35197c0edf..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4235.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Robustin" -delete-after: True -changes: - - rscdel: "Reverted changes in 3d sound system that tripled the distance that sound would carry." diff --git a/html/changelogs/AutoChangeLog-pr-4240.yml b/html/changelogs/AutoChangeLog-pr-4240.yml deleted file mode 100644 index bb77fc8cd8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4240.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "coiax" -delete-after: True -changes: - - rscadd: "Quiet areas of libraries on station have now been equipped with a -vending machine containing suitable recreational activities." diff --git a/html/changelogs/AutoChangeLog-pr-4241.yml b/html/changelogs/AutoChangeLog-pr-4241.yml deleted file mode 100644 index 77a17bb5b1..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4241.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "coiax" -delete-after: True -changes: - - rscadd: "The drone dispenser on Metastation has been moved to the -maintenance by Robotics." diff --git a/html/changelogs/AutoChangeLog-pr-4243.yml b/html/changelogs/AutoChangeLog-pr-4243.yml deleted file mode 100644 index 4971528f94..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4243.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Revenant Defile ability" -delete-after: True -changes: - - bugfix: "Revenant's Defile now removes salt piles" diff --git a/html/changelogs/AutoChangeLog-pr-4244.yml b/html/changelogs/AutoChangeLog-pr-4244.yml deleted file mode 100644 index d1081a8801..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4244.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Dax Dupont & Alek2ander" -delete-after: True -changes: - - tweak: "Binary chat messages been made more visible." diff --git a/html/changelogs/AutoChangeLog-pr-4246.yml b/html/changelogs/AutoChangeLog-pr-4246.yml deleted file mode 100644 index 555f050d39..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4246.yml +++ /dev/null @@ -1,16 +0,0 @@ -author: "XDTM" -delete-after: True -changes: - - rscadd: "Brain damage has been completely reworked! -remove: Brain damage now no longer simply makes you dumb. Although most of its effects have been shifted into a brain trauma." - - rscadd: "Every time you take brain damage, there's a chance you'll suffer a brain trauma. There are many variations of brain traumas, split in mild, severe, and special." - - rscadd: "Mild brain traumas are the easiest to get, can be lightly to moderately annoying, and can be cured with mannitol and time." - - rscadd: "Severe brain traumas are much rarer and require extensive brain damage before you have a chance to get them; they are usually very debilitating. Unlike mild traumas, they require surgery to cure. A new surgery procedure has been added for this, the aptly named Brain Surgery. It can also heal minor traumas." - - rscadd: "Special brain traumas are rarely gained in place of Severe traumas: they are either complex or beneficial. -However, they are also even easier to cure than mild traumas, which means that keeping these will usually mean keeping a mild trauma along with it." - - rscadd: "Mobs can only naturally have one mild trauma and one severe or special trauma." - - balance: "Brain damage will now kill and ruin the brain if it goes above 200. If it somehow goes above 400, the brain will melt and be destroyed completely." - - balance: "Many brain-damaging effects have been given a damage cap, making them non-lethal." - - rscdel: "The Unintelligible mutation has been removed and made into a brain trauma." - - rscdel: "Brain damage no longer makes using machines a living hell." - - rscadd: "Abductors give minor traumas to people they experiment on." diff --git a/html/changelogs/AutoChangeLog-pr-4250.yml b/html/changelogs/AutoChangeLog-pr-4250.yml deleted file mode 100644 index 7539b323a8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4250.yml +++ /dev/null @@ -1,16 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - rscadd: "Added the Eminence role to clockcult! Players can elect themselves or ghosts as the Eminence from the eminence spire structure on Reebe." - - rscadd: "The Eminence is incorporeal and invisible, and directs the entire cult. Anything they say is heard over the Hierophant network, and they can issue commands by middle-clicking themselves or different turfs." - - rscadd: "The Eminence also has a single-use mass recall that warps all servants to the Ark chamber." - - rscadd: "Added traps, triggers, and brass filaments to link them. They can all be constructed from brass sheets, and do different things and trigger in different ways. Current traps include the brass skewer and steam vent, and triggers include the pressure sensor, lever, and repeater." - - rscadd: "The Eminence can activate trap triggers by clicking on them!" - - rscadd: "Servants can deconstruct traps instantly with a wrench." - - rscdel: "Mending Mantra has been removed." - - tweak: "Clockwork scriptures have been recolored and sorted based on their functions; yellow scriptures are for construction, red for offense, blue for defense, and purple for niche." - - balance: "Servants now spawn with a PDA and black shoes to make disguise more feasible." - - balance: "The Eminence can superheat up to 20 clockwork walls at a time. Superheated walls are immune to hulk and mech punches, but can still be broken conventionally." - - balance: "Clockwork walls are slightly faster to build before the Ark activates, taking an extra second less." - - bugfix: "Poly no longer continually undergoes binary fission when Ratvar is in range." - - code_imp: "The global records alert for servants will no longer display info that doesn't affect them since the rework." diff --git a/html/changelogs/AutoChangeLog-pr-4254.yml b/html/changelogs/AutoChangeLog-pr-4254.yml deleted file mode 100644 index cdfa4c7c0b..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4254.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - bugfix: "Games vending machines can now properly be rebuilt." - - bugfix: "Games vending machines can now be refilled via supply crates." - - rscadd: "Games Supply Crates have been added to the cargo console." diff --git a/html/changelogs/AutoChangeLog-pr-4259.yml b/html/changelogs/AutoChangeLog-pr-4259.yml deleted file mode 100644 index 7536cfa7a6..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4259.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "Action buttons now remember positions where you locked." - - tweak: "Now locking action buttons prevents them from being reset." diff --git a/html/changelogs/AutoChangeLog-pr-4260.yml b/html/changelogs/AutoChangeLog-pr-4260.yml deleted file mode 100644 index 1880edb973..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4260.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - rscadd: "You can now make pet carriers from the autolathe, to carry around chef meat and other small animals without having to drag them. The HoP, captain, and CMO also start with carriers in their lockers for their pets." diff --git a/html/changelogs/AutoChangeLog-pr-4261.yml b/html/changelogs/AutoChangeLog-pr-4261.yml deleted file mode 100644 index d7b0bcebf5..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4261.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - tweak: "Slime blueprints can now make an area compatible with Xenobio consoles, regardless of the name of the new area" diff --git a/html/changelogs/AutoChangeLog-pr-4264.yml b/html/changelogs/AutoChangeLog-pr-4264.yml deleted file mode 100644 index 3a3b5c1f42..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4264.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "You now can get a medal for wasting hours talking to the secret debug tile." - - bugfix: "Fixed runtime for the tile when poly's speech file doesn't exist." diff --git a/html/changelogs/AutoChangeLog-pr-4266.yml b/html/changelogs/AutoChangeLog-pr-4266.yml deleted file mode 100644 index e66348d5b4..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4266.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Fixed the camera failure, race swap, cursed items, and imposter wizard random events" - - tweak: "The cursed items event no longer nullspaces items" diff --git a/html/changelogs/AutoChangeLog-pr-4267.yml b/html/changelogs/AutoChangeLog-pr-4267.yml deleted file mode 100644 index 97e3a17b9a..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4267.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "MrDoomBringer" -delete-after: True -changes: - - imageadd: "All stations have been outfitted with brand new Smoke Machines! They have nicer sprites now!" diff --git a/html/changelogs/AutoChangeLog-pr-4270.yml b/html/changelogs/AutoChangeLog-pr-4270.yml deleted file mode 100644 index 06c99c93ee..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4270.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "deathride58" -delete-after: True -changes: - - config: "The default view range can now be defined in the config. The default is 15x15, which is simplified to 7 by BYOND. For reference, Goonstation's widescreen range is 21x15. Do note that changing this value will affect the title screen. The title screen images and the title screen area on the Centcom z-level will have to be updated if the default view range is changed." diff --git a/html/changelogs/AutoChangeLog-pr-4272.yml b/html/changelogs/AutoChangeLog-pr-4272.yml deleted file mode 100644 index 8bedafab45..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4272.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "coiax" -delete-after: True -changes: - - rscadd: "The drone dispenser on Box Station has been moved from the Testing -Lab to the Morgue/Robotics maintenance tunnel." diff --git a/html/changelogs/AutoChangeLog-pr-4274.yml b/html/changelogs/AutoChangeLog-pr-4274.yml deleted file mode 100644 index b1915f089b..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4274.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Dax Dupont" -delete-after: True -changes: - - bugfix: "Fixed observer chat flavor of silicon chat." diff --git a/html/changelogs/AutoChangeLog-pr-4279.yml b/html/changelogs/AutoChangeLog-pr-4279.yml deleted file mode 100644 index cddc887068..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4279.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Dax Dupont" -delete-after: True -changes: - - bugfix: "Grilles now no longer revert to a pre-broken icon state when you hit them after they broke." diff --git a/html/changelogs/AutoChangeLog-pr-4283.yml b/html/changelogs/AutoChangeLog-pr-4283.yml deleted file mode 100644 index a96b866609..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4283.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - tweak: "The pAI software interface is now accessible via an action button." diff --git a/html/changelogs/AutoChangeLog-pr-4286.yml b/html/changelogs/AutoChangeLog-pr-4286.yml deleted file mode 100644 index 83ede8f21d..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4286.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "External airlocks of the mining base and gulag are now cycle-linked." diff --git a/html/changelogs/AutoChangeLog-pr-4287.yml b/html/changelogs/AutoChangeLog-pr-4287.yml deleted file mode 100644 index 55bbeb05c2..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4287.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "XDTM" -delete-after: True -changes: - - tweak: "Instead of activating randomly on speech, Godwoken Syndrome randomly grants inspiration, causing the next message to be a Voice of God." diff --git a/html/changelogs/AutoChangeLog-pr-4289.yml b/html/changelogs/AutoChangeLog-pr-4289.yml deleted file mode 100644 index d0da6e0f58..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4289.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "Nanotrasen would like to remind crewmembers and especially medical personnel to stand clear of cadeavers before applying a defibrillator shock. (You get shocked if you're pulling/grabbing someone being defibbed.)" - - tweak: "defib shock/charge sounds upped from 50% to 75%." diff --git a/html/changelogs/AutoChangeLog-pr-4290.yml b/html/changelogs/AutoChangeLog-pr-4290.yml deleted file mode 100644 index a7a034433f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4290.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Swindly" -delete-after: True -changes: - - rscadd: "You can kill yourself with a few more items." diff --git a/html/changelogs/AutoChangeLog-pr-4292.yml b/html/changelogs/AutoChangeLog-pr-4292.yml deleted file mode 100644 index 14dda4b668..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4292.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - tweak: "Flickering lights will now actually flicker and not go between emergency lights and normal lighting." diff --git a/html/changelogs/AutoChangeLog-pr-4296.yml b/html/changelogs/AutoChangeLog-pr-4296.yml deleted file mode 100644 index 1e87a3fdaf..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4296.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - bugfix: "Emergency lights no longer stay on forever in some cases." diff --git a/html/changelogs/AutoChangeLog-pr-4305.yml b/html/changelogs/AutoChangeLog-pr-4305.yml deleted file mode 100644 index d6ae57f28d..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4305.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "The MULEbots that the station starts with now show their ID numbers." diff --git a/html/changelogs/AutoChangeLog-pr-4306.yml b/html/changelogs/AutoChangeLog-pr-4306.yml deleted file mode 100644 index 0a6361f11d..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4306.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Improvedname" -delete-after: True -changes: - - tweak: "cats now drop their ears and tail when butchered." diff --git a/html/changelogs/AutoChangeLog-pr-4308.yml b/html/changelogs/AutoChangeLog-pr-4308.yml deleted file mode 100644 index 5f277e0e53..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4308.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Booze-o-mats have beer" diff --git a/html/changelogs/AutoChangeLog-pr-4312.yml b/html/changelogs/AutoChangeLog-pr-4312.yml deleted file mode 100644 index 8c05f5d79e..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4312.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Robustin" -delete-after: True -changes: - - bugfix: "Modes not in rotation have had their \"false report\" weights for the Command Report standardized" diff --git a/html/changelogs/AutoChangeLog-pr-4313.yml b/html/changelogs/AutoChangeLog-pr-4313.yml deleted file mode 100644 index a1124c765a..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4313.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - tweak: "The white ship navigation computer now takes 10 seconds to designate a landing spot, and users can no longer see the syndicate shuttle or its custom landing location. If the white ship landing location would intersect the syndicate shuttle or its landing location, it will fail after the 10 seconds have elapsed." diff --git a/html/changelogs/AutoChangeLog-pr-4314.yml b/html/changelogs/AutoChangeLog-pr-4314.yml deleted file mode 100644 index e471271981..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4314.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "flightsuits should no longer disappear when you take them off involuntarily" - - bugfix: "beam rifles actually fire striaght now" - - bugfix: "click catchers now actually work" - - bugfix: "you no longer see space in areas you normally can't see, instead of black. in reality you can still see space but it's faint enough that you can't tell so I'll say I fixed it." diff --git a/html/changelogs/AutoChangeLog-pr-4315.yml b/html/changelogs/AutoChangeLog-pr-4315.yml deleted file mode 100644 index a021f0ccc4..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4315.yml +++ /dev/null @@ -1,10 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "Added MANY new types of airlock assembly that can be built with metal. Use metal in hand to see the new airlock assembly recipes." - - rscadd: "Added new airlock types to the RCD and airlock painter" - - rscadd: "Vault door assemblies can be built with 8 plasteel, high security assemblies with 6 plasteel" - - rscadd: "Glass mineral airlocks are finally constructible. Use glass and mineral sheets on an airlock assembly in any order to make them." - - tweak: "Glass and mineral sheets are now able to be welded out of door assemblies rather than having to deconstruct the whole thing" - - rscdel: "Airlock painter no longer works on airlock assemblies (still works on airlocks)" - - bugfix: "Titanium airlocks no longer have any missing overlays" diff --git a/html/changelogs/AutoChangeLog-pr-4319.yml b/html/changelogs/AutoChangeLog-pr-4319.yml deleted file mode 100644 index 851d5f12bc..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4319.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Frozenguy5" -delete-after: True -changes: - - balance: "Some hardsuits have had their melee, fire and rad armor ratings tweaked." diff --git a/html/changelogs/AutoChangeLog-pr-4331.yml b/html/changelogs/AutoChangeLog-pr-4331.yml deleted file mode 100644 index 04532aa4a8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4331.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Swindly" -delete-after: True -changes: - - bugfix: "Swarmers can no longer deconstruct objects with living things in them." diff --git a/html/changelogs/AutoChangeLog-pr-4338.yml b/html/changelogs/AutoChangeLog-pr-4338.yml deleted file mode 100644 index da4fde1e23..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4338.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "You can now print telecomms equipment again." diff --git a/html/changelogs/AutoChangeLog-pr-4339.yml b/html/changelogs/AutoChangeLog-pr-4339.yml deleted file mode 100644 index bf7c49d3e8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4339.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Robustin" -delete-after: True -changes: - - rscadd: "The blood cult revive rune will now replace the souls of braindead or inactive cultists/constructs when properly invoked. These \"revivals\" will not count toward the revive limit." - - rscadd: "The clock cult healing rune will now replace the souls of braindead or inactive cultists/constructs when left atop the rune. These \"revivals\" will not drain the rune's energy." diff --git a/html/changelogs/AutoChangeLog-pr-4340.yml b/html/changelogs/AutoChangeLog-pr-4340.yml deleted file mode 100644 index 6992dc2fd8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4340.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "deathride58" -delete-after: True -changes: - - bugfix: "fixes mobs not metabolizing their reagents" diff --git a/html/changelogs/AutoChangeLog-pr-4341.yml b/html/changelogs/AutoChangeLog-pr-4341.yml deleted file mode 100644 index e276d3bcb8..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4341.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Mark9013100" -delete-after: True -changes: - - rscadd: "Medical Wardrobes now contain an additional standard and EMT labcoat." diff --git a/html/changelogs/AutoChangeLog-pr-4344.yml b/html/changelogs/AutoChangeLog-pr-4344.yml deleted file mode 100644 index a020f7882f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4344.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "deathride58" -delete-after: True -changes: - - bugfix: "Donator items use the proper sprites when worn again." diff --git a/html/changelogs/AutoChangeLog-pr-4346.yml b/html/changelogs/AutoChangeLog-pr-4346.yml deleted file mode 100644 index d03954b91f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4346.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "deathride58" -delete-after: True -changes: - - bugfix: "The standard-issue PDAs are now holographic again." diff --git a/html/changelogs/AutoChangeLog-pr-4349.yml b/html/changelogs/AutoChangeLog-pr-4349.yml deleted file mode 100644 index 3f1bb91439..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4349.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Nonstandard power cells found in MULEbots, cyborgs, and elsewhere now have the correct description." diff --git a/html/changelogs/AutoChangeLog-pr-4350.yml b/html/changelogs/AutoChangeLog-pr-4350.yml deleted file mode 100644 index 2116fa9fd5..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4350.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "deathride58" -delete-after: True -changes: - - bugfix: "Genetics will no longer have a random block completely disappear each round" diff --git a/html/changelogs/AutoChangeLog-pr-4351.yml b/html/changelogs/AutoChangeLog-pr-4351.yml deleted file mode 100644 index bc5cabdb55..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4351.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Naksu" -delete-after: True -changes: - - bugfix: "glass shards and bananium floors no longer make a sound when \"walked\" over by a camera or a ghost" diff --git a/html/changelogs/AutoChangeLog-pr-4353.yml b/html/changelogs/AutoChangeLog-pr-4353.yml deleted file mode 100644 index 6fcf3e2ebe..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4353.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "deathride58" -delete-after: True -changes: - - rscadd: "All maps now have departmental lathes as they're supposed to." - - rscadd: "Pubbystation and Omegastation now have kinkmates! This does not add them back to the rotation, though. Tell Jay to re-enable Pubby and Omega in the server's config." - - rscadd: "Omegastation's dorms now have bolt buttons." - - bugfix: "The table in the back of Boxstation's maint bar gambling area will no longer throw people around." diff --git a/html/changelogs/AutoChangeLog-pr-4354.yml b/html/changelogs/AutoChangeLog-pr-4354.yml deleted file mode 100644 index e9aa1f0f2b..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4354.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Naksu" -delete-after: True -changes: - - code_imp: "Tidied up some loc assignments" diff --git a/html/changelogs/AutoChangeLog-pr-4359.yml b/html/changelogs/AutoChangeLog-pr-4359.yml deleted file mode 100644 index 6679e4b920..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4359.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - server: "Added new admin flag, AUTOLOGIN, to control if admins start with admin powers. this defaults to on, and can be removed with -AUTOLOGIN" - - admin: "Admins with +PERMISSION may now deadmin or readmin other admins via the permission panel." diff --git a/html/changelogs/AutoChangeLog-pr-4361.yml b/html/changelogs/AutoChangeLog-pr-4361.yml deleted file mode 100644 index 140a9a4fe3..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4361.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Shuttles now place hyperspace ripples where they are about to land again." diff --git a/html/changelogs/AutoChangeLog-pr-4363.yml b/html/changelogs/AutoChangeLog-pr-4363.yml deleted file mode 100644 index fda81eb42b..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4363.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "JStheguy" -delete-after: True -changes: - - rscadd: "Added 10 new assembly designs to the integrated circuit printer, the difference from current designs is purely aesthetics." - - imageadd: "Added the icons for said new assembly designs to electronic_setups.dmi, changed the current electronic mechanism and electronic machine sprites." diff --git a/html/changelogs/AutoChangeLog-pr-4365.yml b/html/changelogs/AutoChangeLog-pr-4365.yml deleted file mode 100644 index 165bb4d0df..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4365.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Epoc" -delete-after: True -changes: - - bugfix: "Adds Cybernetic Lungs to the Cyber Organs research node" diff --git a/html/changelogs/AutoChangeLog-pr-4372.yml b/html/changelogs/AutoChangeLog-pr-4372.yml deleted file mode 100644 index 7c1aa4b97c..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4372.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "ShizCalev" -delete-after: True -changes: - - soundadd: "Revamped gun dry-firing sounds." - - tweak: "Everyone around you will now hear when your gun goes click. You don't want to hear click when you want to hear bang!" diff --git a/html/changelogs/AutoChangeLog-pr-4375.yml b/html/changelogs/AutoChangeLog-pr-4375.yml deleted file mode 100644 index 2cf7f4c721..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4375.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Naksu" -delete-after: True -changes: - - code_imp: "fixes the remaining loc assignments" diff --git a/html/changelogs/AutoChangeLog-pr-4377.yml b/html/changelogs/AutoChangeLog-pr-4377.yml deleted file mode 100644 index 5234e24f49..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4377.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - rscadd: "Grinding runed metal and brass now produces iron/blood and iron/teslium, respectively." - - balance: "As part of some code-side improvements, the amount of reagents you get from grinding some objects might be slightly different." - - bugfix: "Some grinding recipes that didn't work, like dead mice and glowsticks, now do." - - bugfix: "All-In-One grinders now correctly grind up everything, instead of one thing at a time." diff --git a/html/changelogs/AutoChangeLog-pr-4378.yml b/html/changelogs/AutoChangeLog-pr-4378.yml deleted file mode 100644 index 22ea638655..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4378.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - imageadd: "Closet sprites changed." diff --git a/html/changelogs/AutoChangeLog-pr-4382.yml b/html/changelogs/AutoChangeLog-pr-4382.yml deleted file mode 100644 index 64568eb274..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4382.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - config: "Added \"$include\" directives to config files. These are recursive. Only config.txt will be default loaded if they are specified inside it" diff --git a/html/changelogs/AutoChangeLog-pr-4383.yml b/html/changelogs/AutoChangeLog-pr-4383.yml deleted file mode 100644 index cf9c743a03..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4383.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Naksu" -delete-after: True -changes: - - code_imp: "Preliminary work on tracking cliented living mobs across Z-levels to facilitate mob AI changes later" diff --git a/html/changelogs/AutoChangeLog-pr-4384.yml b/html/changelogs/AutoChangeLog-pr-4384.yml deleted file mode 100644 index d7f2f90350..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4384.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "EtheoBoxxman" -delete-after: True -changes: - - rscdel: "Removed chasm that spawns on killing ash walker tendril" diff --git a/html/changelogs/AutoChangeLog-pr-4389.yml b/html/changelogs/AutoChangeLog-pr-4389.yml deleted file mode 100644 index 36f17b95de..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4389.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Toriate" -delete-after: True -changes: - - tweak: "NEBs now consistently alt click to recolor" diff --git a/html/changelogs/AutoChangeLog-pr-4390.yml b/html/changelogs/AutoChangeLog-pr-4390.yml deleted file mode 100644 index 89d3683a34..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4390.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "AverageJoe82" -delete-after: True -changes: - - rscadd: "drones now have night vision" - - rscdel: "drones no longer have lights" diff --git a/html/changelogs/AutoChangeLog-pr-4394.yml b/html/changelogs/AutoChangeLog-pr-4394.yml deleted file mode 100644 index 68d57a2d11..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4394.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "The shuttle will no longer be autocalled if the round has already ended." diff --git a/html/changelogs/AutoChangeLog-pr-4412.yml b/html/changelogs/AutoChangeLog-pr-4412.yml deleted file mode 100644 index 6280189218..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4412.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - tweak: "Vitality matrices don't have visible messages when someone crosses them anymore." diff --git a/html/changelogs/AutoChangeLog-pr-4416.yml b/html/changelogs/AutoChangeLog-pr-4416.yml deleted file mode 100644 index 543fe52edd..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4416.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Robustin" -delete-after: True -changes: - - bugfix: "The wizard event \"race swap\" should now stick to \"safer\" species." diff --git a/html/changelogs/AutoChangeLog-pr-4417.yml b/html/changelogs/AutoChangeLog-pr-4417.yml deleted file mode 100644 index 46b7019353..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4417.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Xhuis" -delete-after: True -changes: - - bugfix: "Clockcult power alerts will no longer show outside of the clockcult gamemode (they could be triggered by scarabs.)" diff --git a/html/changelogs/AutoChangeLog-pr-4420.yml b/html/changelogs/AutoChangeLog-pr-4420.yml deleted file mode 100644 index 305d701c7f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4420.yml +++ /dev/null @@ -1,10 +0,0 @@ -author: "XDTM" -delete-after: True -changes: - - rscadd: "A few new traumas have been added." - - balance: "Thresholds to get brain traumas have been lowered, as they currently pretty much only trigger if you intentionally chug impedrezene." - - tweak: "Melee head hits deal minor brain damage. Crits still do a significant amount." - - tweak: "Nuke Op implants no longer trigger on deathgasp. (They still explode on death)" - - tweak: "You'll now receive messages when crossing certain brain damage thresholds." - - tweak: "Split Personalities are instructed not to suicide while in control." - - tweak: "Godwoken Syndrome now randomly sends Voice of God commands, instead of being controllable." diff --git a/html/changelogs/AutoChangeLog-pr-4433.yml b/html/changelogs/AutoChangeLog-pr-4433.yml deleted file mode 100644 index 39bde17139..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4433.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ninjanomnom" -delete-after: True -changes: - - bugfix: "Decals should now rotate the correct way around." diff --git a/html/changelogs/AutoChangeLog-pr-4437.yml b/html/changelogs/AutoChangeLog-pr-4437.yml deleted file mode 100644 index 9b11b0912e..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4437.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "nicbn" -delete-after: True -changes: - - bugfix: "Now the chem smoke machine uses stock parts for volume and range." diff --git a/html/changelogs/AutoChangeLog-pr-4442.yml b/html/changelogs/AutoChangeLog-pr-4442.yml deleted file mode 100644 index e480e91419..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4442.yml +++ /dev/null @@ -1,8 +0,0 @@ -author: "XDTM" -delete-after: True -changes: - - rscadd: "Abductors can now see if people already have glands! Never worry about abducting the same guy twice again." - - rscadd: "Added the Mind Interface Device to the abductor shop for 2 Credits. Only scientists can use it." - - rscadd: "The MID has two modes: Transmit and Control." - - rscadd: "Transmit will allow you to send a message anytime, anywhere to the mind of a target of your choice, regardless of language barriers. The message will be anonymous, but abductor-like." - - rscadd: "Control allows you to give a temporary directive to a target with an implanted gland, that they MUST follow. Duration and amount of uses varies by gland type. When a gland is spent, it will no longer respond to Control signals. The target forgets ever receiving the objective when the duration ends." diff --git a/html/changelogs/AutoChangeLog-pr-4445.yml b/html/changelogs/AutoChangeLog-pr-4445.yml deleted file mode 100644 index 6dd7a7e486..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4445.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Fixed captain's PDA showing unusable Toggle Remote Door menu option" diff --git a/html/changelogs/AutoChangeLog-pr-4446.yml b/html/changelogs/AutoChangeLog-pr-4446.yml deleted file mode 100644 index 3811f7ffb7..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4446.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "coiax" -delete-after: True -changes: - - balance: "The codespeak manual now has unlimited uses and costs 3 TC." - - bugfix: "Nuke ops can now purchase the codespeak manual, as was intended." diff --git a/html/changelogs/AutoChangeLog-pr-4453.yml b/html/changelogs/AutoChangeLog-pr-4453.yml deleted file mode 100644 index 24bce9c510..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4453.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "coiax" -delete-after: True -changes: - - rscadd: "A changeling will learn all languages from anyone they absorb." diff --git a/html/changelogs/AutoChangeLog-pr-4458.yml b/html/changelogs/AutoChangeLog-pr-4458.yml deleted file mode 100644 index 4e51890691..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4458.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "XDTM" -delete-after: True -changes: - - tweak: "The Disease Outbreak event now can generate random advanced viruses, with more symptoms and higher level as round time goes on." diff --git a/html/changelogs/AutoChangeLog-pr-4464.yml b/html/changelogs/AutoChangeLog-pr-4464.yml deleted file mode 100644 index 17f7d8fc07..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4464.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "You can enforce no smoking zones with a disarm aimed at the smokers mouth." diff --git a/html/changelogs/AutoChangeLog-pr-4466.yml b/html/changelogs/AutoChangeLog-pr-4466.yml deleted file mode 100644 index e8239ebfb4..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4466.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Toriate" -delete-after: True -changes: - - balance: "Roundstart xenos are no longer pierce immune, also no more extra damage from heat." diff --git a/html/changelogs/AutoChangeLog-pr-4467.yml b/html/changelogs/AutoChangeLog-pr-4467.yml deleted file mode 100644 index ae009bf26f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4467.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "improvedname" -delete-after: True -changes: - - bugfix: "Corrects 357. speedloader in the autolathe" diff --git a/html/changelogs/AutoChangeLog-pr-4475.yml b/html/changelogs/AutoChangeLog-pr-4475.yml deleted file mode 100644 index f37e80ed55..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4475.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - bugfix: "Passing a space transition no longer interrupts pulls." diff --git a/html/changelogs/AutoChangeLog-pr-4477.yml b/html/changelogs/AutoChangeLog-pr-4477.yml deleted file mode 100644 index bba0dab724..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4477.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - bugfix: "Fixes arm implants being immune to EMPs" diff --git a/html/changelogs/AutoChangeLog-pr-4479.yml b/html/changelogs/AutoChangeLog-pr-4479.yml deleted file mode 100644 index 623a1ada72..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4479.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscdel: "Integrated circuit smoke circuits now require 10 units of reagents to fire." diff --git a/html/changelogs/AutoChangeLog-pr-4487.yml b/html/changelogs/AutoChangeLog-pr-4487.yml deleted file mode 100644 index 588566e15c..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4487.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "ganglyalexander" -delete-after: True -changes: - - bugfix: "module icons for dog borgs now reference to a existing icon" diff --git a/html/changelogs/AutoChangeLog-pr-4488.yml b/html/changelogs/AutoChangeLog-pr-4488.yml deleted file mode 100644 index 21031f2cf3..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4488.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "coiax" -delete-after: True -changes: - - rscadd: "At the end of the round, all players can see who the antagonists -are." diff --git a/html/changelogs/AutoChangeLog-pr-4490.yml b/html/changelogs/AutoChangeLog-pr-4490.yml deleted file mode 100644 index 6477196745..0000000000 --- a/html/changelogs/AutoChangeLog-pr-4490.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "CitadelStationBot" -delete-after: True -changes: - - rscadd: "You can adjust line height in chat settings" - - tweak: "Default chat line height is slightly shorter, from 1.4 to 1.2" From 6856fc1be26ec9b5acef63a0dbac3c24d80421af Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 22 Dec 2017 14:32:56 -0600 Subject: [PATCH 93/96] [MIRROR] [s] Fixes the frying oil reagent (#4504) * Merge pull request #33745 from vuonojenmustaturska/oilfix [s] Fixes the frying oil reagent * [s] Fixes the frying oil reagent --- code/modules/reagents/chemistry/reagents/food_reagents.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index a3c0d2c034..a9f9145972 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -97,10 +97,10 @@ /datum/reagent/consumable/cooking_oil/reaction_obj(obj/O, reac_volume) if(holder && holder.chem_temp >= fry_temperature) - if(isitem(O)) + if(isitem(O) && !istype(O, /obj/item/reagent_containers/food/snacks/deepfryholder)) O.loc.visible_message("[O] rapidly fries as it's splashed with hot oil! Somehow.") - var/obj/item/reagent_containers/food/snacks/deepfryholder/F = new(O.drop_location()) - F.fry(O, volume) + var/obj/item/reagent_containers/food/snacks/deepfryholder/F = new(O.drop_location(), O) + F.fry(volume) /datum/reagent/consumable/cooking_oil/reaction_mob(mob/living/M, method = TOUCH, reac_volume, show_message = 1, touch_protection = 0) if(!istype(M)) From f6e82e446049d5d236ed953144ab2efb375344bc Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 22 Dec 2017 14:33:00 -0600 Subject: [PATCH 94/96] Automatic changelog generation for PR #4504 [ci skip] --- html/changelogs/AutoChangeLog-pr-4504.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4504.yml diff --git a/html/changelogs/AutoChangeLog-pr-4504.yml b/html/changelogs/AutoChangeLog-pr-4504.yml new file mode 100644 index 0000000000..7da90cb88b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4504.yml @@ -0,0 +1,4 @@ +author: "Naksu" +delete-after: True +changes: + - bugfix: "frying oil actually works" From 938f409782d7b8589fc5ba6bc936bcc17318eed5 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 22 Dec 2017 15:14:25 -0600 Subject: [PATCH 95/96] [MIRROR] Christmas (#4491) * Christmas (#33690) * Christmas Event Updates * Dont recreate the list every time * Check for drop del * Changes some things to placate that one guy from FTL * Christmas --- code/game/objects/items/gift.dm | 34 +++++++++++++++++++++----- code/game/objects/structures/flora.dm | 18 +++++++++++--- code/modules/events/holiday/xmas.dm | 25 +++---------------- code/modules/holiday/holidays.dm | 4 +-- icons/obj/flora/pinetrees.dmi | Bin 36037 -> 42806 bytes 5 files changed, 49 insertions(+), 32 deletions(-) diff --git a/code/game/objects/items/gift.dm b/code/game/objects/items/gift.dm index 1e3e9ccd73..0fe53f293c 100644 --- a/code/game/objects/items/gift.dm +++ b/code/game/objects/items/gift.dm @@ -7,6 +7,9 @@ /* * Gifts */ + +GLOBAL_LIST_EMPTY(possible_gifts) + /obj/item/a_gift name = "gift" desc = "PRESENTS!!!! eek!" @@ -30,6 +33,14 @@ to_chat(M, "You're supposed to be spreading gifts, not opening them yourself!") return + var/gift_type = get_gift_type() + + qdel(src) + var/obj/item/I = new gift_type(M) + M.put_in_hands(I) + I.add_fingerprint(M) + +/obj/item/a_gift/proc/get_gift_type() var/gift_type_list = list(/obj/item/sord, /obj/item/storage/wallet, /obj/item/storage/photo_album, @@ -72,10 +83,21 @@ var/gift_type = pick(gift_type_list) - if(!ispath(gift_type, /obj/item)) - return + return gift_type - qdel(src) - var/obj/item/I = new gift_type(M) - M.put_in_hands(I) - I.add_fingerprint(M) + +/obj/item/a_gift/anything + name = "christmas gift" + desc = "It could be anything!" + +/obj/item/a_gift/anything/get_gift_type() + if(!GLOB.possible_gifts.len) + var/list/gift_types_list = subtypesof(/obj/item) + for(var/V in gift_types_list) + var/obj/item/I = V + if((!initial(I.icon_state)) || (!initial(I.item_state)) || (initial(I.flags_1) & ABSTRACT_1)) + gift_types_list -= V + GLOB.possible_gifts = gift_types_list + var/gift_type = pick(GLOB.possible_gifts) + + return gift_type diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index f7071cd0a5..393ff3886d 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -36,9 +36,6 @@ else return ..() - - - /obj/structure/flora/tree/pine name = "pine tree" desc = "A coniferous pine tree." @@ -53,6 +50,21 @@ name = "xmas tree" desc = "A wondrous decorated Christmas tree." icon_state = "pine_c" + var/gifts_under_tree = FALSE + var/list/ckeys_that_took = list() + +/obj/structure/flora/tree/pine/xmas/attack_hand(mob/living/user) + if(!gifts_under_tree) + return + if(!user.ckey) + return + if(ckeys_that_took[user.ckey]) + to_chat(user, "You already took your gift.") + return + to_chat(user, "After a bit of rummaging, you locate a gift with your name on it!") + ckeys_that_took[user.ckey] = TRUE + var/obj/item/a_gift/anything/A = new + user.put_in_hands(A) /obj/structure/flora/tree/pine/xmas/Initialize() . = ..() diff --git a/code/modules/events/holiday/xmas.dm b/code/modules/events/holiday/xmas.dm index 2f5618714d..956a214009 100644 --- a/code/modules/events/holiday/xmas.dm +++ b/code/modules/events/holiday/xmas.dm @@ -1,19 +1,3 @@ -/datum/round_event_control/treevenge - name = "Treevenge (Christmas)" - holidayID = CHRISTMAS - typepath = /datum/round_event/treevenge - max_occurrences = 1 - weight = 20 - -/datum/round_event/treevenge/start() - for(var/obj/structure/flora/tree/pine/xmas in world) - var/mob/living/simple_animal/hostile/tree/evil_tree = new /mob/living/simple_animal/hostile/tree(xmas.loc) - evil_tree.icon_state = xmas.icon_state - evil_tree.icon_living = evil_tree.icon_state - evil_tree.icon_dead = evil_tree.icon_state - evil_tree.icon_gib = evil_tree.icon_state - qdel(xmas) //b-but I don't want to delete xmas... - //this is an example of a possible round-start event /datum/round_event_control/presents name = "Presents under Trees (Christmas)" @@ -24,12 +8,11 @@ earliest_start = 0 /datum/round_event/presents/start() - for(var/obj/structure/flora/tree/pine/xmas in world) + for(var/obj/structure/flora/tree/pine/xmas/xmas in world) if(!(xmas.z in GLOB.station_z_levels)) continue - for(var/turf/open/floor/T in orange(1,xmas)) - for(var/i=1,i<=rand(1,5),i++) - new /obj/item/a_gift(T) + xmas.icon_state = "pinepresents" + xmas.gifts_under_tree = TRUE for(var/mob/living/simple_animal/pet/dog/corgi/Ian/Ian in GLOB.mob_living_list) Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian)) for(var/obj/machinery/computer/security/telescreen/entertainment/Monitor in GLOB.machines) @@ -98,7 +81,7 @@ name = "Santa is coming to town! (Christmas)" holidayID = CHRISTMAS typepath = /datum/round_event/santa - weight = 150 + weight = 20 max_occurrences = 1 earliest_start = 20000 diff --git a/code/modules/holiday/holidays.dm b/code/modules/holiday/holidays.dm index 388a9d6893..85605fd2c4 100644 --- a/code/modules/holiday/holidays.dm +++ b/code/modules/holiday/holidays.dm @@ -387,9 +387,9 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and /datum/holiday/xmas name = CHRISTMAS - begin_day = 23 + begin_day = 22 begin_month = DECEMBER - end_day = 25 + end_day = 27 /datum/holiday/xmas/greet() return "Have a merry Christmas!" diff --git a/icons/obj/flora/pinetrees.dmi b/icons/obj/flora/pinetrees.dmi index e7fa58cb1a95b17e0c6c4151ec109fa299c2da72..a68e0388b08e29a8ab2ee1b3ee8ea684f778f98c 100644 GIT binary patch literal 42806 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 literal 36037 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 Date: Fri, 22 Dec 2017 15:14:27 -0600 Subject: [PATCH 96/96] Automatic changelog generation for PR #4491 [ci skip] --- html/changelogs/AutoChangeLog-pr-4491.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4491.yml diff --git a/html/changelogs/AutoChangeLog-pr-4491.yml b/html/changelogs/AutoChangeLog-pr-4491.yml new file mode 100644 index 0000000000..3076537362 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4491.yml @@ -0,0 +1,4 @@ +author: "Kor" +delete-after: True +changes: + - rscadd: "During Christmas you will be able to click on the tree in the Chapel to receive one present per round. That present can contain any item in the game."