diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 7e9ea75db89..89333ee5fa2 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -85,6 +85,9 @@ var/humans_need_surnames = 0 var/allow_random_events = 0 // enables random events mid-round when set to 1 var/allow_ai = 0 // allow ai job + var/panic_bunker = 0 // prevents new people it hasn't seen before from connecting + var/notify_new_player_age = 0 // how long do we notify admins of a new player + var/irc_first_connection_alert = 0 // do we notify the irc channel when somebody is connecting for the first time? var/traitor_scaling_coeff = 6 //how much does the amount of players get divided by to determine traitors var/changeling_scaling_coeff = 6 //how much does the amount of players get divided by to determine changelings @@ -316,6 +319,12 @@ config.hard_popcap_message = value if("extreme_popcap_message") config.extreme_popcap_message = value + if("panic_bunker") + config.panic_bunker = 1 + if("notify_new_player_age") + config.notify_new_player_age = text2num(value) + if("irc_first_connection_alert") + config.irc_first_connection_alert = 1 else diary << "Unknown setting in configuration: '[name]'" diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index d3a96e20ce2..7bee21bbb03 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -108,6 +108,7 @@ Note: you can set the datum's defined processing_interval to some integer to set /datum/controller/game_controller/proc/roundHasStarted() for(var/datum/subsystem/SS in subsystems) SS.can_fire = 1 + SS.next_fire = world.time /datum/controller/game_controller/proc/Recover() var/msg = "## DEBUG: [time2text(world.timeofday)] MC restarted. Reports:\n" diff --git a/code/controllers/subsystem/nanoUI.dm b/code/controllers/subsystem/nanoUI.dm index f9083f7e8ed..45fc8f8c1f4 100644 --- a/code/controllers/subsystem/nanoUI.dm +++ b/code/controllers/subsystem/nanoUI.dm @@ -9,10 +9,29 @@ var/datum/subsystem/nano/SSnano var/list/open_uis = list() //a list of current open /nanoui UIs, grouped by src_object and ui_key var/list/processing_uis = list() //a list of current open /nanoui UIs, not grouped, for use in processing + //List of asset filenames to be sent to the client on user login + var/list/asset_files = list() + /datum/subsystem/nano/New() NEW_SS_GLOBAL(SSnano) + //Generate list of files to send to client for nano UI's + var/list/nano_asset_dirs = list(\ + "nano/css/",\ + "nano/images/",\ + "nano/js/",\ + "nano/templates/"\ + ) + var/list/filenames = null + for (var/path in nano_asset_dirs) + filenames = flist(path) + for(var/filename in filenames) + //Ignore directories + if(copytext(filename, length(filename)) != "/") + if(fexists(path + filename)) + asset_files.Add(fcopy_rsc(path + filename)) + /datum/subsystem/nano/stat_entry() stat(name, "[round(cost,0.001)]ds (CPU:[round(cpu,1)]%) [processing_uis.len]") @@ -27,4 +46,4 @@ var/datum/subsystem/nano/SSnano ui.process() ++i continue - processing_uis.Cut(i, i+1) \ No newline at end of file + processing_uis.Cut(i, i+1) diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 941a445e17b..5e77e908e94 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -388,7 +388,7 @@ to destroy them and players will be able to make replacements. board_type = "machine" origin_tech = "materials=2;engineering=2" req_components = list( - /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/weapon/stock_parts/micro_laser = 1, /obj/item/weapon/stock_parts/console_screen = 1) //Almost the same recipe as destructive analyzer to give people choices. diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm index 943ad971222..198cf71e19b 100644 --- a/code/game/objects/structures/barsigns.dm +++ b/code/game/objects/structures/barsigns.dm @@ -5,18 +5,32 @@ icon_state = "empty" req_access = list(access_bar) var/list/barsigns=list() + var/list/hiddensigns + var/broken = 0 + var/emagged = 0 + var/state = 0 + var/prev_sign = "" + var/panel_open = 0 + + + /obj/structure/sign/barsign/New() ..() + //filling the barsigns list for(var/bartype in typesof(/datum/barsign) - /datum/barsign) var/datum/barsign/signinfo = new bartype - barsigns += signinfo + if(!signinfo.hidden) + barsigns += signinfo + //randomly assigning a sign set_sign(pick(barsigns)) + + /obj/structure/sign/barsign/proc/set_sign(var/datum/barsign/sign) if(!istype(sign)) return @@ -27,101 +41,205 @@ else desc = "It displays \"[name]\"." + + /obj/structure/sign/barsign/attack_ai(mob/user as mob) return src.attack_hand(user) + + /obj/structure/sign/barsign/attack_hand(mob/user as mob) if (!src.allowed(user)) user << "Access denied." return - + if (broken) + user << "The controls seem unresponsive." + return pick_sign() + + + +/obj/structure/sign/barsign/attackby(var/obj/item/I, var/mob/user) + if(!allowed(user)) + user << "Access denied." + return + if( istype(I, /obj/item/weapon/screwdriver)) + if(!panel_open) + user << "You open the maintenance panel." + set_sign(new /datum/barsign/hiddensigns/signoff) + panel_open = 1 + else + user << "You close the maintenance panel." + if(!broken && !emagged) + set_sign(pick(barsigns)) + else if(emagged) + set_sign(new /datum/barsign/hiddensigns/syndibarsign) + else + set_sign(new /datum/barsign/hiddensigns/empbarsign) + panel_open = 0 + + if(istype(I, /obj/item/stack/cable_coil) && panel_open) + var/obj/item/stack/cable_coil/C = I + if(emagged) //Emagged, not broken by EMP + user << "Sign has been damaged beyond repair." + return + else if(!broken) + user << "This sign is functioning properly." + return + + if(C.use(2)) + user << "You replace the burnt wiring." + broken = 0 + else + user << "You need at least two lengths of cable." + + + /obj/structure/sign/barsign/emp_act(severity) - var/prev_icon = icon_state - icon_state = "empbarsign" - sleep(300*severity) //measured in deci-seconds - icon_state = prev_icon + set_sign(new /datum/barsign/hiddensigns/empbarsign) + broken = 1 + + + + +/obj/structure/sign/barsign/emag_act(mob/user) + if(broken || emagged) + user << "Nothing interesting happens." + return + user << "You emag the barsign. Takeover in progress..." + sleep(100) //10 seconds + set_sign(new /datum/barsign/hiddensigns/syndibarsign) + emagged = 1 + req_access = list(access_syndicate) + + /obj/structure/sign/barsign/proc/pick_sign() var/picked_name = input("Available Signage", "Bar Sign") as null|anything in barsigns if(!picked_name) return - set_sign(picked_name) + //Code below is to define useless variables for datums. It errors without these + + /datum/barsign var/name = "Name" var/icon = "Icon" var/desc = "desc" + var/hidden = 0 + //Anything below this is where all the specific signs are. If people want to add more signs, add them below. + + /datum/barsign/maltesefalcon name = "Maltese Falcon" icon = "maltesefalcon" - desc = "The Maltese Faclon, Space Bar and Grill" + desc = "The Maltese Falcon, Space Bar and Grill" + /datum/barsign/thebark name = "The Bark" icon = "thebark" desc = "Ian's bar of choice" + /datum/barsign/harmbaton name = "The Harmbaton" icon = "theharmbaton" desc = "A great dining experience for both security members and assistants" + /datum/barsign/thesingulo name = "The Singulo" icon = "thesingulo" desc = "Where people go that'd rather not be called by their name" + /datum/barsign/thedrunkcarp name = "The Drunk Carp" icon = "thedrunkcarp" desc = "Don't drink and Swim" + /datum/barsign/scotchservinwill name = "Scotch Servin Willy's" icon = "scotchservinwill" desc = "Willy sure moved up in the world from clown to bartender" + /datum/barsign/officerbeersky name = "Officer Beersky's" icon = "officerbeersky" desc = "Man eat a dong, these drinks are great" + /datum/barsign/thecavern name = "The Cavern" icon = "thecavern" desc = "Fine drinks while listening to some fine tunes" + /datum/barsign/theouterspess name = "The Outer Spess" icon = "theouterspess" desc = "This bar isn't actually located in outer space" + /datum/barsign/slipperyshots name = "Slippery Shots" icon = "slipperyshots" desc = "Slippery slope to drunkeness with our shots!" + /datum/barsign/thegreytide name = "The Grey Tide" icon = "thegreytide" desc = "Abandon your toolboxing ways and enjoy a lazy beer!" + /datum/barsign/honkednloaded name = "Honked 'n' Loaded" icon = "honkednloaded" desc = "Honk." -/datum/barsign/thenest +/datm/barsign/thenest name = "The Nest" icon = "thenest" - desc = "A good place to retire for a drink after a night of crime fighting." \ No newline at end of file + desc = "A good place to retire for a drink after a long night of crime fighting." + + + +/datum/barsign/hiddensigns + hidden = 1 + + +//Hidden signs list below this point + + + +/datum/barsign/hiddensigns/empbarsign + name = "Haywire Barsign" + icon = "empbarsign" + desc = "Something has gone very wrong." + + + +/datum/barsign/hiddensigns/syndibarsign + name = "Syndi Cat Takeover" + icon = "syndibarsign" + desc = "Syndicate or die." + + + +/datum/barsign/hiddensigns/signoff + name = "Bar Sign" + icon = "empty" + desc = "This sign doesn't seem to be on." \ No newline at end of file diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 4a6433fe273..4abe574216a 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -42,10 +42,15 @@ world/IsBanned(key,address,computer_id) return ..() //Guest Checking - if(!guests_allowed && IsGuestKey(key)) - log_access("Failed Login: [key] - Guests not allowed") - message_admins("Failed Login: [key] - Guests not allowed") - return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.") + if(IsGuestKey(key)) + if (!guests_allowed) + log_access("Failed Login: [key] - Guests not allowed") + message_admins("Failed Login: [key] - Guests not allowed") + return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.") + if (config.panic_bunker && dbcon && dbcon.IsConnected()) + log_access("Failed Login: [key] - Guests not allowed during panic bunker") + message_admins("Failed Login: [key] - Guests not allowed during panic bunker") + return list("reason"="guest", "desc"="\nReason: Sorry but the server is currently not accepting connections from never before seen players or guests. If you have played on this server with a byond account before, please log in to the byond account you have played from.") //Population Cap Checking if(config.extreme_popcap && living_player_count() >= config.extreme_popcap && !(ckey(key) in admin_datums)) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 0434213187c..f35c93a3e89 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -100,7 +100,8 @@ var/list/admin_verbs_server = list( /datum/admins/proc/toggleAI, /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ /client/proc/cmd_debug_del_all, - /client/proc/toggle_random_events + /client/proc/toggle_random_events, + /client/proc/panicbunker ) var/list/admin_verbs_debug = list( /client/proc/restart_controller, @@ -190,7 +191,8 @@ var/list/admin_verbs_hideable = list( /proc/possess, /proc/release, /client/proc/reload_admins, - /client/proc/reset_all_tcs + /client/proc/reset_all_tcs, + /client/proc/panicbunker ) /client/proc/add_admin_verbs() diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 484b4c31cc2..7d6dd693e86 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -88,6 +88,23 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," msg = "HELP: [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (TP) [ai_found ? " (CL)" : ""]: [msg]" //send this msg to all admins + + for(var/client/X in admins) + if(X.prefs.toggles & SOUND_ADMINHELP) + X << 'sound/effects/adminhelp.ogg' + X << msg + + + //show it to the person adminhelping too + src << "PM to-Admins: [original_msg]" + + //send it to irc if nobody is on and tell us how many were on + var/admin_number_present = send2irc_adminless_only(original_msg) + log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins who have +BAN.") + feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN) var/admin_number_total = 0 //Total number of admins var/admin_number_afk = 0 //Holds the number of admins who are afk var/admin_number_ignored = 0 //Holds the number of admins without +BAN (so admins who are not really admins) @@ -95,30 +112,24 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," for(var/client/X in admins) admin_number_total++; var/invalid = 0 - if(!check_rights_for(X, R_BAN)) + if(requiredflags != 0 && !check_rights_for(X, requiredflags)) admin_number_ignored++ invalid = 1 if(X.is_afk()) admin_number_afk++ invalid = 1 + if(X.holder.fakekey) + admin_number_ignored++ + invalid = 1 if(invalid) admin_number_decrease++ - if(X.prefs.toggles & SOUND_ADMINHELP) - X << 'sound/effects/adminhelp.ogg' - X << msg - - //show it to the person adminhelping too - src << "PM to-Admins: [original_msg]" - var/admin_number_present = admin_number_total - admin_number_decrease //Number of admins who are neither afk nor invalid - log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins who have +BAN.") if(admin_number_present <= 0) if(!admin_number_afk && !admin_number_ignored) - send2irc(ckey, "[original_msg] - No admins online") + send2irc(source, "[msg] - No admins online") else - send2irc(ckey, "[original_msg] - All admins AFK ([admin_number_afk]/[admin_number_total]) or skipped ([admin_number_ignored]/[admin_number_total])") - feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return + send2irc(source, "[msg] - All admins AFK ([admin_number_afk]/[admin_number_total]) or skipped ([admin_number_ignored]/[admin_number_total])") + return admin_number_present proc/send2irc(msg,msg2) if(config.useircbot) diff --git a/code/modules/admin/verbs/panicbunker.dm b/code/modules/admin/verbs/panicbunker.dm new file mode 100644 index 00000000000..ff530656cbf --- /dev/null +++ b/code/modules/admin/verbs/panicbunker.dm @@ -0,0 +1,15 @@ +/client/proc/panicbunker() + set category = "Server" + set name = "Toggle Panic Bunker" + if (!config.sql_enabled) + usr << "The Database is not enabled!" + return + + config.panic_bunker = (!config.panic_bunker) + + log_admin("[key_name(usr)] has toggled the Panic Bunker, it is now [(config.panic_bunker?"on":"off")]") + message_admins("[key_name_admin(usr)] has toggled the Panic Bunker, it is now [(config.panic_bunker?"enabled":"disabled")].") + if (config.panic_bunker && (!dbcon || !dbcon.IsConnected())) + message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.") + feedback_add_details("admin_verb","PANIC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 32ae0986467..4607b7ff78d 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -90,7 +90,9 @@ var/list/external_rsc_urls var/next_external_rsc = 0 #endif + /client/New(TopicData) + TopicData = null //Prevent calls to client.Topic from connect if(connection != "seeker") //Invalid connection type. @@ -136,6 +138,25 @@ var/next_external_rsc = 0 add_verbs_from_config() set_client_age_from_db() + if (isnum(player_age) && player_age == -1) //first connection + if (config.panic_bunker && !holder && !(ckey in deadmins)) + log_access("Failed Login: [key] - New account attempting to connect during panic bunker") + message_admins("Failed Login: [key] - New account attempting to connect during panic bunker") + src << "Sorry but the server is currently not accepting connections from never before seen players." + del(src) + return 0 + + if (config.notify_new_player_age >= 0) + message_admins("New user: [key_name_admin(src)] is connecting here for the first time.") + if (config.irc_first_connection_alert) + send2irc_adminless_only("New user", "[key_name(src)] is connecting for the first time!") + + player_age = 0 // set it from -1 to 0 so the job selection code doesn't have a panic attack + + else if (isnum(player_age) && player_age < config.notify_new_player_age) + message_admins("New user: [key_name_admin(src)] just connected with an age of [player_age] day[(player_age==1?"":"s")]") + + if (!ticker || ticker.current_state == GAME_STATE_PREGAME) spawn (rand(10,150)) if (src) @@ -172,14 +193,15 @@ var/next_external_rsc = 0 var/sql_ckey = sanitizeSQL(src.ckey) var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") - query.Execute() + if (!query.Execute()) + return while (query.NextRow()) player_age = text2num(query.item[2]) return - //player not found. - player_age = 0 - message_admins("[key_name_admin(src)] is connecting here for the first time.") + + //no match mark it as a first connection for use in client/New() + player_age = -1 /client/proc/sync_client_with_db() @@ -239,25 +261,9 @@ var/next_external_rsc = 0 //send resources to the client. It's here in its own proc so we can move it around easiliy if need be /client/proc/send_resources() + //Send nanoui files to client + SSnano.send_resources(src) getFiles( - 'nano/js/libraries.min.js', - 'nano/js/nano_update.js', - 'nano/js/nano_config.js', - 'nano/js/nano_base_helpers.js', - 'nano/css/shared.css', - 'nano/css/icons.css', - 'nano/templates/chem_dispenser.tmpl', - 'nano/templates/chem_heater.tmpl', - 'nano/templates/smes.tmpl', - 'nano/templates/apc.tmpl', - 'nano/templates/cryo.tmpl', - 'nano/templates/solar_control.tmpl', - 'nano/images/uiBackground.png', - 'nano/images/uiIcons16.png', - 'nano/images/uiIcons24.png', - 'nano/images/uiLinkPendingIcon.gif', - 'nano/images/uiNoticeBackground.jpg', - 'nano/images/uiTitleFluff.png', 'html/search.js', 'html/panels.css', 'html/browser/common.css', diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 0e8bbfc0da3..8c5c8be36ff 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -842,7 +842,7 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob, p podman.ckey = ckey_holder podman.gender = blood_gender podman.faction |= factions - hardset_dna(podman,null,null,podman.real_name,blood_type,/datum/species/plant/pod,"#59CE00")//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman + hardset_dna(podman,null,null,podman.real_name,blood_type,/datum/species/plant/pod)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman podman.set_cloned_appearance() else //else, one packet of seeds. maybe two diff --git a/code/modules/nano/nanomanager.dm b/code/modules/nano/nanomanager.dm index c463787a17e..07a6a4570dc 100644 --- a/code/modules/nano/nanomanager.dm +++ b/code/modules/nano/nanomanager.dm @@ -182,3 +182,7 @@ return 1 // success +//Send all needed nano ui files to the client +/datum/subsystem/nano/proc/send_resources(client) + for(var/file in asset_files) + client << browse_rsc(file) diff --git a/code/modules/reagents/Chemistry-Goon-Pyrotechnics.dm b/code/modules/reagents/Chemistry-Goon-Pyrotechnics.dm index 0d503e6164f..0f20253e345 100644 --- a/code/modules/reagents/Chemistry-Goon-Pyrotechnics.dm +++ b/code/modules/reagents/Chemistry-Goon-Pyrotechnics.dm @@ -101,10 +101,10 @@ id = "liquid_dark_matter" result = "liquid_dark_matter" required_reagents = list("stable_plasma" = 1, "radium" = 1, "carbon" = 1) - result_amount = 3 + result_amount = null required_temp = 474 -/datum/reagent/liquid_dark_matter/reaction_turf(var/turf/simulated/T, var/volume) +/*/datum/reagent/liquid_dark_matter/reaction_turf(var/turf/simulated/T, var/volume) if(istype(T, /turf/simulated/floor/)) goonchem_vortex(T, 0, 5, 3) return @@ -114,13 +114,13 @@ if(method == TOUCH) var/turf/simulated/T = get_turf(M) goonchem_vortex(T, 0, 5, 3) - return + return*/ //o god what the fuck goof /datum/chemical_reaction/liquid_dark_matter/on_reaction(var/datum/reagents/holder, var/created_volume) var/turf/simulated/T = get_turf(holder.my_atom) goonchem_vortex(T, 0, 5, 6) return -proc/goonchem_vortex(var/turf/simulated/T, var/setting_type, var/range, var/pull_times) +/proc/goonchem_vortex(var/turf/simulated/T, var/setting_type, var/range, var/pull_times) for(var/atom/movable/X in orange(range, T)) if(istype(X, /obj/effect)) continue //stop pulling smoke and hotspots please diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index 6dc2bd1375a..1e9bcb8c6a0 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -61,13 +61,13 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). /obj/machinery/r_n_d/circuit_imprinter/proc/check_mat(datum/design/being_built, var/M) switch(M) if("$glass") - return (g_amount - (being_built.materials[M]/efficiency_coeff) >= 0) ? 1 : 0 + return (g_amount - (being_built.materials[M]/efficiency_coeff) >= 0) if("$gold") - return (gold_amount - (being_built.materials[M]/efficiency_coeff) >= 0) ? 1 : 0 + return (gold_amount - (being_built.materials[M]/efficiency_coeff) >= 0) if("$diamond") - return (diamond_amount - (being_built.materials[M]/efficiency_coeff) >= 0) ? 1 : 0 + return (diamond_amount - (being_built.materials[M]/efficiency_coeff) >= 0) else - return (reagents.has_reagent(M, (being_built.materials[M]/efficiency_coeff)) != 0) ? 1 : 0 + return (reagents.has_reagent(M, (being_built.materials[M]/efficiency_coeff)) != 0) /obj/machinery/r_n_d/circuit_imprinter/proc/TotalMaterials() diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 1749511b743..d076c813158 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -369,34 +369,38 @@ won't update every console in existence) but it's more of a hassle to do. Also, if (g2g) //If input is incorrect, nothing happens + var/enough_materials = 1 linked_lathe.busy = 1 flick("protolathe_n",linked_lathe) use_power(power) for(var/M in being_built.materials) - if(!linked_lathe.check_mat(being_built, M)) + if(linked_lathe.check_mat(being_built, M) < amount) src.visible_message("The [src.name] beeps, \"Not enough materials to complete prototype.\"") + enough_materials = 0 g2g = 0 break - switch(M) - if("$metal") - linked_lathe.m_amount = max(0, (linked_lathe.m_amount-(being_built.materials[M]/coeff * amount))) - if("$glass") - linked_lathe.g_amount = max(0, (linked_lathe.g_amount-(being_built.materials[M]/coeff * amount))) - if("$gold") - linked_lathe.gold_amount = max(0, (linked_lathe.gold_amount-(being_built.materials[M]/coeff * amount))) - if("$silver") - linked_lathe.silver_amount = max(0, (linked_lathe.silver_amount-(being_built.materials[M]/coeff * amount))) - if("$plasma") - linked_lathe.plasma_amount = max(0, (linked_lathe.plasma_amount-(being_built.materials[M]/coeff * amount))) - if("$uranium") - linked_lathe.uranium_amount = max(0, (linked_lathe.uranium_amount-(being_built.materials[M]/coeff * amount))) - if("$diamond") - linked_lathe.diamond_amount = max(0, (linked_lathe.diamond_amount-(being_built.materials[M]/coeff * amount))) - if("$bananium") - linked_lathe.clown_amount = max(0, (linked_lathe.clown_amount-(being_built.materials[M]/coeff * amount))) - else - linked_lathe.reagents.remove_reagent(M, being_built.materials[M]/coeff * amount) + if(enough_materials) + for(var/M in being_built.materials) + switch(M) + if("$metal") + linked_lathe.m_amount = max(0, (linked_lathe.m_amount-(being_built.materials[M]/coeff * amount))) + if("$glass") + linked_lathe.g_amount = max(0, (linked_lathe.g_amount-(being_built.materials[M]/coeff * amount))) + if("$gold") + linked_lathe.gold_amount = max(0, (linked_lathe.gold_amount-(being_built.materials[M]/coeff * amount))) + if("$silver") + linked_lathe.silver_amount = max(0, (linked_lathe.silver_amount-(being_built.materials[M]/coeff * amount))) + if("$plasma") + linked_lathe.plasma_amount = max(0, (linked_lathe.plasma_amount-(being_built.materials[M]/coeff * amount))) + if("$uranium") + linked_lathe.uranium_amount = max(0, (linked_lathe.uranium_amount-(being_built.materials[M]/coeff * amount))) + if("$diamond") + linked_lathe.diamond_amount = max(0, (linked_lathe.diamond_amount-(being_built.materials[M]/coeff * amount))) + if("$bananium") + linked_lathe.clown_amount = max(0, (linked_lathe.clown_amount-(being_built.materials[M]/coeff * amount))) + else + linked_lathe.reagents.remove_reagent(M, being_built.materials[M]/coeff * amount) var/P = being_built.build_path //lets save these values before the spawn() just in case. Nobody likes runtimes. var/R = being_built.reliability @@ -827,17 +831,17 @@ won't update every console in existence) but it's more of a hassle to do. Also, for(var/M in D.materials) t = linked_lathe.check_mat(D, M) temp_material += " | " - if (!t) + if (t < 1) temp_material += "[D.materials[M]/coeff] [CallMaterialName(M)]" else temp_material += " [D.materials[M]/coeff] [CallMaterialName(M)]" c = min(c,t) - if (c) + if (c >= 1) dat += "[D.name]" - if(c >= 5.0) + if(c >= 5) dat += "x5" - if(c >= 10.0) + if(c >= 10) dat += "x10" dat += "[temp_material]" else @@ -860,17 +864,17 @@ won't update every console in existence) but it's more of a hassle to do. Also, for(var/M in D.materials) t = linked_lathe.check_mat(D, M) temp_material += " | " - if (!t) + if (t < 1) temp_material += "[D.materials[M]/coeff] [CallMaterialName(M)]" else temp_material += " [D.materials[M]/coeff] [CallMaterialName(M)]" c = min(c,t) - if (c) + if (c >= 1) dat += "[D.name]" - if(c >= 5.0) + if(c >= 5) dat += "x5" - if(c >= 10.0) + if(c >= 10) dat += "x10" dat += "[temp_material]" else diff --git a/config/config.txt b/config/config.txt index 412245906b1..e28c4ff6b2f 100644 --- a/config/config.txt +++ b/config/config.txt @@ -175,4 +175,16 @@ HARD_MESSAGE The server is currently serving a high number of users, You cannot #EXTREME_POPCAP 200 ## Message for extreme cap -EXTREME_MESSAGE The server is currently serving a high number of users, find alternative servers. \ No newline at end of file +EXTREME_MESSAGE The server is currently serving a high number of users, find alternative servers. + +## Notify admins when a new player connects for the first x days a player's been around. (0 for first connection only, -1 for never) +## Requres database +NOTIFY_NEW_PLAYER_AGE 0 + +## Notify the irc channel when a new player makes their first connection +## Requres database +#IRC_FIRST_CONNECTION_ALERT + +## Deny all new connections by ckeys we haven't seen before (exempts admins and only denies the connection if the database is enabled and connected) +## Requires database +#PANIC_BUNKER \ No newline at end of file diff --git a/html/changelogs/MrStonedOne-panicBunker-PR-8006.yml b/html/changelogs/MrStonedOne-panicBunker-PR-8006.yml new file mode 100644 index 00000000000..4b4a1cc6a67 --- /dev/null +++ b/html/changelogs/MrStonedOne-panicBunker-PR-8006.yml @@ -0,0 +1,40 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# spellcheck (typo fixes) +# experiment +# tgs (TG-ported fixes?) +################################# + +# Your name. +author: MrStonedOne + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. Fuck you N3X15, should have made this work with tabs +# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit. +# Please surround your changes in single (') or double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: 'Adds a Panic Bunker!' + - tweak: 'This will prevent any player who has never connected before from connecting. (Admins are exempt)' + - tweak: 'Can be enabled per-round by any admin with +SERVER or for longer periods via the config.' + - recadd: 'Also adds some other config options relating to new joins, server operators should consult their configuration file for more details.' + \ No newline at end of file diff --git a/icons/obj/barsigns.dmi b/icons/obj/barsigns.dmi index 9fd008228db..ea10d30db0a 100644 Binary files a/icons/obj/barsigns.dmi and b/icons/obj/barsigns.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 6bce7153849..08724346457 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -798,6 +798,7 @@ #include "code\modules\admin\verbs\modifyvariables.dm" #include "code\modules\admin\verbs\one_click_antag.dm" #include "code\modules\admin\verbs\onlyone.dm" +#include "code\modules\admin\verbs\panicbunker.dm" #include "code\modules\admin\verbs\playsound.dm" #include "code\modules\admin\verbs\possess.dm" #include "code\modules\admin\verbs\pray.dm"