diff --git a/SQL/database_changelog.txt b/SQL/database_changelog.txt index d0546da131..d28b33a8eb 100644 --- a/SQL/database_changelog.txt +++ b/SQL/database_changelog.txt @@ -1,3 +1,23 @@ +20 May 2017, by Jordie0608 + +Created table `round` to replace tracking of the datapoints 'round_start', 'round_end', 'server_ip', 'game_mode', 'round_end_results', 'end_error', 'end_proper', 'emergency_shuttle', 'map_name' and 'station_renames' in the `feedback` table. +Once created this table is populated with rows from the `feedback` table. + +START TRANSACTION; +CREATE TABLE `feedback`.`round` (`id` INT(11) NOT NULL AUTO_INCREMENT, `start_datetime` DATETIME NOT NULL, `end_datetime` DATETIME NULL, `server_ip` INT(10) UNSIGNED NOT NULL, `server_port` SMALLINT(5) UNSIGNED NOT NULL, `commit_hash` CHAR(40) NULL, `game_mode` VARCHAR(32) NULL, `game_mode_result` VARCHAR(64) NULL, `end_state` VARCHAR(64) NULL, `shuttle_name` VARCHAR(64) NULL, `map_name` VARCHAR(32) NULL, `station_name` VARCHAR(80) NULL, PRIMARY KEY (`id`)); +INSERT INTO `feedback`.`round` +(`id`, `start_datetime`, `end_datetime`, `server_ip`, `server_port`, `commit_hash`, `game_mode`, `game_mode_result`, `end_state`, `shuttle_name`, `map_name`, `station_name`) +SELECT DISTINCT ri.round_id, IFNULL(STR_TO_DATE(st.details,'%a %b %e %H:%i:%s %Y'), TIMESTAMP(0)), STR_TO_DATE(et.details,'%a %b %e %H:%i:%s %Y'), IFNULL(INET_ATON(SUBSTRING_INDEX(IF(si.details = '', '0', IF(SUBSTRING_INDEX(si.details, ':', 1) LIKE '%_._%', si.details, '0')), ':', 1)), INET_ATON(0)), IFNULL(IF(si.details LIKE '%:_%', CAST(SUBSTRING_INDEX(si.details, ':', -1) AS UNSIGNED), '0'), '0'), ch.details, gm.details, mr.details, IFNULL(es.details, ep.details), ss.details, mn.details, sn.details +FROM `feedback`.`feedback`AS ri +LEFT JOIN `feedback`.`feedback` AS st ON ri.round_id = st.round_id AND st.var_name = "round_start" LEFT JOIN `feedback`.`feedback` AS et ON ri.round_id = et.round_id AND et.var_name = "round_end" LEFT JOIN `feedback`.`feedback` AS si ON ri.round_id = si.round_id AND si.var_name = "server_ip" LEFT JOIN `feedback`.`feedback` AS ch ON ri.round_id = ch.round_id AND ch.var_name = "revision" LEFT JOIN `feedback`.`feedback` AS gm ON ri.round_id = gm.round_id AND gm.var_name = "game_mode" LEFT JOIN `feedback`.`feedback` AS mr ON ri.round_id = mr.round_id AND mr.var_name = "round_end_result" LEFT JOIN `feedback`.`feedback` AS es ON ri.round_id = es.round_id AND es.var_name = "end_state" LEFT JOIN `feedback`.`feedback` AS ep ON ri.round_id = ep.round_id AND ep.var_name = "end_proper" LEFT JOIN `feedback`.`feedback` AS ss ON ri.round_id = ss.round_id AND ss.var_name = "emergency_shuttle" LEFT JOIN `feedback`.`feedback` AS mn ON ri.round_id = mn.round_id AND mn.var_name = "map_name" LEFT JOIN `feedback`.`feedback` AS sn ON ri.round_id = sn.round_id AND sn.var_name = "station_renames"; +COMMIT; + +It's not necessary to delete the rows from the `feedback` table but henceforth these datapoints will be in the `round` table. + +Remember to add a prefix to the table names if you use them + +---------------------------------------------------- + 21 April 2017, by Jordie0608 Modified table 'player', adding the column 'accountjoindate', removing the column 'id' and making the column 'ckey' the primary key. diff --git a/SQL/tgstation_schema.sql b/SQL/tgstation_schema.sql index 73e2d465f3..46729fc9bb 100644 --- a/SQL/tgstation_schema.sql +++ b/SQL/tgstation_schema.sql @@ -362,6 +362,29 @@ CREATE TABLE `poll_vote` ( KEY `idx_pvote_optionid_ckey` (`optionid`,`ckey`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `round` +-- +DROP TABLE IF EXISTS `round`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `round` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `start_datetime` DATETIME NOT NULL, + `end_datetime` DATETIME NULL, + `server_ip` INT(10) UNSIGNED NOT NULL, + `server_port` SMALLINT(5) UNSIGNED NOT NULL, + `commit_hash` CHAR(40) NULL, + `game_mode` VARCHAR(32) NULL, + `game_mode_result` VARCHAR(64) NULL, + `end_state` VARCHAR(64) NULL, + `shuttle_name` VARCHAR(64) NULL, + `map_name` VARCHAR(32) NULL, + `station_name` VARCHAR(80) NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; diff --git a/SQL/tgstation_schema_prefixed.sql b/SQL/tgstation_schema_prefixed.sql index 4d74b9deaa..f717bf96ad 100644 --- a/SQL/tgstation_schema_prefixed.sql +++ b/SQL/tgstation_schema_prefixed.sql @@ -362,6 +362,29 @@ CREATE TABLE `SS13_poll_vote` ( KEY `idx_pvote_optionid_ckey` (`optionid`,`ckey`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `SS13_round` +-- +DROP TABLE IF EXISTS `SS13_round`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `SS13_round` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `start_datetime` DATETIME NOT NULL, + `end_datetime` DATETIME NULL, + `server_ip` INT(10) UNSIGNED NOT NULL, + `server_port` SMALLINT(5) UNSIGNED NOT NULL, + `commit_hash` CHAR(40) NULL, + `game_mode` VARCHAR(32) NULL, + `game_mode_result` VARCHAR(64) NULL, + `end_state` VARCHAR(64) NULL, + `shuttle_name` VARCHAR(64) NULL, + `map_name` VARCHAR(32) NULL, + `station_name` VARCHAR(80) NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 7303f0f33a..0858d6acdb 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -42,6 +42,7 @@ // Subsystems shutdown in the reverse of the order they initialize in // The numbers just define the ordering, they are meaningless otherwise. +#define INIT_ORDER_DBCORE 17 #define INIT_ORDER_SERVER_MAINT 16 #define INIT_ORDER_JOBS 15 #define INIT_ORDER_EVENTS 14 diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index f606a0d61a..46a963ee53 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -82,8 +82,6 @@ SUBSYSTEM_DEF(blackbox) add_details("radio_usage","PDA-[pda_msg_amt]") add_details("radio_usage","RC-[rc_msg_amt]") - set_details("round_end","[time2text(world.realtime)]") //This one MUST be the last one that gets set. - if (!SSdbcore.Connect()) return diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index cf3efc3bc3..b052b20f5d 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -1,7 +1,7 @@ SUBSYSTEM_DEF(dbcore) name = "Database" flags = SS_NO_INIT|SS_NO_FIRE - + init_order = INIT_ORDER_DBCORE var/const/FAILED_DB_CONNECTION_CUTOFF = 5 var/const/Default_Cursor = 0 @@ -30,6 +30,11 @@ SUBSYSTEM_DEF(dbcore) _db_con = SSdbcore._db_con /datum/controller/subsystem/dbcore/Shutdown() + //This is as close as we can get to the true round end before Disconnect() without changing where it's called, defeating the reason this is a subsystem + if(SSdbcore.Connect()) + var/sql_station_name = sanitizeSQL(station_name()) + var/datum/DBQuery/query_round_end = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (end_datetime, game_mode_result, end_state, station_name) VALUES (Now(), '[SSticker.mode_result]', '[SSticker.end_state]', '[sql_station_name]') WHERE id = [GLOB.round_id]") + query_round_end.Execute() if(IsConnected()) Disconnect() @@ -48,7 +53,7 @@ SUBSYSTEM_DEF(dbcore) if(failed_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect anymore. return FALSE - + if(!config.sql_enabled) return FALSE @@ -171,16 +176,16 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table var/_db_query /datum/DBQuery/New(sql_query, datum/controller/subsystem/dbcore/connection_handler, cursor_handler) - if(sql_query) + if(sql_query) sql = sql_query - if(connection_handler) + if(connection_handler) db_connection = connection_handler - if(cursor_handler) + if(cursor_handler) default_cursor = cursor_handler item = list() _db_query = _dm_db_new_query() -/datum/DBQuery/proc/Connect(datum/controller/subsystem/dbcore/connection_handler) +/datum/DBQuery/proc/Connect(datum/controller/subsystem/dbcore/connection_handler) db_connection = connection_handler /datum/DBQuery/proc/warn_execute() @@ -194,16 +199,16 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table if(!. && log_error) log_sql("[ErrorMsg()] | Query used: [sql]") -/datum/DBQuery/proc/NextRow() +/datum/DBQuery/proc/NextRow() return _dm_db_next_row(_db_query,item,conversions) /datum/DBQuery/proc/RowsAffected() return _dm_db_rows_affected(_db_query) -/datum/DBQuery/proc/RowCount() +/datum/DBQuery/proc/RowCount() return _dm_db_row_count(_db_query) -/datum/DBQuery/proc/ErrorMsg() +/datum/DBQuery/proc/ErrorMsg() return _dm_db_error_msg(_db_query) /datum/DBQuery/proc/Columns() @@ -232,11 +237,11 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table return db_connection.Quote(str) /datum/DBQuery/proc/SetConversion(column,conversion) - if(istext(column)) + if(istext(column)) column = columns.Find(column) - if(!conversions) + if(!conversions) conversions = list(column) - else if(conversions.len < column) + else if(conversions.len < column) conversions.len = column conversions[column] = conversion diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 0d1eaadc08..a26c0bd2cd 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -60,6 +60,8 @@ SUBSYSTEM_DEF(ticker) var/round_start_time = 0 var/list/round_start_events + var/mode_result = "undefined" + var/end_state = "undefined" var/modevoted = FALSE //Have we sent a vote for the gamemode? @@ -639,9 +641,9 @@ SUBSYSTEM_DEF(ticker) sleep(50) if(mode.station_was_nuked) - Reboot("Station destroyed by Nuclear Device.", "end_proper", "nuke") + Reboot("Station destroyed by Nuclear Device.", "nuke") else - Reboot("Round ended.", "end_proper", "proper completion") + Reboot("Round ended.", "proper completion") /datum/controller/subsystem/ticker/proc/send_tip_of_the_round() var/m @@ -842,7 +844,7 @@ SUBSYSTEM_DEF(ticker) C.Export("##action=load_rsc", round_end_sound) round_end_sound_sent = TRUE -/datum/controller/subsystem/ticker/proc/Reboot(reason, feedback_c, feedback_r, delay) +/datum/controller/subsystem/ticker/proc/Reboot(reason, end_string, delay) set waitfor = FALSE if(usr && !check_rights(R_SERVER, TRUE)) return @@ -864,7 +866,9 @@ SUBSYSTEM_DEF(ticker) to_chat(world, "Reboot was cancelled by an admin.") return - SSblackbox.set_details("[feedback_c]","[feedback_r]") + if(end_string) + end_state = end_string + log_game("Rebooting World. [reason]") diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index deea959c00..bdb129c867 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -137,7 +137,7 @@ SUBSYSTEM_DEF(vote) active_admins = 1 break if(!active_admins) - SSticker.Reboot("Restart vote successful.", "end_error", "restart vote") + SSticker.Reboot("Restart vote successful.", "restart vote") else to_chat(world, "Notice:Restart vote will not restart the server automatically because there are active admins on.") message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.") diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm index 47e2ce6a14..8ba6a2f125 100644 --- a/code/game/gamemodes/blob/blob_finish.dm +++ b/code/game/gamemodes/blob/blob_finish.dm @@ -20,7 +20,7 @@ if(round_converted) //So badmin blobs later don't step on the dead natural blobs metaphorical toes ..() if(blobwincount <= GLOB.blobs_legit.len) - SSblackbox.set_details("round_end_result","win - blob took over") + SSticker.mode_result = "win - blob took over" to_chat(world, "The blob has taken over the station!") to_chat(world, "The entire station was eaten by the Blob!") log_game("Blob mode completed with a blob victory.") @@ -28,7 +28,7 @@ SSticker.news_report = BLOB_WIN else if(station_was_nuked) - SSblackbox.set_details("round_end_result","halfwin - nuke") + SSticker.mode_result = "halfwin - nuke" to_chat(world, "Partial Win: The station has been destroyed!") to_chat(world, "Directive 7-12 has been successfully carried out, preventing the Blob from spreading.") log_game("Blob mode completed with a tie (station destroyed).") @@ -36,7 +36,7 @@ SSticker.news_report = BLOB_NUKE else if(!GLOB.blob_cores.len) - SSblackbox.set_details("round_end_result","loss - blob eliminated") + SSticker.mode_result = "loss - blob eliminated" to_chat(world, "The staff has won!") to_chat(world, "The alien organism has been eradicated from the station!") log_game("Blob mode completed with a crew victory.") diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 132c834f10..48e1ff1957 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -191,7 +191,7 @@ Credit where due: var/datum/game_mode/clockwork_cult/C = SSticker.mode if(C.check_clockwork_victory()) text += "Ratvar's servants have succeeded in fulfilling His goals!" - SSblackbox.set_details("round_end_result", "win - servants completed their objective (summon ratvar)") + SSticker.mode_result = "win - servants completed their objective (summon ratvar)" else var/half_victory = FALSE var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = locate() in GLOB.all_clockwork_objects @@ -200,10 +200,10 @@ Credit where due: if(half_victory) text += "The crew escaped before Ratvar could rise, but the gateway \ was successfully constructed!" - SSblackbox.set_details("round_end_result", "halfwin - servants constructed the gateway but their objective was not completed (summon ratvar)") + SSticker.mode_result = "halfwin - servants constructed the gateway but their objective was not completed (summon ratvar)" else text += "Ratvar's servants have failed!" - SSblackbox.set_details("round_end_result", "loss - servants failed their objective (summon ratvar)") + 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]" diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 5de8a39216..a58c4874dc 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -208,12 +208,10 @@ /datum/game_mode/cult/declare_completion() if(!check_cult_victory()) - SSblackbox.set_details("round_end_result","win - cult win") - SSblackbox.set_val("round_end_result",acolytes_survived) + SSticker.mode_result = "win - cult win" to_chat(world, "The cult has succeeded! Nar-sie has snuffed out another torch in the void!") else - SSblackbox.set_details("round_end_result","loss - staff stopped the cult") - SSblackbox.set_val("round_end_result",acolytes_survived) + 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 = "" @@ -257,22 +255,15 @@ /datum/game_mode/proc/datum_cult_completion() var/text = "" - var/acolytes_survived = 0 - for(var/datum/mind/cult_mind in cult) - if (cult_mind.current && cult_mind.current.stat != DEAD) - if(cult_mind.current.onCentcom() || cult_mind.current.onSyndieBase()) - acolytes_survived++ var/cult_fail = 0 cult_fail += eldergod if(!GLOB.sac_complete) cult_fail++ if(!cult_fail) - SSblackbox.set_details("round_end_result","win - cult win") - SSblackbox.set_val("round_end_result",acolytes_survived) + SSticker.mode_result = "win - cult win" to_chat(world, "The cult has succeeded! Nar-sie has snuffed out another torch in the void!") else - SSblackbox.set_details("round_end_result","loss - staff stopped the cult") - SSblackbox.set_val("round_end_result",acolytes_survived) + 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:" diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 0129197273..c57e9180f5 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -80,11 +80,17 @@ report = config.intercept addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME) - SSblackbox.set_details("round_start","[time2text(world.realtime)]") - if(SSticker && SSticker.mode) - SSblackbox.set_details("game_mode","[SSticker.mode]") - if(GLOB.revdata.commit) - SSblackbox.set_details("revision","[GLOB.revdata.commit]") + if(SSdbcore.Connect()) + var/sql + if(SSticker && SSticker.mode) + sql += "game_mode = '[SSticker.mode]'" + if(sql) + sql += ", " + if(GLOB.revdata.commit) + sql += "commit_hash = '[GLOB.revdata.commit]'" + if(sql) + var/datum/DBQuery/query_round_game_mode = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET [sql] WHERE id = [GLOB.round_id]") + query_round_game_mode.Execute() if(report) addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h)) generate_station_goals() diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index f32fc80d61..6606a0d871 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -288,12 +288,12 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/ return if(!winner) to_chat(world, "The station was [station_was_nuked ? "destroyed!" : "evacuated before a gang could claim it! The station wins!"]
") - SSblackbox.set_details("round_end_result","loss - gangs failed takeover") + SSticker.mode_result = "loss - gangs failed takeover" SSticker.news_report = GANG_LOSS else to_chat(world, "The [winner.name] Gang successfully performed a hostile takeover of the station!
") - SSblackbox.set_details("round_end_result","win - gang domination complete") + SSticker.mode_result = "win - gang domination complete" SSticker.news_report = GANG_TAKEOVER diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index 400b38309b..6d4a678913 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -50,8 +50,6 @@ else to_chat(world, "Nobody survived the meteor storm!") - SSblackbox.set_details("round_end_result","end - evacuation") - SSblackbox.set_val("round_end_result",survivors) - + SSticker.mode_result = "end - evacuation" ..() return 1 diff --git a/code/game/gamemodes/miniantags/monkey/monkey.dm b/code/game/gamemodes/miniantags/monkey/monkey.dm index f9ea8dcc2c..20ba54afc4 100644 --- a/code/game/gamemodes/miniantags/monkey/monkey.dm +++ b/code/game/gamemodes/miniantags/monkey/monkey.dm @@ -107,10 +107,8 @@ /datum/game_mode/monkey/declare_completion() if(check_monkey_victory()) - SSblackbox.set_details("round_end_result","win - monkey win") - SSblackbox.set_val("round_end_result",escaped_monkeys) + SSticker.mode_result = "win - monkey win" to_chat(world, "The monkeys have overthrown their captors! Eeek eeeek!!") else - SSblackbox.set_details("round_end_result","loss - staff stopped the monkeys") - SSblackbox.set_val("round_end_result",escaped_monkeys) + SSticker.mode_result = "loss - staff stopped the monkeys" to_chat(world, "The staff managed to contain the monkey infestation!") diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 6af3e86b7e..14a5ffcd5e 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -201,70 +201,70 @@ if(nuke_off_station == NUKE_SYNDICATE_BASE) - SSblackbox.set_details("round_end_result","loss - syndicate nuked - disk secured") + 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) - SSblackbox.set_details("round_end_result","win - syndicate nuke") + 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) - SSblackbox.set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time") + 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) - SSblackbox.set_details("round_end_result","halfwin - blew wrong station") + 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) - SSblackbox.set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time") + 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()) - SSblackbox.set_details("round_end_result","loss - evacuation - disk secured - syndi team 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) - SSblackbox.set_details("round_end_result","loss - evacuation - disk secured") + 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()) - SSblackbox.set_details("round_end_result","halfwin - evacuation - disk not secured") + 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) - SSblackbox.set_details("round_end_result","halfwin - detonation averted") + 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) - SSblackbox.set_details("round_end_result","halfwin - interrupted") + SSticker.mode_result = "halfwin - interrupted" to_chat(world, "Neutral Victory") to_chat(world, "Round was mysteriously interrupted!") diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 5964983b09..0cad439948 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -459,7 +459,7 @@ var/datum/game_mode/nuclear/NM = SSticker.mode NM.nukes_left -- if(!SSticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is - SSticker.Reboot("Station destroyed by Nuclear Device.", "end_error", "nuke - unhandled ending") + SSticker.Reboot("Station destroyed by Nuclear Device.", "nuke - unhandled ending") /* diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 7a31d1f3cd..5cfdb11087 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -345,13 +345,13 @@ ////////////////////////////////////////////////////////////////////// /datum/game_mode/revolution/declare_completion() if(finished == 1) - SSblackbox.set_details("round_end_result","win - heads killed") + 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) - SSblackbox.set_details("round_end_result","loss - rev heads killed") + SSticker.mode_result = "loss - rev heads killed" to_chat(world, "The heads of staff managed to stop the revolution!") SSticker.news_report = REVS_LOSE diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm index dd69d77b14..d8bf34c99e 100644 --- a/code/game/gamemodes/wizard/raginmages.dm +++ b/code/game/gamemodes/wizard/raginmages.dm @@ -133,7 +133,7 @@ /datum/game_mode/wizard/raginmages/declare_completion() if(finished) - SSblackbox.set_details("round_end_result","loss - wizard killed") + SSticker.mode_result = "loss - wizard killed" to_chat(world, "The crew has managed to hold off the wizard attack! The Space Wizards Federation has been taught a lesson they will not soon forget!") ..(1) diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 0d169e9024..ef8db43171 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -180,7 +180,7 @@ /datum/game_mode/wizard/declare_completion() if(finished) - SSblackbox.set_details("round_end_result","loss - wizard killed") + 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 diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index c426cf2b41..b89d219245 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1,826 +1,828 @@ -//////////////////////////////// -/proc/message_admins(msg) - msg = "ADMIN LOG: [msg]" - to_chat(GLOB.admins, msg) - -/proc/relay_msg_admins(msg) - msg = "RELAY: [msg]" - to_chat(GLOB.admins, msg) - - -///////////////////////////////////////////////////////////////////////////////////////////////Panels - -/datum/admins/proc/show_player_panel(mob/M in GLOB.mob_list) - set category = "Admin" - set name = "Show Player Panel" - set desc="Edit player (respawn, ban, heal, etc)" - - if(!check_rights()) - return - - if(!isobserver(usr)) - log_game("[key_name_admin(usr)] checked the player panel while in game.") - - if(!M) - to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.") - return - - var/body = "Options for [M.key]" - body += "Options panel for [M]" - if(M.client) - body += " played by [M.client] " - body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]" - - if(isnewplayer(M)) - body += " Hasn't Entered Game " - else - body += " \[Heal\] " - - if(M.client) - body += "
\[First Seen: [M.client.player_join_date]\]\[Byond account registered on: [M.client.account_join_date]\]" - body += "
Show related accounts by: " - body += "\[ CID | " - body += "IP \]" - - body += "

\[ " - body += "VV - " - body += "TP - " - body += "PM - " - body += "SM - " - body += "FLW - " - body += "LOGS\]
" - - body += "Mob type = [M.type]

" - - body += "Kick | " - body += "Ban | " - body += "Jobban | " - body += "Identity Ban | " - if(jobban_isbanned(M, "OOC")) - body+= "OOCBan | " - else - body+= "OOCBan | " - if(jobban_isbanned(M, "emote")) - body+= "EmoteBan | " - else - body+= "Emoteban | " - - body += "Notes | Messages | Watchlist | " - if(M.client) - body += "| Prison | " - body += "\ Send back to Lobby | " - var/muted = M.client.prefs.muted - body += "
Mute: " - body += "\[IC | " - body += "OOC | " - body += "PRAY | " - body += "ADMINHELP | " - body += "DEADCHAT\]" - body += "(toggle all)" - - body += "

" - body += "Jump to | " - body += "Get | " - body += "Send To" - - body += "

" - body += "Traitor panel | " - body += "Narrate to | " - body += "Subtle message | " - body += "Language Menu" - - if (M.client) - if(!isnewplayer(M)) - body += "

" - body += "Transformation:" - body += "
" - - //Human - if(ishuman(M)) - body += "Human | " - else - body += "Humanize | " - - //Monkey - if(ismonkey(M)) - body += "Monkeyized | " - else - body += "Monkeyize | " - - //Corgi - if(iscorgi(M)) - body += "Corgized | " - else - body += "Corgize | " - - //AI / Cyborg - if(isAI(M)) - body += "Is an AI " - else if(ishuman(M)) - body += "Make AI | " - body += "Make Robot | " - body += "Make Alien | " - body += "Make Slime | " - body += "Make Blob | " - - //Simple Animals - if(isanimal(M)) - body += "Re-Animalize | " - else - body += "Animalize | " - - body += "

" - body += "Rudimentary transformation:
These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.

" - body += "Observer | " - body += "\[ Alien: Drone, " - body += "Hunter, " - body += "Sentinel, " - body += "Praetorian, " - body += "Queen, " - body += "Larva \] " - body += "Human " - body += "\[ slime: Baby, " - body += "Adult \] " - body += "Monkey | " - body += "Cyborg | " - body += "Cat | " - body += "Runtime | " - body += "Corgi | " - body += "Ian | " - body += "Crab | " - body += "Coffee | " - //body += "Parrot | " - //body += "Poly | " - body += "\[ Construct: Juggernaut , " - body += "Artificer , " - body += "Wraith \] " - body += "Shade" - body += "
" - - if (M.client) - body += "

" - body += "Other actions:" - body += "
" - body += "Forcesay | " - body += "Thunderdome 1 | " - body += "Thunderdome 2 | " - body += "Thunderdome Admin | " - body += "Thunderdome Observer | " - - body += "
" - body += "" - - usr << browse(body, "window=adminplayeropts-\ref[M];size=550x515") - SSblackbox.add_details("admin_verb","Player Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/datum/admins/proc/access_news_network() //MARKER - set category = "Fun" - set name = "Access Newscaster Network" - set desc = "Allows you to view, add and edit news feeds." - - if (!istype(src,/datum/admins)) - src = usr.client.holder - if (!istype(src,/datum/admins)) - to_chat(usr, "Error: you are not an admin!") - return - var/dat - dat = text("Admin Newscaster

Admin Newscaster Unit

") - - switch(admincaster_screen) - if(0) - dat += "Welcome to the admin newscaster.
Here you can add, edit and censor every newspiece on the network." - dat += "
Feed channels and stories entered through here will be uneditable and handled as official news by the rest of the units." - dat += "
Note that this panel allows full freedom over the news network, there are no constrictions except the few basic ones. Don't break things!" - if(GLOB.news_network.wanted_issue.active) - dat+= "
Read Wanted Issue" - dat+= "

Create Feed Channel" - dat+= "
View Feed Channels" - dat+= "
Submit new Feed story" - dat+= "

Exit" - var/wanted_already = 0 - if(GLOB.news_network.wanted_issue.active) - wanted_already = 1 - dat+="
Feed Security functions:
" - dat+="
[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue" - dat+="
Censor Feed Stories" - dat+="
Mark Feed Channel with Nanotrasen D-Notice (disables and locks the channel)." - dat+="

The newscaster recognises you as:
[src.admin_signature]
" - if(1) - dat+= "Station Feed Channels
" - if( isemptylist(GLOB.news_network.network_channels) ) - dat+="No active channels found..." - else - for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) - if(CHANNEL.is_admin_channel) - dat+="[CHANNEL.channel_name]
" - else - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" - dat+="

Refresh" - dat+="
Back" - if(2) - dat+="Creating new Feed Channel..." - dat+="
Channel Name: [src.admincaster_feed_channel.channel_name]
" - dat+="Channel Author: [src.admin_signature]
" - dat+="Will Accept Public Feeds: [(src.admincaster_feed_channel.locked) ? ("NO") : ("YES")]

" - dat+="
Submit

Cancel
" - if(3) - dat+="Creating new Feed Message..." - dat+="
Receiving Channel: [src.admincaster_feed_channel.channel_name]
" //MARK - dat+="Message Author: [src.admin_signature]
" - dat+="Message Body: [src.admincaster_feed_message.returnBody(-1)]
" - dat+="
Submit

Cancel
" - if(4) - dat+="Feed story successfully submitted to [src.admincaster_feed_channel.channel_name].

" - dat+="
Return
" - if(5) - dat+="Feed Channel [src.admincaster_feed_channel.channel_name] created successfully.

" - dat+="
Return
" - if(6) - dat+="ERROR: Could not submit Feed story to Network.

" - if(src.admincaster_feed_channel.channel_name=="") - dat+="Invalid receiving channel name.
" - if(src.admincaster_feed_message.returnBody(-1) == "" || src.admincaster_feed_message.returnBody(-1) == "\[REDACTED\]") - dat+="Invalid message body.
" - dat+="
Return
" - if(7) - dat+="ERROR: Could not submit Feed Channel to Network.

" - if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]") - dat+="Invalid channel name.
" - var/check = 0 - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) - if(FC.channel_name == src.admincaster_feed_channel.channel_name) - check = 1 - break - if(check) - dat+="Channel name already in use.
" - dat+="
Return
" - if(9) - dat+="[admincaster_feed_channel.channel_name]: \[created by: [admincaster_feed_channel.returnAuthor(-1)]\]
" - if(src.admincaster_feed_channel.censored) - dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
" - dat+="No further feed story additions are allowed while the D-Notice is in effect.

" - else - if( isemptylist(src.admincaster_feed_channel.messages) ) - dat+="No feed messages found in channel...
" - else - var/i = 0 - for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages) - i++ - dat+="-[MESSAGE.returnBody(-1)]
" - if(MESSAGE.img) - usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png") - dat+="

" - dat+="\[Story by [MESSAGE.returnAuthor(-1)]\]
" - dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]:
" - for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments) - dat+="[comment.body]
[comment.author] [comment.time_stamp]
" - dat+="
" - dat+="

Refresh" - dat+="
Back" - if(10) - dat+="Nanotrasen Feed Censorship Tool
" - dat+="NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
" - dat+="Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.
" - dat+="
Select Feed channel to get Stories from:
" - if(isemptylist(GLOB.news_network.network_channels)) - dat+="No feed channels found active...
" - else - for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" - dat+="
Cancel" - if(11) - dat+="Nanotrasen D-Notice Handler
" - dat+="A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's" - dat+="morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed" - dat+="stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
" - if(isemptylist(GLOB.news_network.network_channels)) - dat+="No feed channels found active...
" - else - for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" - - dat+="
Back" - if(12) - dat+="[src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.returnAuthor(-1)] \]
" - dat+="[(src.admincaster_feed_channel.authorCensor) ? ("Undo Author censorship") : ("Censor channel Author")]
" - - if( isemptylist(src.admincaster_feed_channel.messages) ) - dat+="No feed messages found in channel...
" - else - for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages) - dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
" - dat+="[(MESSAGE.bodyCensor) ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.authorCensor) ? ("Undo Author Censorship") : ("Censor message Author")]
" - dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]: [MESSAGE.locked ? "Unlock" : "Lock"]
" - for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments) - dat+="[comment.body] X
[comment.author] [comment.time_stamp]
" - dat+="
Back" - if(13) - dat+="[src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.returnAuthor(-1)] \]
" - dat+="Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
" - if(src.admincaster_feed_channel.censored) - dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
" - dat+="No further feed story additions are allowed while the D-Notice is in effect.

" - else - if( isemptylist(src.admincaster_feed_channel.messages) ) - dat+="No feed messages found in channel...
" - else - for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages) - dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
" - dat+="
Back" - if(14) - dat+="Wanted Issue Handler:" - var/wanted_already = 0 - var/end_param = 1 - if(GLOB.news_network.wanted_issue.active) - wanted_already = 1 - end_param = 2 - if(wanted_already) - dat+="
A wanted issue is already in Feed Circulation. You can edit or cancel it below.
" - dat+="
" - dat+="Criminal Name: [src.admincaster_wanted_message.criminal]
" - dat+="Description: [src.admincaster_wanted_message.body]
" - if(wanted_already) - dat+="Wanted Issue created by:[GLOB.news_network.wanted_issue.scannedUser]
" - else - dat+="Wanted Issue will be created under prosecutor:[src.admin_signature]
" - dat+="
[(wanted_already) ? ("Edit Issue") : ("Submit")]" - if(wanted_already) - dat+="
Take down Issue" - dat+="
Cancel" - if(15) - dat+="Wanted issue for [src.admincaster_wanted_message.criminal] is now in Network Circulation.

" - dat+="
Return
" - if(16) - dat+="ERROR: Wanted Issue rejected by Network.

" - if(src.admincaster_wanted_message.criminal =="" || src.admincaster_wanted_message.criminal == "\[REDACTED\]") - dat+="Invalid name for person wanted.
" - if(src.admincaster_wanted_message.body == "" || src.admincaster_wanted_message.body == "\[REDACTED\]") - dat+="Invalid description.
" - dat+="
Return
" - if(17) - dat+="Wanted Issue successfully deleted from Circulation
" - dat+="
Return
" - if(18) - dat+="-- STATIONWIDE WANTED ISSUE --
\[Submitted by: [GLOB.news_network.wanted_issue.scannedUser]\]
" - dat+="Criminal: [GLOB.news_network.wanted_issue.criminal]
" - dat+="Description: [GLOB.news_network.wanted_issue.body]
" - dat+="Photo:: " - if(GLOB.news_network.wanted_issue.img) - usr << browse_rsc(GLOB.news_network.wanted_issue.img, "tmp_photow.png") - dat+="
" - else - dat+="None" - dat+="
Back
" - if(19) - dat+="Wanted issue for [src.admincaster_wanted_message.criminal] successfully edited.

" - dat+="
Return
" - else - dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" - - //to_chat(world, "Channelname: [src.admincaster_feed_channel.channel_name] [src.admincaster_feed_channel.author]") - //to_chat(world, "Msg: [src.admincaster_feed_message.author] [src.admincaster_feed_message.body]") - usr << browse(dat, "window=admincaster_main;size=400x600") - onclose(usr, "admincaster_main") - - -/datum/admins/proc/Game() - if(!check_rights(0)) - return - - var/dat = {" -
Game Panel

\n - Change Game Mode
- "} - if(GLOB.master_mode == "secret") - dat += "(Force Secret Mode)
" - - dat += {" -
- Create Object
- Quick Create Object
- Create Turf
- Create Mob
- "} - - if(marked_datum && istype(marked_datum, /atom)) - dat += "Duplicate Marked Datum
" - - usr << browse(dat, "window=admin2;size=210x200") - return - -/////////////////////////////////////////////////////////////////////////////////////////////////admins2.dm merge -//i.e. buttons/verbs - - -/datum/admins/proc/restart() - set category = "Server" - set name = "Reboot World" - set desc="Restarts the world immediately" - if (!usr.client.holder) - return - - var/list/options = list("Regular Restart", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)") - var result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options - if(result) - SSblackbox.add_details("admin_verb","Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - switch(result) - if("Regular Restart") - SSticker.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10) - if("Hard Restart (No Delay, No Feeback Reason)") - world.Reboot() - if("Hardest Restart (No actions, just reboot)") +//////////////////////////////// +/proc/message_admins(msg) + msg = "ADMIN LOG: [msg]" + to_chat(GLOB.admins, msg) + +/proc/relay_msg_admins(msg) + msg = "RELAY: [msg]" + to_chat(GLOB.admins, msg) + + +///////////////////////////////////////////////////////////////////////////////////////////////Panels + +/datum/admins/proc/show_player_panel(mob/M in GLOB.mob_list) + set category = "Admin" + set name = "Show Player Panel" + set desc="Edit player (respawn, ban, heal, etc)" + + if(!check_rights()) + return + + if(!isobserver(usr)) + log_game("[key_name_admin(usr)] checked the player panel while in game.") + + if(!M) + to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.") + return + + var/body = "Options for [M.key]" + body += "Options panel for [M]" + if(M.client) + body += " played by [M.client] " + body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]" + + if(isnewplayer(M)) + body += " Hasn't Entered Game " + else + body += " \[Heal\] " + + if(M.client) + body += "
\[First Seen: [M.client.player_join_date]\]\[Byond account registered on: [M.client.account_join_date]\]" + body += "
Show related accounts by: " + body += "\[ CID | " + body += "IP \]" + + body += "

\[ " + body += "VV - " + body += "TP - " + body += "PM - " + body += "SM - " + body += "FLW - " + body += "LOGS\]
" + + body += "Mob type = [M.type]

" + + body += "Kick | " + body += "Ban | " + body += "Jobban | " + body += "Identity Ban | " + if(jobban_isbanned(M, "OOC")) + body+= "OOCBan | " + else + body+= "OOCBan | " + if(jobban_isbanned(M, "emote")) + body+= "EmoteBan | " + else + body+= "Emoteban | " + + body += "Notes | Messages | Watchlist | " + if(M.client) + body += "| Prison | " + body += "\ Send back to Lobby | " + var/muted = M.client.prefs.muted + body += "
Mute: " + body += "\[IC | " + body += "OOC | " + body += "PRAY | " + body += "ADMINHELP | " + body += "DEADCHAT\]" + body += "(toggle all)" + + body += "

" + body += "Jump to | " + body += "Get | " + body += "Send To" + + body += "

" + body += "Traitor panel | " + body += "Narrate to | " + body += "Subtle message | " + body += "Language Menu" + + if (M.client) + if(!isnewplayer(M)) + body += "

" + body += "Transformation:" + body += "
" + + //Human + if(ishuman(M)) + body += "Human | " + else + body += "Humanize | " + + //Monkey + if(ismonkey(M)) + body += "Monkeyized | " + else + body += "Monkeyize | " + + //Corgi + if(iscorgi(M)) + body += "Corgized | " + else + body += "Corgize | " + + //AI / Cyborg + if(isAI(M)) + body += "Is an AI " + else if(ishuman(M)) + body += "Make AI | " + body += "Make Robot | " + body += "Make Alien | " + body += "Make Slime | " + body += "Make Blob | " + + //Simple Animals + if(isanimal(M)) + body += "Re-Animalize | " + else + body += "Animalize | " + + body += "

" + body += "Rudimentary transformation:
These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.

" + body += "Observer | " + body += "\[ Alien: Drone, " + body += "Hunter, " + body += "Sentinel, " + body += "Praetorian, " + body += "Queen, " + body += "Larva \] " + body += "Human " + body += "\[ slime: Baby, " + body += "Adult \] " + body += "Monkey | " + body += "Cyborg | " + body += "Cat | " + body += "Runtime | " + body += "Corgi | " + body += "Ian | " + body += "Crab | " + body += "Coffee | " + //body += "Parrot | " + //body += "Poly | " + body += "\[ Construct: Juggernaut , " + body += "Artificer , " + body += "Wraith \] " + body += "Shade" + body += "
" + + if (M.client) + body += "

" + body += "Other actions:" + body += "
" + body += "Forcesay | " + body += "Thunderdome 1 | " + body += "Thunderdome 2 | " + body += "Thunderdome Admin | " + body += "Thunderdome Observer | " + + body += "
" + body += "" + + usr << browse(body, "window=adminplayeropts-\ref[M];size=550x515") + SSblackbox.add_details("admin_verb","Player Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/datum/admins/proc/access_news_network() //MARKER + set category = "Fun" + set name = "Access Newscaster Network" + set desc = "Allows you to view, add and edit news feeds." + + if (!istype(src,/datum/admins)) + src = usr.client.holder + if (!istype(src,/datum/admins)) + to_chat(usr, "Error: you are not an admin!") + return + var/dat + dat = text("Admin Newscaster

Admin Newscaster Unit

") + + switch(admincaster_screen) + if(0) + dat += "Welcome to the admin newscaster.
Here you can add, edit and censor every newspiece on the network." + dat += "
Feed channels and stories entered through here will be uneditable and handled as official news by the rest of the units." + dat += "
Note that this panel allows full freedom over the news network, there are no constrictions except the few basic ones. Don't break things!" + if(GLOB.news_network.wanted_issue.active) + dat+= "
Read Wanted Issue" + dat+= "

Create Feed Channel" + dat+= "
View Feed Channels" + dat+= "
Submit new Feed story" + dat+= "

Exit" + var/wanted_already = 0 + if(GLOB.news_network.wanted_issue.active) + wanted_already = 1 + dat+="
Feed Security functions:
" + dat+="
[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue" + dat+="
Censor Feed Stories" + dat+="
Mark Feed Channel with Nanotrasen D-Notice (disables and locks the channel)." + dat+="

The newscaster recognises you as:
[src.admin_signature]
" + if(1) + dat+= "Station Feed Channels
" + if( isemptylist(GLOB.news_network.network_channels) ) + dat+="No active channels found..." + else + for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) + if(CHANNEL.is_admin_channel) + dat+="[CHANNEL.channel_name]
" + else + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" + dat+="

Refresh" + dat+="
Back" + if(2) + dat+="Creating new Feed Channel..." + dat+="
Channel Name: [src.admincaster_feed_channel.channel_name]
" + dat+="Channel Author: [src.admin_signature]
" + dat+="Will Accept Public Feeds: [(src.admincaster_feed_channel.locked) ? ("NO") : ("YES")]

" + dat+="
Submit

Cancel
" + if(3) + dat+="Creating new Feed Message..." + dat+="
Receiving Channel: [src.admincaster_feed_channel.channel_name]
" //MARK + dat+="Message Author: [src.admin_signature]
" + dat+="Message Body: [src.admincaster_feed_message.returnBody(-1)]
" + dat+="
Submit

Cancel
" + if(4) + dat+="Feed story successfully submitted to [src.admincaster_feed_channel.channel_name].

" + dat+="
Return
" + if(5) + dat+="Feed Channel [src.admincaster_feed_channel.channel_name] created successfully.

" + dat+="
Return
" + if(6) + dat+="ERROR: Could not submit Feed story to Network.

" + if(src.admincaster_feed_channel.channel_name=="") + dat+="Invalid receiving channel name.
" + if(src.admincaster_feed_message.returnBody(-1) == "" || src.admincaster_feed_message.returnBody(-1) == "\[REDACTED\]") + dat+="Invalid message body.
" + dat+="
Return
" + if(7) + dat+="ERROR: Could not submit Feed Channel to Network.

" + if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]") + dat+="Invalid channel name.
" + var/check = 0 + for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + if(FC.channel_name == src.admincaster_feed_channel.channel_name) + check = 1 + break + if(check) + dat+="Channel name already in use.
" + dat+="
Return
" + if(9) + dat+="[admincaster_feed_channel.channel_name]: \[created by: [admincaster_feed_channel.returnAuthor(-1)]\]
" + if(src.admincaster_feed_channel.censored) + dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
" + dat+="No further feed story additions are allowed while the D-Notice is in effect.

" + else + if( isemptylist(src.admincaster_feed_channel.messages) ) + dat+="No feed messages found in channel...
" + else + var/i = 0 + for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages) + i++ + dat+="-[MESSAGE.returnBody(-1)]
" + if(MESSAGE.img) + usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png") + dat+="

" + dat+="\[Story by [MESSAGE.returnAuthor(-1)]\]
" + dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]:
" + for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments) + dat+="[comment.body]
[comment.author] [comment.time_stamp]
" + dat+="
" + dat+="

Refresh" + dat+="
Back" + if(10) + dat+="Nanotrasen Feed Censorship Tool
" + dat+="NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
" + dat+="Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.
" + dat+="
Select Feed channel to get Stories from:
" + if(isemptylist(GLOB.news_network.network_channels)) + dat+="No feed channels found active...
" + else + for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" + dat+="
Cancel" + if(11) + dat+="Nanotrasen D-Notice Handler
" + dat+="A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's" + dat+="morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed" + dat+="stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
" + if(isemptylist(GLOB.news_network.network_channels)) + dat+="No feed channels found active...
" + else + for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" + + dat+="
Back" + if(12) + dat+="[src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.returnAuthor(-1)] \]
" + dat+="[(src.admincaster_feed_channel.authorCensor) ? ("Undo Author censorship") : ("Censor channel Author")]
" + + if( isemptylist(src.admincaster_feed_channel.messages) ) + dat+="No feed messages found in channel...
" + else + for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages) + dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
" + dat+="[(MESSAGE.bodyCensor) ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.authorCensor) ? ("Undo Author Censorship") : ("Censor message Author")]
" + dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]: [MESSAGE.locked ? "Unlock" : "Lock"]
" + for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments) + dat+="[comment.body] X
[comment.author] [comment.time_stamp]
" + dat+="
Back" + if(13) + dat+="[src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.returnAuthor(-1)] \]
" + dat+="Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
" + if(src.admincaster_feed_channel.censored) + dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
" + dat+="No further feed story additions are allowed while the D-Notice is in effect.

" + else + if( isemptylist(src.admincaster_feed_channel.messages) ) + dat+="No feed messages found in channel...
" + else + for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages) + dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
" + dat+="
Back" + if(14) + dat+="Wanted Issue Handler:" + var/wanted_already = 0 + var/end_param = 1 + if(GLOB.news_network.wanted_issue.active) + wanted_already = 1 + end_param = 2 + if(wanted_already) + dat+="
A wanted issue is already in Feed Circulation. You can edit or cancel it below.
" + dat+="
" + dat+="Criminal Name: [src.admincaster_wanted_message.criminal]
" + dat+="Description: [src.admincaster_wanted_message.body]
" + if(wanted_already) + dat+="Wanted Issue created by:[GLOB.news_network.wanted_issue.scannedUser]
" + else + dat+="Wanted Issue will be created under prosecutor:[src.admin_signature]
" + dat+="
[(wanted_already) ? ("Edit Issue") : ("Submit")]" + if(wanted_already) + dat+="
Take down Issue" + dat+="
Cancel" + if(15) + dat+="Wanted issue for [src.admincaster_wanted_message.criminal] is now in Network Circulation.

" + dat+="
Return
" + if(16) + dat+="ERROR: Wanted Issue rejected by Network.

" + if(src.admincaster_wanted_message.criminal =="" || src.admincaster_wanted_message.criminal == "\[REDACTED\]") + dat+="Invalid name for person wanted.
" + if(src.admincaster_wanted_message.body == "" || src.admincaster_wanted_message.body == "\[REDACTED\]") + dat+="Invalid description.
" + dat+="
Return
" + if(17) + dat+="Wanted Issue successfully deleted from Circulation
" + dat+="
Return
" + if(18) + dat+="-- STATIONWIDE WANTED ISSUE --
\[Submitted by: [GLOB.news_network.wanted_issue.scannedUser]\]
" + dat+="Criminal: [GLOB.news_network.wanted_issue.criminal]
" + dat+="Description: [GLOB.news_network.wanted_issue.body]
" + dat+="Photo:: " + if(GLOB.news_network.wanted_issue.img) + usr << browse_rsc(GLOB.news_network.wanted_issue.img, "tmp_photow.png") + dat+="
" + else + dat+="None" + dat+="
Back
" + if(19) + dat+="Wanted issue for [src.admincaster_wanted_message.criminal] successfully edited.

" + dat+="
Return
" + else + dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" + + //to_chat(world, "Channelname: [src.admincaster_feed_channel.channel_name] [src.admincaster_feed_channel.author]") + //to_chat(world, "Msg: [src.admincaster_feed_message.author] [src.admincaster_feed_message.body]") + usr << browse(dat, "window=admincaster_main;size=400x600") + onclose(usr, "admincaster_main") + + +/datum/admins/proc/Game() + if(!check_rights(0)) + return + + var/dat = {" +
Game Panel

\n + Change Game Mode
+ "} + if(GLOB.master_mode == "secret") + dat += "(Force Secret Mode)
" + + dat += {" +
+ Create Object
+ Quick Create Object
+ Create Turf
+ Create Mob
+ "} + + if(marked_datum && istype(marked_datum, /atom)) + dat += "Duplicate Marked Datum
" + + usr << browse(dat, "window=admin2;size=210x200") + return + +/////////////////////////////////////////////////////////////////////////////////////////////////admins2.dm merge +//i.e. buttons/verbs + + +/datum/admins/proc/restart() + set category = "Server" + set name = "Reboot World" + set desc="Restarts the world immediately" + if (!usr.client.holder) + return + + var/list/options = list("Regular Restart", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)") + var result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options + if(result) + SSblackbox.add_details("admin_verb","Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + switch(result) + if("Regular Restart") + SSticker.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10) + if("Hard Restart (No Delay, No Feeback Reason)") + world.Reboot() + if("Hardest Restart (No actions, just reboot)") + world.Reboot(fast_track = TRUE) - -/datum/admins/proc/end_round() - set category = "Server" - set name = "End Round" - set desc = "Attempts to produce a round end report and then restart the server organically." - - if (!usr.client.holder) - return - var/confirm = alert("End the round and restart the game world?", "End Round", "Yes", "Cancel") - if(confirm == "Cancel") - return - if(confirm == "Yes") - SSticker.force_ending = 1 - SSblackbox.add_details("admin_verb","End Round") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/datum/admins/proc/announce() - set category = "Special Verbs" - set name = "Announce" - set desc="Announce your desires to the world" - if(!check_rights(0)) - return - - var/message = input("Global message to send:", "Admin Announce", null, null) as message - if(message) - if(!check_rights(R_SERVER,0)) - message = adminscrub(message,500) - to_chat(world, "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n \t [message]") - log_admin("Announce: [key_name(usr)] : [message]") - SSblackbox.add_details("admin_verb","Announce") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/set_admin_notice() - set category = "Special Verbs" - set name = "Set Admin Notice" - set desc ="Set an announcement that appears to everyone who joins the server. Only lasts this round" - if(!check_rights(0)) - return - - var/new_admin_notice = input(src,"Set a public notice for this round. Everyone who joins the server will see it.\n(Leaving it blank will delete the current notice):","Set Notice",GLOB.admin_notice) as message|null - if(new_admin_notice == null) - return - if(new_admin_notice == GLOB.admin_notice) - return - if(new_admin_notice == "") - message_admins("[key_name(usr)] removed the admin notice.") - log_admin("[key_name(usr)] removed the admin notice:\n[GLOB.admin_notice]") - else - message_admins("[key_name(usr)] set the admin notice.") - log_admin("[key_name(usr)] set the admin notice:\n[new_admin_notice]") - to_chat(world, "Admin Notice:\n \t [new_admin_notice]") - SSblackbox.add_details("admin_verb","Set Admin Notice") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - GLOB.admin_notice = new_admin_notice - return - -/datum/admins/proc/toggleooc() - set category = "Server" - set desc="Toggle dis bitch" - set name="Toggle OOC" - toggle_ooc() - log_admin("[key_name(usr)] toggled OOC.") - message_admins("[key_name_admin(usr)] toggled OOC.") - SSblackbox.add_details("admin_toggle","Toggle OOC|[GLOB.ooc_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggleoocdead() - set category = "Server" - set desc="Toggle dis bitch" - set name="Toggle Dead OOC" - GLOB.dooc_allowed = !( GLOB.dooc_allowed ) - - log_admin("[key_name(usr)] toggled OOC.") - message_admins("[key_name_admin(usr)] toggled Dead OOC.") - SSblackbox.add_details("admin_toggle","Toggle Dead OOC|[GLOB.dooc_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/startnow() - set category = "Server" - set desc="Start the round RIGHT NOW" - set name="Start Now" - if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP) - SSticker.start_immediately = TRUE - log_admin("[usr.key] has started the game.") - var/msg = "" - if(SSticker.current_state == GAME_STATE_STARTUP) - msg = " (The server is still setting up, but the round will be \ - started as soon as possible.)" - message_admins("\ - [usr.key] has started the game.[msg]") - SSblackbox.add_details("admin_verb","Start Now") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return 1 - else - to_chat(usr, "Error: Start Now: Game has already started.") - - return 0 - -/datum/admins/proc/toggleenter() - set category = "Server" - set desc="People can't enter" - set name="Toggle Entering" - GLOB.enter_allowed = !( GLOB.enter_allowed ) - if (!( GLOB.enter_allowed )) - to_chat(world, "New players may no longer enter the game.") - else - to_chat(world, "New players may now enter the game.") - log_admin("[key_name(usr)] toggled new player game entering.") - message_admins("[key_name_admin(usr)] toggled new player game entering.") - world.update_status() - SSblackbox.add_details("admin_toggle","Toggle Entering|[GLOB.enter_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggleAI() - set category = "Server" - set desc="People can't be AI" - set name="Toggle AI" - config.allow_ai = !( config.allow_ai ) - if (!( config.allow_ai )) - to_chat(world, "The AI job is no longer chooseable.") - else - to_chat(world, "The AI job is chooseable now.") - log_admin("[key_name(usr)] toggled AI allowed.") - world.update_status() - SSblackbox.add_details("admin_toggle","Toggle AI|[config.allow_ai]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggleaban() - set category = "Server" - set desc="Respawn basically" - set name="Toggle Respawn" - GLOB.abandon_allowed = !( GLOB.abandon_allowed ) - if (GLOB.abandon_allowed) - to_chat(world, "You may now respawn.") - else - to_chat(world, "You may no longer respawn :(") - message_admins("[key_name_admin(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].") - log_admin("[key_name(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].") - world.update_status() - SSblackbox.add_details("admin_toggle","Toggle Respawn|[GLOB.abandon_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/delay() - set category = "Server" - set desc="Delay the game start" - set name="Delay pre-game" - - var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(SSticker.GetTimeLeft()/10)) as num|null - if(SSticker.current_state > GAME_STATE_PREGAME) - return alert("Too late... The game has already started!") - if(newtime) - SSticker.SetTimeLeft(newtime * 10) - if(newtime < 0) - to_chat(world, "The game start has been delayed.") - log_admin("[key_name(usr)] delayed the round start.") - else - to_chat(world, "The game will start in [newtime] seconds.") - world << 'sound/ai/attention.ogg' - log_admin("[key_name(usr)] set the pre-game delay to [newtime] seconds.") - SSblackbox.add_details("admin_verb","Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/unprison(mob/M in GLOB.mob_list) - set category = "Admin" - set name = "Unprison" - if (M.z == ZLEVEL_CENTCOM) - M.loc = pick(GLOB.latejoin) - message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]") - log_admin("[key_name(usr)] has unprisoned [key_name(M)]") - else - alert("[M.name] is not prisoned.") - SSblackbox.add_details("admin_verb","Unprison") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS - -/* -/datum/admins/proc/get_sab_desc(var/target) - switch(target) - if(1) - return "Destroy at least 70% of the plasma canisters on the station" - if(2) - return "Destroy the AI" - if(3) - var/count = 0 - for(var/mob/living/carbon/monkey/Monkey in world) + +/datum/admins/proc/end_round() + set category = "Server" + set name = "End Round" + set desc = "Attempts to produce a round end report and then restart the server organically." + + if (!usr.client.holder) + return + var/confirm = alert("End the round and restart the game world?", "End Round", "Yes", "Cancel") + if(confirm == "Cancel") + return + if(confirm == "Yes") + SSticker.force_ending = 1 + SSblackbox.add_details("admin_verb","End Round") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/datum/admins/proc/announce() + set category = "Special Verbs" + set name = "Announce" + set desc="Announce your desires to the world" + if(!check_rights(0)) + return + + var/message = input("Global message to send:", "Admin Announce", null, null) as message + if(message) + if(!check_rights(R_SERVER,0)) + message = adminscrub(message,500) + to_chat(world, "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n \t [message]") + log_admin("Announce: [key_name(usr)] : [message]") + SSblackbox.add_details("admin_verb","Announce") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/set_admin_notice() + set category = "Special Verbs" + set name = "Set Admin Notice" + set desc ="Set an announcement that appears to everyone who joins the server. Only lasts this round" + if(!check_rights(0)) + return + + var/new_admin_notice = input(src,"Set a public notice for this round. Everyone who joins the server will see it.\n(Leaving it blank will delete the current notice):","Set Notice",GLOB.admin_notice) as message|null + if(new_admin_notice == null) + return + if(new_admin_notice == GLOB.admin_notice) + return + if(new_admin_notice == "") + message_admins("[key_name(usr)] removed the admin notice.") + log_admin("[key_name(usr)] removed the admin notice:\n[GLOB.admin_notice]") + else + message_admins("[key_name(usr)] set the admin notice.") + log_admin("[key_name(usr)] set the admin notice:\n[new_admin_notice]") + to_chat(world, "Admin Notice:\n \t [new_admin_notice]") + SSblackbox.add_details("admin_verb","Set Admin Notice") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + GLOB.admin_notice = new_admin_notice + return + +/datum/admins/proc/toggleooc() + set category = "Server" + set desc="Toggle dis bitch" + set name="Toggle OOC" + toggle_ooc() + log_admin("[key_name(usr)] toggled OOC.") + message_admins("[key_name_admin(usr)] toggled OOC.") + SSblackbox.add_details("admin_toggle","Toggle OOC|[GLOB.ooc_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggleoocdead() + set category = "Server" + set desc="Toggle dis bitch" + set name="Toggle Dead OOC" + GLOB.dooc_allowed = !( GLOB.dooc_allowed ) + + log_admin("[key_name(usr)] toggled OOC.") + message_admins("[key_name_admin(usr)] toggled Dead OOC.") + SSblackbox.add_details("admin_toggle","Toggle Dead OOC|[GLOB.dooc_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/startnow() + set category = "Server" + set desc="Start the round RIGHT NOW" + set name="Start Now" + if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP) + SSticker.start_immediately = TRUE + log_admin("[usr.key] has started the game.") + var/msg = "" + if(SSticker.current_state == GAME_STATE_STARTUP) + msg = " (The server is still setting up, but the round will be \ + started as soon as possible.)" + message_admins("\ + [usr.key] has started the game.[msg]") + SSblackbox.add_details("admin_verb","Start Now") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return 1 + else + to_chat(usr, "Error: Start Now: Game has already started.") + + return 0 + +/datum/admins/proc/toggleenter() + set category = "Server" + set desc="People can't enter" + set name="Toggle Entering" + GLOB.enter_allowed = !( GLOB.enter_allowed ) + if (!( GLOB.enter_allowed )) + to_chat(world, "New players may no longer enter the game.") + else + to_chat(world, "New players may now enter the game.") + log_admin("[key_name(usr)] toggled new player game entering.") + message_admins("[key_name_admin(usr)] toggled new player game entering.") + world.update_status() + SSblackbox.add_details("admin_toggle","Toggle Entering|[GLOB.enter_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggleAI() + set category = "Server" + set desc="People can't be AI" + set name="Toggle AI" + config.allow_ai = !( config.allow_ai ) + if (!( config.allow_ai )) + to_chat(world, "The AI job is no longer chooseable.") + else + to_chat(world, "The AI job is chooseable now.") + log_admin("[key_name(usr)] toggled AI allowed.") + world.update_status() + SSblackbox.add_details("admin_toggle","Toggle AI|[config.allow_ai]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggleaban() + set category = "Server" + set desc="Respawn basically" + set name="Toggle Respawn" + GLOB.abandon_allowed = !( GLOB.abandon_allowed ) + if (GLOB.abandon_allowed) + to_chat(world, "You may now respawn.") + else + to_chat(world, "You may no longer respawn :(") + message_admins("[key_name_admin(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].") + log_admin("[key_name(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].") + world.update_status() + SSblackbox.add_details("admin_toggle","Toggle Respawn|[GLOB.abandon_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/delay() + set category = "Server" + set desc="Delay the game start" + set name="Delay pre-game" + + var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(SSticker.GetTimeLeft()/10)) as num|null + if(SSticker.current_state > GAME_STATE_PREGAME) + return alert("Too late... The game has already started!") + if(newtime) + SSticker.SetTimeLeft(newtime * 10) + if(newtime < 0) + to_chat(world, "The game start has been delayed.") + log_admin("[key_name(usr)] delayed the round start.") + else + to_chat(world, "The game will start in [newtime] seconds.") + world << 'sound/ai/attention.ogg' + log_admin("[key_name(usr)] set the pre-game delay to [newtime] seconds.") + SSblackbox.add_details("admin_verb","Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/unprison(mob/M in GLOB.mob_list) + set category = "Admin" + set name = "Unprison" + if (M.z == ZLEVEL_CENTCOM) + M.loc = pick(GLOB.latejoin) + message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]") + log_admin("[key_name(usr)] has unprisoned [key_name(M)]") + else + alert("[M.name] is not prisoned.") + SSblackbox.add_details("admin_verb","Unprison") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS + +/* +/datum/admins/proc/get_sab_desc(var/target) + switch(target) + if(1) + return "Destroy at least 70% of the plasma canisters on the station" + if(2) + return "Destroy the AI" + if(3) + var/count = 0 + for(var/mob/living/carbon/monkey/Monkey in world) if(Monkey.z == ZLEVEL_STATION) - count++ - return "Kill all [count] of the monkeys on the station" - if(4) - return "Cut power to at least 80% of the station" - else - return "Error: Invalid sabotage target: [target]" -*/ -/datum/admins/proc/spawn_atom(object as text) - set category = "Debug" - set desc = "(atom path) Spawn an atom" - set name = "Spawn" - - if(!check_rights(R_SPAWN)) - return - - var/chosen = pick_closest_path(object) - if(!chosen) - return - if(ispath(chosen,/turf)) - var/turf/T = get_turf(usr.loc) - T.ChangeTurf(chosen) - else - var/atom/A = new chosen(usr.loc) - A.admin_spawned = TRUE - - log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") - SSblackbox.add_details("admin_verb","Spawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/datum/admins/proc/show_traitor_panel(mob/M in GLOB.mob_list) - set category = "Admin" - set desc = "Edit mobs's memory and role" - set name = "Show Traitor Panel" - - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - if(!M.mind) - to_chat(usr, "This mob has no mind!") - return - - M.mind.edit_memory() - SSblackbox.add_details("admin_verb","Traitor Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/datum/admins/proc/toggletintedweldhelmets() - set category = "Debug" - set desc="Reduces view range when wearing welding helmets" - set name="Toggle tinted welding helmes" - GLOB.tinted_weldhelh = !( GLOB.tinted_weldhelh ) - if (GLOB.tinted_weldhelh) - to_chat(world, "The tinted_weldhelh has been enabled!") - else - to_chat(world, "The tinted_weldhelh has been disabled!") - log_admin("[key_name(usr)] toggled tinted_weldhelh.") - message_admins("[key_name_admin(usr)] toggled tinted_weldhelh.") - SSblackbox.add_details("admin_toggle","Toggle Tinted Welding Helmets|[GLOB.tinted_weldhelh]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggleguests() - set category = "Server" - set desc="Guests can't enter" - set name="Toggle guests" - GLOB.guests_allowed = !( GLOB.guests_allowed ) - if (!( GLOB.guests_allowed )) - to_chat(world, "Guests may no longer enter the game.") - else - to_chat(world, "Guests may now enter the game.") - log_admin("[key_name(usr)] toggled guests game entering [GLOB.guests_allowed?"":"dis"]allowed.") - message_admins("[key_name_admin(usr)] toggled guests game entering [GLOB.guests_allowed?"":"dis"]allowed.") - SSblackbox.add_details("admin_toggle","Toggle Guests|[GLOB.guests_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/output_ai_laws() - var/ai_number = 0 - for(var/mob/living/silicon/S in GLOB.mob_list) - ai_number++ - if(isAI(S)) - to_chat(usr, "AI [key_name(S, usr)]'s laws:") - else if(iscyborg(S)) - var/mob/living/silicon/robot/R = S - to_chat(usr, "CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independant)"]: laws:") - else if (ispAI(S)) - to_chat(usr, "pAI [key_name(S, usr)]'s laws:") - else - to_chat(usr, "SOMETHING SILICON [key_name(S, usr)]'s laws:") - - if (S.laws == null) - to_chat(usr, "[key_name(S, usr)]'s laws are null?? Contact a coder.") - else - S.laws.show_laws(usr) - if(!ai_number) - to_chat(usr, "No AIs located" ) - -/datum/admins/proc/output_all_devil_info() - var/devil_number = 0 - for(var/D in SSticker.mode.devils) - devil_number++ - to_chat(usr, "Devil #[devil_number]:

" + SSticker.mode.printdevilinfo(D)) - 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.mind)) - else - to_chat(usr, "[M] is not a devil.") - -/datum/admins/proc/manage_free_slots() - if(!check_rights()) - return - var/dat = "Manage Free Slots" - var/count = 0 - - if(SSticker && !SSticker.mode) - alert(usr, "You cannot manage jobs before the round starts!") - return - - if(SSjob) - for(var/datum/job/job in SSjob.occupations) - count++ - var/J_title = html_encode(job.title) - var/J_opPos = html_encode(job.total_positions - (job.total_positions - job.current_positions)) - var/J_totPos = html_encode(job.total_positions) - if(job.total_positions < 0) - dat += "[J_title]: [J_opPos] (unlimited)" - else - dat += "[J_title]: [J_opPos]/[J_totPos]" - - if(job.title == "AI" || job.title == "Cyborg") - dat += " (Cannot Late Join)
" - continue - if(job.total_positions >= 0) - dat += " Add | " - if(job.total_positions > job.current_positions) - dat += "Remove | " - else - dat += "Remove | " - dat += "Unlimit" - else - dat += " Limit" - dat += "
" - - dat += "" - var/winheight = 100 + (count * 20) - winheight = min(winheight, 690) - usr << browse(dat, "window=players;size=375x[winheight]") - -// -// -//ALL DONE -//********************************************************************************************************* -//TO-DO: -// -// - -//RIP ferry snowflakes - -//Kicks all the clients currently in the lobby. The second parameter (kick_only_afk) determins if an is_afk() check is ran, or if all clients are kicked -//defaults to kicking everyone (afk + non afk clients in the lobby) -//returns a list of ckeys of the kicked clients -/proc/kick_clients_in_lobby(message, kick_only_afk = 0) - var/list/kicked_client_names = list() - for(var/client/C in GLOB.clients) - if(isnewplayer(C.mob)) - if(kick_only_afk && !C.is_afk()) //Ignore clients who are not afk - continue - if(message) - to_chat(C, message) - kicked_client_names.Add("[C.ckey]") - qdel(C) - return kicked_client_names - -//returns 1 to let the dragdrop code know we are trapping this event -//returns 0 if we don't plan to trap the event -/datum/admins/proc/cmd_ghost_drag(mob/dead/observer/frommob, mob/living/tomob) - - //this is the exact two check rights checks required to edit a ckey with vv. - if (!check_rights(R_VAREDIT,0) || !check_rights(R_SPAWN|R_DEBUG,0)) - return 0 - - if (!frommob.ckey) - return 0 - - var/question = "" - if (tomob.ckey) - question = "This mob already has a user ([tomob.key]) in control of it! " - question += "Are you sure you want to place [frommob.name]([frommob.key]) in control of [tomob.name]?" - - var/ask = alert(question, "Place ghost in control of mob?", "Yes", "No") - if (ask != "Yes") - return 1 - - if (!frommob || !tomob) //make sure the mobs don't go away while we waited for a response - return 1 - - tomob.ghostize(0) - - message_admins("[key_name_admin(usr)] has put [frommob.ckey] in control of [tomob.name].") - log_admin("[key_name(usr)] stuffed [frommob.ckey] into [tomob.name].") - SSblackbox.add_details("admin_verb","Ghost Drag Control") - - tomob.ckey = frommob.ckey - qdel(frommob) - - return 1 - -/client/proc/adminGreet(logout) - if(SSticker.HasRoundStarted()) - var/string - if(logout && config && config.announce_admin_logout) - string = pick( - "Admin logout: [key_name(src)]") - else if(!logout && config && config.announce_admin_login && (prefs.toggles & ANNOUNCE_LOGIN)) - string = pick( - "Admin login: [key_name(src)]") - if(string) + count++ + return "Kill all [count] of the monkeys on the station" + if(4) + return "Cut power to at least 80% of the station" + else + return "Error: Invalid sabotage target: [target]" +*/ +/datum/admins/proc/spawn_atom(object as text) + set category = "Debug" + set desc = "(atom path) Spawn an atom" + set name = "Spawn" + + if(!check_rights(R_SPAWN)) + return + + var/chosen = pick_closest_path(object) + if(!chosen) + return + if(ispath(chosen,/turf)) + var/turf/T = get_turf(usr.loc) + T.ChangeTurf(chosen) + else + var/atom/A = new chosen(usr.loc) + A.admin_spawned = TRUE + + log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") + SSblackbox.add_details("admin_verb","Spawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/datum/admins/proc/show_traitor_panel(mob/M in GLOB.mob_list) + set category = "Admin" + set desc = "Edit mobs's memory and role" + set name = "Show Traitor Panel" + + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + if(!M.mind) + to_chat(usr, "This mob has no mind!") + return + + M.mind.edit_memory() + SSblackbox.add_details("admin_verb","Traitor Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/datum/admins/proc/toggletintedweldhelmets() + set category = "Debug" + set desc="Reduces view range when wearing welding helmets" + set name="Toggle tinted welding helmes" + GLOB.tinted_weldhelh = !( GLOB.tinted_weldhelh ) + if (GLOB.tinted_weldhelh) + to_chat(world, "The tinted_weldhelh has been enabled!") + else + to_chat(world, "The tinted_weldhelh has been disabled!") + log_admin("[key_name(usr)] toggled tinted_weldhelh.") + message_admins("[key_name_admin(usr)] toggled tinted_weldhelh.") + SSblackbox.add_details("admin_toggle","Toggle Tinted Welding Helmets|[GLOB.tinted_weldhelh]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggleguests() + set category = "Server" + set desc="Guests can't enter" + set name="Toggle guests" + GLOB.guests_allowed = !( GLOB.guests_allowed ) + if (!( GLOB.guests_allowed )) + to_chat(world, "Guests may no longer enter the game.") + else + to_chat(world, "Guests may now enter the game.") + log_admin("[key_name(usr)] toggled guests game entering [GLOB.guests_allowed?"":"dis"]allowed.") + message_admins("[key_name_admin(usr)] toggled guests game entering [GLOB.guests_allowed?"":"dis"]allowed.") + SSblackbox.add_details("admin_toggle","Toggle Guests|[GLOB.guests_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/output_ai_laws() + var/ai_number = 0 + for(var/mob/living/silicon/S in GLOB.mob_list) + ai_number++ + if(isAI(S)) + to_chat(usr, "AI [key_name(S, usr)]'s laws:") + else if(iscyborg(S)) + var/mob/living/silicon/robot/R = S + to_chat(usr, "CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independant)"]: laws:") + else if (ispAI(S)) + to_chat(usr, "pAI [key_name(S, usr)]'s laws:") + else + to_chat(usr, "SOMETHING SILICON [key_name(S, usr)]'s laws:") + + if (S.laws == null) + to_chat(usr, "[key_name(S, usr)]'s laws are null?? Contact a coder.") + else + S.laws.show_laws(usr) + if(!ai_number) + to_chat(usr, "No AIs located" ) + +/datum/admins/proc/output_all_devil_info() + var/devil_number = 0 + for(var/D in SSticker.mode.devils) + devil_number++ + to_chat(usr, "Devil #[devil_number]:

" + SSticker.mode.printdevilinfo(D)) + 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.mind)) + else + to_chat(usr, "[M] is not a devil.") + +/datum/admins/proc/manage_free_slots() + if(!check_rights()) + return + var/dat = "Manage Free Slots" + var/count = 0 + + if(SSticker && !SSticker.mode) + alert(usr, "You cannot manage jobs before the round starts!") + return + + if(SSjob) + for(var/datum/job/job in SSjob.occupations) + count++ + var/J_title = html_encode(job.title) + var/J_opPos = html_encode(job.total_positions - (job.total_positions - job.current_positions)) + var/J_totPos = html_encode(job.total_positions) + if(job.total_positions < 0) + dat += "[J_title]: [J_opPos] (unlimited)" + else + dat += "[J_title]: [J_opPos]/[J_totPos]" + + if(job.title == "AI" || job.title == "Cyborg") + dat += " (Cannot Late Join)
" + continue + if(job.total_positions >= 0) + dat += " Add | " + if(job.total_positions > job.current_positions) + dat += "Remove | " + else + dat += "Remove | " + dat += "Unlimit" + else + dat += " Limit" + dat += "
" + + dat += "" + var/winheight = 100 + (count * 20) + winheight = min(winheight, 690) + usr << browse(dat, "window=players;size=375x[winheight]") + +// +// +//ALL DONE +//********************************************************************************************************* +//TO-DO: +// +// + +//RIP ferry snowflakes + +//Kicks all the clients currently in the lobby. The second parameter (kick_only_afk) determins if an is_afk() check is ran, or if all clients are kicked +//defaults to kicking everyone (afk + non afk clients in the lobby) +//returns a list of ckeys of the kicked clients +/proc/kick_clients_in_lobby(message, kick_only_afk = 0) + var/list/kicked_client_names = list() + for(var/client/C in GLOB.clients) + if(isnewplayer(C.mob)) + if(kick_only_afk && !C.is_afk()) //Ignore clients who are not afk + continue + if(message) + to_chat(C, message) + kicked_client_names.Add("[C.ckey]") + qdel(C) + return kicked_client_names + +//returns 1 to let the dragdrop code know we are trapping this event +//returns 0 if we don't plan to trap the event +/datum/admins/proc/cmd_ghost_drag(mob/dead/observer/frommob, mob/living/tomob) + + //this is the exact two check rights checks required to edit a ckey with vv. + if (!check_rights(R_VAREDIT,0) || !check_rights(R_SPAWN|R_DEBUG,0)) + return 0 + + if (!frommob.ckey) + return 0 + + var/question = "" + if (tomob.ckey) + question = "This mob already has a user ([tomob.key]) in control of it! " + question += "Are you sure you want to place [frommob.name]([frommob.key]) in control of [tomob.name]?" + + var/ask = alert(question, "Place ghost in control of mob?", "Yes", "No") + if (ask != "Yes") + return 1 + + if (!frommob || !tomob) //make sure the mobs don't go away while we waited for a response + return 1 + + tomob.ghostize(0) + + message_admins("[key_name_admin(usr)] has put [frommob.ckey] in control of [tomob.name].") + log_admin("[key_name(usr)] stuffed [frommob.ckey] into [tomob.name].") + SSblackbox.add_details("admin_verb","Ghost Drag Control") + + tomob.ckey = frommob.ckey + qdel(frommob) + + return 1 + +/client/proc/adminGreet(logout) + if(SSticker.HasRoundStarted()) + var/string + if(logout && config && config.announce_admin_logout) + string = pick( + "Admin logout: [key_name(src)]") + else if(!logout && config && config.announce_admin_login && (prefs.toggles & ANNOUNCE_LOGIN)) + string = pick( + "Admin login: [key_name(src)]") + if(string) message_admins("[string]") \ No newline at end of file diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index d479ddf1bc..e1ed63793d 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -297,7 +297,9 @@ setTimer(SSshuttle.emergencyDockTime) send2irc("Server", "The Emergency Shuttle has docked with the station.") priority_announce("The Emergency Shuttle has docked with the station. You have [timeLeft(600)] minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg', "Priority") - SSblackbox.add_details("emergency_shuttle", src.name) + if(SSdbcore.Connect()) + var/datum/DBQuery/query_round_shuttle_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET shuttle_name = '[name]' WHERE id = [GLOB.round_id]") + query_round_shuttle_name.Execute() // Gangs only have one attempt left if the shuttle has // docked with the station to prevent suffering from diff --git a/code/world.dm b/code/world.dm index df083571c4..dc71eed15f 100644 --- a/code/world.dm +++ b/code/world.dm @@ -56,13 +56,12 @@ /world/proc/SetRoundID() if(config.sql_enabled) if(SSdbcore.Connect()) - log_world("Database connection established.") - var/datum/DBQuery/query_feedback_create_round = SSdbcore.NewQuery("INSERT INTO [format_table_name("feedback")] SELECT null, Now(), IFNULL(MAX(round_id),0)+1, \"server_ip\", 0, \"[world.internet_address]:[world.port]\" FROM [format_table_name("feedback")]") - query_feedback_create_round.Execute() - var/datum/DBQuery/query_feedback_max_id = SSdbcore.NewQuery("SELECT MAX(round_id) FROM [format_table_name("feedback")]") - query_feedback_max_id.Execute() - if(query_feedback_max_id.NextRow()) - GLOB.round_id = query_feedback_max_id.item[1] + var/datum/DBQuery/query_round_start = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (start_datetime, server_ip, server_port) VALUES (Now(), INET_ATON('[world.internet_address]'), '[world.port]')") + query_round_start.Execute() + var/datum/DBQuery/query_round_last_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()") + query_round_last_id.Execute() + if(query_round_last_id.NextRow()) + GLOB.round_id = query_round_last_id.item[1] else log_world("Your server failed to establish a connection with the database.") @@ -225,7 +224,7 @@ else to_chat(world, "Rebooting world...") Master.Shutdown() //run SS shutdowns - log_world("World rebooted at [time_stamp()]"); + log_world("World rebooted at [time_stamp()]") ..() /world/proc/load_motd()