From 0e510e8c345c6fb4793bddd5b106d8b973cd94ae Mon Sep 17 00:00:00 2001 From: Poojawa Date: Tue, 11 Sep 2018 00:54:07 -0500 Subject: [PATCH] HELPERS --- code/__HELPERS/AStar.dm | 5 +- code/__HELPERS/_lists.dm | 43 ++++++++++++- code/__HELPERS/_logging.dm | 112 +++++++++++++++++++++++++++++---- code/__HELPERS/areas.dm | 23 ++++--- code/__HELPERS/game.dm | 2 +- code/__HELPERS/icons.dm | 8 ++- code/__HELPERS/level_traits.dm | 2 +- code/__HELPERS/mobs.dm | 95 ---------------------------- code/__HELPERS/radiation.dm | 24 ++++--- code/__HELPERS/roundend.dm | 42 ++++++++++++- code/__HELPERS/unsorted.dm | 89 +++----------------------- 11 files changed, 224 insertions(+), 221 deletions(-) diff --git a/code/__HELPERS/AStar.dm b/code/__HELPERS/AStar.dm index c038e2e2e2..5e03d9b350 100644 --- a/code/__HELPERS/AStar.dm +++ b/code/__HELPERS/AStar.dm @@ -101,7 +101,10 @@ Actual Adjacent procs : //sanitation var/turf/end = get_turf(_end) var/turf/start = get_turf(caller) - if((!start)||(start.z != end.z)||(start == end)) //no pathfinding between z levels + if(!start || !end) + stack_trace("Invalid A* start or destination") + return 0 + if( start.z != end.z || start == end ) //no pathfinding between z levels return 0 if(maxnodes) //if start turf is farther than maxnodes from end turf, no need to do anything diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 54dd2a982c..fed283adcd 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -20,6 +20,35 @@ #define LAZYLEN(L) length(L) #define LAZYCLEARLIST(L) if(L) L.Cut() #define SANITIZE_LIST(L) ( islist(L) ? L : list() ) +#define reverseList(L) reverseRange(L.Copy()) + +// binary search sorted insert +// IN: Object to be inserted +// LIST: List to insert object into +// TYPECONT: The typepath of the contents of the list +// COMPARE: The variable on the objects to compare +#define BINARY_INSERT(IN, LIST, TYPECONT, COMPARE) \ + var/__BIN_CTTL = length(LIST);\ + if(!__BIN_CTTL) {\ + LIST += IN;\ + } else {\ + var/__BIN_LEFT = 1;\ + var/__BIN_RIGHT = __BIN_CTTL;\ + var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\ + var/##TYPECONT/__BIN_ITEM;\ + while(__BIN_LEFT < __BIN_RIGHT) {\ + __BIN_ITEM = LIST[__BIN_MID];\ + if(__BIN_ITEM.##COMPARE <= IN.##COMPARE) {\ + __BIN_LEFT = __BIN_MID + 1;\ + } else {\ + __BIN_RIGHT = __BIN_MID;\ + };\ + __BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\ + };\ + __BIN_ITEM = LIST[__BIN_MID];\ + __BIN_MID = __BIN_ITEM.##COMPARE > IN.##COMPARE ? __BIN_MID : __BIN_MID + 1;\ + LIST.Insert(__BIN_MID, IN);\ + } //Returns a list in plain english as a string /proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" ) @@ -460,8 +489,18 @@ return l . = l.Copy() for(var/i = 1 to l.len) - if(islist(.[i])) - .[i] = .(.[i]) + var/key = .[i] + if(isnum(key)) + // numbers cannot ever be associative keys + continue + var/value = .[key] + if(islist(value)) + value = deepCopyList(value) + .[key] = value + if(islist(key)) + key = deepCopyList(key) + .[i] = key + .[key] = value //takes an input_key, as text, and the list of keys already used, outputting a replacement key in the format of "[input_key] ([number_of_duplicates])" if it finds a duplicate //use this for lists of things that might have the same name, like mobs or objects, that you plan on giving to a player as input diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 92f7b21bb7..ac17df5773 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -44,6 +44,7 @@ WRITE_LOG(GLOB.world_game_log, "ADMINPRIVATE: [text]") /proc/log_adminsay(text) + GLOB.admin_log.Add(text) if (CONFIG_GET(flag/log_adminchat)) WRITE_LOG(GLOB.world_game_log, "ADMINPRIVATE: ASAY: [text]") @@ -103,6 +104,10 @@ //reusing the PDA option because I really don't think news comments are worth a config option WRITE_LOG(GLOB.world_pda_log, "COMMENT: [text]") +/proc/log_telecomms(text) + if (CONFIG_GET(flag/log_telecomms)) + WRITE_LOG(GLOB.world_telecomms_log, "TCOMMS: [text]") + /proc/log_chat(text) if (CONFIG_GET(flag/log_pda)) //same thing here @@ -134,7 +139,9 @@ /* Log to both DD and the logfile. */ /proc/log_world(text) +#ifdef USE_CUSTOM_ERROR_HANDLER WRITE_LOG(GLOB.world_runtime_log, text) +#endif SEND_TEXT(world.log, text) /* Log to the logfile only. */ @@ -157,19 +164,100 @@ /* Helper procs for building detailed log lines */ -/proc/datum_info_line(datum/D) - if(!istype(D)) - return - if(!ismob(D)) - return "[D] ([D.type])" - var/mob/M = D - return "[M] ([M.ckey]) ([M.type])" +/proc/key_name(whom, include_link = null, include_name = TRUE) + var/mob/M + var/client/C + var/key + var/ckey + var/fallback_name -/proc/atom_loc_line(atom/A) + if(!whom) + return "*null*" + if(istype(whom, /client)) + C = whom + M = C.mob + key = C.key + ckey = C.ckey + else if(ismob(whom)) + M = whom + C = M.client + key = M.key + ckey = M.ckey + else if(istext(whom)) + key = whom + ckey = ckey(whom) + C = GLOB.directory[ckey] + if(C) + M = C.mob + else if(istype(whom,/datum/mind)) + var/datum/mind/mind = whom + key = mind.key + ckey = ckey(key) + if(mind.current) + M = mind.current + if(M.client) + C = M.client + else + fallback_name = mind.name + else // Catch-all cases if none of the types above match + var/swhom = null + + if(istype(whom, /atom)) + var/atom/A = whom + swhom = "[A.name]" + else if(istype(whom, /datum)) + swhom = "[whom]" + + if(!swhom) + swhom = "*invalid*" + + return "\[[swhom]\]" + + . = "" + + if(!ckey) + include_link = FALSE + + if(key) + if(C && C.holder && C.holder.fakekey && !include_name) + if(include_link) + . += "" + . += "Administrator" + else + if(include_link) + . += "" + . += key + if(!C) + . += "\[DC\]" + + if(include_link) + . += "" + else + . += "*no key*" + + if(include_name) + if(M) + if(M.real_name) + . += "/([M.real_name])" + else if(M.name) + . += "/([M.name])" + else if(fallback_name) + . += "/([fallback_name])" + + return . + +/proc/key_name_admin(whom, include_name = TRUE) + return key_name(whom, TRUE, include_name) + +/proc/loc_name(atom/A) if(!istype(A)) - return - var/turf/T = get_turf(A) + return "(INVALID LOCATION)" + + var/turf/T = A + if (!istype(T)) + T = get_turf(A) + if(istype(T)) - return "[A.loc] [COORD(T)] ([A.loc.type])" + return "([AREACOORD(T)])" else if(A.loc) - return "[A.loc] (0, 0, 0) ([A.loc.type])" + return "(UNKNOWN (?, ?, ?))" diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm index 3e9a26b261..f05bf6f3e1 100644 --- a/code/__HELPERS/areas.dm +++ b/code/__HELPERS/areas.dm @@ -3,7 +3,8 @@ // Gets an atmos isolated contained space // Returns an associative list of turf|dirs pairs // The dirs are connected turfs in the same space -// break_if_found is a typecache of turf types to return false if found +// break_if_found is a typecache of turf/area types to return false if found +// Please keep this proc type agnostic. If you need to restrict it do it elsewhere or add an arg. /proc/detect_room(turf/origin, list/break_if_found) if(origin.blocks_air) return list(origin) @@ -13,10 +14,6 @@ var/list/found_turfs = list(origin) while(found_turfs.len) var/turf/sourceT = found_turfs[1] - if(break_if_found[sourceT.type]) - return FALSE - if (istype(sourceT.loc, /area/shuttle)) - return FALSE found_turfs.Cut(1, 2) var/dir_flags = checked_turfs[sourceT] for(var/dir in GLOB.alldirs) @@ -29,18 +26,24 @@ checked_turfs[checkT] |= turn(dir, 180) .[sourceT] |= dir .[checkT] |= turn(dir, 180) + if(break_if_found[checkT.type] || break_if_found[checkT.loc.type]) + return FALSE var/static/list/cardinal_cache = list("[NORTH]"=TRUE, "[EAST]"=TRUE, "[SOUTH]"=TRUE, "[WEST]"=TRUE) if(!cardinal_cache["[dir]"] || checkT.blocks_air || !CANATMOSPASS(sourceT, checkT)) continue found_turfs += checkT // Since checkT is connected, add it to the list to be processed /proc/create_area(mob/creator) - var/static/blacklisted_turfs = typecacheof(/turf/open/space) - var/static/blacklisted_areas = typecacheof(list( - /area/space, + // Passed into the above proc as list/break_if_found + var/static/area_or_turf_fail_types = typecacheof(list( + /turf/open/space, /area/shuttle, )) - var/list/turfs = detect_room(get_turf(creator), blacklisted_turfs) + // Ignore these areas and dont let people expand them. They can expand into them though + var/static/blacklisted_areas = typecacheof(list( + /area/space, + )) + var/list/turfs = detect_room(get_turf(creator), area_or_turf_fail_types) if(!turfs) to_chat(creator, "The new area must be completely airtight and not a part of a shuttle.") return @@ -50,7 +53,7 @@ var/list/areas = list("New Area" = /area) for(var/i in 1 to turfs.len) var/area/place = get_area(turfs[i]) - if(blacklisted_areas[place.type] || istype(place, /area/shuttle)) + if(blacklisted_areas[place.type]) continue if(!place.requires_power || place.noteleport || place.hidden) continue // No expanding powerless rooms etc diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 13f415823c..c590c844eb 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -350,7 +350,7 @@ /proc/flick_overlay(image/I, list/show_to, duration) for(var/client/C in show_to) C.images += I - addtimer(CALLBACK(GLOBAL_PROC, /.proc/remove_images_from_clients, I, show_to), duration, TIMER_CLIENT_TIME) + addtimer(CALLBACK(GLOBAL_PROC, /proc/remove_images_from_clients, I, show_to), duration, TIMER_CLIENT_TIME) /proc/flick_overlay_view(image/I, atom/target, duration) //wrapper for the above, flicks to everyone who can see the target atom var/list/viewing = list() diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index aed2e9c749..d2cb3baa6a 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1027,15 +1027,17 @@ GLOBAL_LIST_EMPTY(friendly_animal_types) return 0 //For creating consistent icons for human looking simple animals -/proc/get_flat_human_icon(icon_id, datum/job/J, datum/preferences/prefs, dummy_key, showDirs = GLOB.cardinals) +/proc/get_flat_human_icon(icon_id, datum/job/J, datum/preferences/prefs, dummy_key, showDirs = GLOB.cardinals, outfit_override = null) var/static/list/humanoid_icon_cache = list() if(!icon_id || !humanoid_icon_cache[icon_id]) var/mob/living/carbon/human/dummy/body = generate_or_wait_for_human_dummy(dummy_key) if(prefs) - prefs.copy_to(body) + prefs.copy_to(body,TRUE,FALSE) if(J) - J.equip(body, TRUE, FALSE) + J.equip(body, TRUE, FALSE, outfit_override = outfit_override) + else if (outfit_override) + body.equipOutfit(outfit_override,visualsOnly = TRUE) var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing") diff --git a/code/__HELPERS/level_traits.dm b/code/__HELPERS/level_traits.dm index b73a0aa83d..55ee069321 100644 --- a/code/__HELPERS/level_traits.dm +++ b/code/__HELPERS/level_traits.dm @@ -14,4 +14,4 @@ #define is_away_level(z) SSmapping.level_trait(z, ZTRAIT_AWAY) // If true, the singularity cannot strip away asteroid turf on this Z -#define is_planet_level(z) (GLOB.z_is_planet["z"]) +#define is_planet_level(z) SSmapping.level_trait(z, ZTRAIT_PLANET) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 51f0a28bd2..7d46553be1 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -266,65 +266,6 @@ GLOBAL_LIST_EMPTY(species_list) else return "unknown" -/* -Proc for attack log creation, because really why not -1 argument is the actor -2 argument is the target of action -3 is the description of action(like punched, throwed, or any other verb) -4 is the tool with which the action was made(usually item) 4 and 5 are very similar(5 have "by " before it, that it) and are separated just to keep things in a bit more in order -5 is additional information, anything that needs to be added -*/ - -/proc/add_logs(mob/user, mob/target, what_done, object=null, addition=null) - var/turf/attack_location = get_turf(target) - - var/is_mob_user = user && ismob(user) - var/is_mob_target = target && ismob(target) - - var/mob/living/living_target - - if(target && isliving(target)) - living_target = target - - var/hp =" " - if(living_target) - hp = " (NEWHP: [living_target.health]) " - - var/starget = "NON-EXISTENT SUBJECT" - if(target) - if(is_mob_target && target.key) - starget = "[target.name]([target.key])" - else - starget = "[target.name]" - - var/ssource = "NON-EXISTENT USER" //How!? - if(user) - if(is_mob_user && user.key) - ssource = "[user.name]([user.key])" - else - ssource = "[user.name]" - - var/sobject = "" - if(object) - sobject = "[object]" - if(addition) - addition = " [addition]" - - var/sattackloc = "" - if(attack_location) - sattackloc = "([attack_location.x],[attack_location.y],[attack_location.z])" - - if(is_mob_user) - var/message = "has [what_done] [starget][(sobject||addition) ? " with ":""][sobject][addition][hp][sattackloc]" - user.log_message(message, INDIVIDUAL_ATTACK_LOG) - - if(is_mob_target) - var/message = "has been [what_done] by [ssource][(sobject||addition) ? " with ":""][sobject][addition][hp][sattackloc]" - target.log_message(message, INDIVIDUAL_ATTACK_LOG) - - log_attack("[ssource] [what_done] [starget][(sobject||addition) ? " with ":""][sobject][addition][hp][sattackloc]") - - /proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks = null) if(!user || !target) return 0 @@ -573,42 +514,6 @@ Proc for attack log creation, because really why not else to_chat(M, message) - -/proc/log_talk(mob/user,message,logtype) - var/turf/say_turf = get_turf(user) - - var/sayloc = "" - if(say_turf) - sayloc = "([say_turf.x],[say_turf.y],[say_turf.z])" - - - var/logmessage = "[message] [sayloc]" - - switch(logtype) - - if(LOGDSAY) - log_dsay(logmessage) - if(LOGSAY) - log_say(logmessage) - if(LOGWHISPER) - log_whisper(logmessage) - if(LOGEMOTE) - log_emote(logmessage) - if(LOGPDA) - log_pda(logmessage) - if(LOGCHAT) - log_chat(logmessage) - if(LOGCOMMENT) - log_comment(logmessage) - if(LOGASAY) - log_adminsay(logmessage) - if(LOGOOC) - log_ooc(logmessage) - log_looc(logmessage) //CITADEL EDIT, logging LOOC because why not - else - warning("Invalid speech logging type detected. [logtype]. Defaulting to say") - log_say(logmessage) - //Used in chemical_mob_spawn. Generates a random mob based on a given gold_core_spawnable value. /proc/create_random_mob(spawn_location, mob_class = HOSTILE_SPAWN) var/static/list/mob_spawn_meancritters = list() // list of possible hostile mobs diff --git a/code/__HELPERS/radiation.dm b/code/__HELPERS/radiation.dm index 93dcdb4b0e..a570ab43ba 100644 --- a/code/__HELPERS/radiation.dm +++ b/code/__HELPERS/radiation.dm @@ -1,26 +1,24 @@ // A special GetAllContents that doesn't search past things with rad insulation -// The protection var only protects the things inside from being affected. -// The protecting object itself will get returned still. +// Components which return COMPONENT_BLOCK_RADIATION prevent further searching into that object's contents. The object itself will get returned still. // The ignore list makes those objects never return at all /proc/get_rad_contents(atom/location) + var/static/list/ignored_things = typecacheof(list( + /mob/dead, + /mob/camera, + /obj/effect, + /obj/docking_port, + /atom/movable/lighting_object, + /obj/item/projectile, + )) var/list/processing_list = list(location) . = list() while(processing_list.len) - var/static/list/ignored_things = typecacheof(list( - /mob/dead, - /mob/camera, - /obj/effect, - /obj/docking_port, - /atom/movable/lighting_object, - /obj/item/projectile - )) var/atom/thing = processing_list[1] processing_list -= thing if(ignored_things[thing.type]) continue . += thing - var/datum/component/rad_insulation/insulation = thing.GetComponent(/datum/component/rad_insulation) - if(insulation && insulation.protects) + if(SEND_SIGNAL(thing, COMSIG_ATOM_RAD_PROBE) & COMPONENT_BLOCK_RADIATION) continue processing_list += thing.contents @@ -43,5 +41,5 @@ log = TRUE if(log) var/turf/_source_T = isturf(source) ? source : get_turf(source) - log_game("Radiation pulse with intensity: [intensity] and range modifier: [range_modifier] in [AREACOORD(_source_T)] ") + log_game("Radiation pulse with intensity: [intensity] and range modifier: [range_modifier] in [loc_name(_source_T)] ") return TRUE \ No newline at end of file diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index e86c57ac24..84d4a40135 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -194,7 +194,7 @@ send2irc("Server", "Round just ended.") - if(length(CONFIG_GET(keyed_string_list/cross_server))) + if(length(CONFIG_GET(keyed_list/cross_server))) send_news_report() CHECK_TICK @@ -271,6 +271,10 @@ var/list/parts = list() var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED + if(GLOB.round_id) + var/statspage = CONFIG_GET(string/roundstatsurl) + var/info = statspage ? "[GLOB.round_id]" : GLOB.round_id + parts += "[GLOB.TAB]Round ID: [info]" parts += "[GLOB.TAB]Shift Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]" parts += "[GLOB.TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[popcount["station_integrity"]]%"]" var/total_players = GLOB.joined_player_list.len @@ -518,10 +522,20 @@ return objective_parts.Join("
") /datum/controller/subsystem/ticker/proc/save_admin_data() + if(IsAdminAdvancedProcCall()) + to_chat(usr, "Admin rank DB Sync blocked: Advanced ProcCall detected.") + return if(CONFIG_GET(flag/admin_legacy_system)) //we're already using legacy system so there's nothing to save return else if(load_admins(TRUE)) //returns true if there was a database failure and the backup was loaded from return + sync_ranks_with_db() + var/list/sql_admins = list() + for(var/datum/admins/A in GLOB.protected_admins) + var/sql_ckey = sanitizeSQL(A.owner.ckey) + var/sql_rank = sanitizeSQL(A.rank.name) + sql_admins = list(list("ckey" = "'[sql_ckey]'", "rank" = "'[sql_rank]'")) + SSdbcore.MassInsert(format_table_name("admin"), sql_admins, duplicate_key = TRUE) var/datum/DBQuery/query_admin_rank_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] p INNER JOIN [format_table_name("admin")] a ON p.ckey = a.ckey SET p.lastadminrank = a.rank") query_admin_rank_update.Execute() qdel(query_admin_rank_update) @@ -543,3 +557,29 @@ file_data["admins"]["[i]"] = A.rank.name fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/ticker/proc/update_everything_flag_in_db() + for(var/datum/admin_rank/R in GLOB.admin_ranks) + var/list/flags = list() + if(R.include_rights == R_EVERYTHING) + flags += "flags" + if(R.exclude_rights == R_EVERYTHING) + flags += "exclude_flags" + if(R.can_edit_rights == R_EVERYTHING) + flags += "can_edit_flags" + if(!flags.len) + continue + var/sql_rank = sanitizeSQL(R.name) + var/flags_to_check = flags.Join(" != [R_EVERYTHING] AND ") + " != [R_EVERYTHING]" + var/datum/DBQuery/query_check_everything_ranks = SSdbcore.NewQuery("SELECT flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] WHERE rank = '[sql_rank]' AND ([flags_to_check])") + if(!query_check_everything_ranks.Execute()) + qdel(query_check_everything_ranks) + return + if(query_check_everything_ranks.NextRow()) //no row is returned if the rank already has the correct flag value + var/flags_to_update = flags.Join(" = [R_EVERYTHING], ") + " = [R_EVERYTHING]" + var/datum/DBQuery/query_update_everything_ranks = SSdbcore.NewQuery("UPDATE [format_table_name("admin_ranks")] SET [flags_to_update] WHERE rank = '[sql_rank]'") + if(!query_update_everything_ranks.Execute()) + qdel(query_update_everything_ranks) + return + qdel(query_update_everything_ranks) + qdel(query_check_everything_ranks) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index f7aac6123e..be20918485 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -372,80 +372,6 @@ Turf and target are separate in case you want to teleport some distance from a t return "[round(units * 0.000001, 0.001)] MJ" return "[round(units * 0.000000001, 0.0001)] GJ" -/proc/key_name(whom, include_link = null, include_name = 1) - var/mob/M - var/client/C - var/key - var/ckey - var/fallback_name - - if(!whom) - return "*null*" - if(istype(whom, /client)) - C = whom - M = C.mob - key = C.key - ckey = C.ckey - else if(ismob(whom)) - M = whom - C = M.client - key = M.key - ckey = M.ckey - else if(istext(whom)) - key = whom - ckey = ckey(whom) - C = GLOB.directory[ckey] - if(C) - M = C.mob - else if(istype(whom,/datum/mind)) - var/datum/mind/mind = whom - key = mind.key - ckey = ckey(key) - if(mind.current) - M = mind.current - if(M.client) - C = M.client - else - fallback_name = mind.name - else - return "*invalid*" - - . = "" - - if(!ckey) - include_link = 0 - - if(key) - if(C && C.holder && C.holder.fakekey && !include_name) - if(include_link) - . += "" - . += "Administrator" - else - if(include_link) - . += "" - . += key - if(!C) - . += "\[DC\]" - - if(include_link) - . += "" - else - . += "*no key*" - - if(include_name) - if(M) - if(M.real_name) - . += "/([M.real_name])" - else if(M.name) - . += "/([M.name])" - else if(fallback_name) - . += "/([fallback_name])" - - return . - -/proc/key_name_admin(whom, include_name = 1) - return key_name(whom, 1, include_name) - /proc/get_mob_by_ckey(key) if(!key) return @@ -651,14 +577,9 @@ Turf and target are separate in case you want to teleport some distance from a t //Takes: Area type as a text string from a variable. //Returns: Instance for the area in the world. /proc/get_area_instance_from_text(areatext) - var/areainstance = null if(istext(areatext)) areatext = text2path(areatext) - for(var/V in GLOB.sortedAreas) - var/area/A = V - if(A.type == areatext) - areainstance = V - return areainstance + return GLOB.areas_by_type[areatext] //Takes: Area type as text string or as typepath OR an instance of the area. //Returns: A list of all areas of that type in the world. @@ -1349,7 +1270,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) var/ready_to_die = FALSE /mob/dview/Initialize() //Properly prevents this mob from gaining huds or joining any global lists - return + return INITIALIZE_HINT_NORMAL /mob/dview/Destroy(force = FALSE) if(!ready_to_die) @@ -1538,6 +1459,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) /obj/item/reagent_containers/food/snacks/soup, /obj/item/reagent_containers/food/snacks/grown, /obj/item/reagent_containers/food/snacks/grown/mushroom, + /obj/item/reagent_containers/food/snacks/grown/nettle, // base type /obj/item/reagent_containers/food/snacks/deepfryholder ) blocked |= typesof(/obj/item/reagent_containers/food/snacks/customizable) @@ -1545,7 +1467,10 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) return pick(typesof(/obj/item/reagent_containers/food/snacks) - blocked) /proc/get_random_drink() - return pick(subtypesof(/obj/item/reagent_containers/food/drinks)) + var/list/blocked = list(/obj/item/reagent_containers/food/drinks/soda_cans, + /obj/item/reagent_containers/food/drinks/bottle + ) + return pick(subtypesof(/obj/item/reagent_containers/food/drinks) - blocked) //For these two procs refs MUST be ref = TRUE format like typecaches! /proc/weakref_filter_list(list/things, list/refs)