diff --git a/baystation12.dme b/baystation12.dme index 4d2eac3f53c..3d52f63fb55 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -176,6 +176,7 @@ #include "code\datums\diseases\advance\symptoms\weight.dm" #include "code\datums\helper_datums\construction_datum.dm" #include "code\datums\helper_datums\events.dm" +#include "code\datums\helper_datums\getrev.dm" #include "code\datums\helper_datums\global_iterator.dm" #include "code\datums\helper_datums\teleport.dm" #include "code\datums\helper_datums\topic_input.dm" diff --git a/code/ZAS/Turf.dm b/code/ZAS/Turf.dm index 331c00dd37e..2dfcfcdf812 100644 --- a/code/ZAS/Turf.dm +++ b/code/ZAS/Turf.dm @@ -45,6 +45,45 @@ air_master.connect(sim, src) +/* + Simple heuristic for determining if removing the turf from it's zone may possibly partition the zone (A very bad thing). + Instead of analyzing the entire zone, we only check the nearest 3x3 turfs surrounding the src turf. + This implementation may produce false positives but it (hopefully) will not produce any false negatives. +*/ + +/turf/simulated/proc/can_safely_remove_from_zone() + #ifdef ZLEVELS + return 1 //not sure how to generalize this to multiz at the moment. + #else + + if(!zone) return 0 + + var/check_dirs = get_zone_neighbours(src) + var/unconnected_dirs = check_dirs + + for(var/dir in list(NORTHWEST, NORTHEAST, SOUTHEAST, SOUTHWEST)) + + //for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH) + if((dir & check_dirs) == dir) + //check that they are connected by the corner turf + var/connected_dirs = get_zone_neighbours(get_step(src, dir)) + if(connected_dirs && (dir & turn(connected_dirs, 180)) == dir) + unconnected_dirs &= ~dir //they are, so unflag the cardinals in question + + //it is safe to remove src from the zone if all cardinals are connected by corner turfs + return !unconnected_dirs + + #endif + +//helper for can_safely_remove_from_zone() +/turf/simulated/proc/get_zone_neighbours(turf/simulated/T) + . = 0 + if(istype(T) && T.zone) + for(var/dir in cardinal) + var/turf/simulated/other = get_step(T, dir) + if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1) + . |= dir + /turf/simulated/update_air_properties() if(zone && zone.invalid) @@ -60,7 +99,7 @@ if(zone) var/zone/z = zone - if(s_block & ZONE_BLOCKED) //Hacky, but prevents normal airlocks from rebuilding zones all the time + if(can_safely_remove_from_zone()) //Helps normal airlocks avoid rebuilding zones all the time z.remove(src) else z.rebuild() diff --git a/code/__HELPERS/logging.dm b/code/__HELPERS/logging.dm index 69d01e3d358..50f55703d34 100644 --- a/code/__HELPERS/logging.dm +++ b/code/__HELPERS/logging.dm @@ -81,3 +81,15 @@ /proc/log_misc(text) diary << "\[[time_stamp()]]MISC: [text][log_end]" + +//pretty print a direction bitflag, can be useful for debugging. +/proc/print_dir(var/dir) + var/list/comps = list() + if(dir & NORTH) comps += "NORTH" + if(dir & SOUTH) comps += "SOUTH" + if(dir & EAST) comps += "EAST" + if(dir & WEST) comps += "WEST" + if(dir & UP) comps += "UP" + if(dir & DOWN) comps += "DOWN" + + return english_list(comps, nothing_text="0", and_text="|", comma_text="|") diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 478700d5f82..216a45ee1c3 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -70,19 +70,19 @@ /proc/list2text(list/ls, sep) if (ls.len <= 1) // Early-out code for empty or singleton lists. return ls.len ? ls[1] : "" - + var/l = ls.len // Made local for sanic speed. var/i = 0 // Incremented every time a list index is accessed. - + if (sep <> null) // Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc... #define S1 sep, ls[++i] #define S4 S1, S1, S1, S1 #define S16 S4, S4, S4, S4 #define S64 S16, S16, S16, S16 - + . = "[ls[++i]]" // Make sure the initial element is converted to text. - + // Having the small concatenations come before the large ones boosted speed by an average of at least 5%. if (l-1 & 0x01) // 'i' will always be 1 here. . = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2. @@ -111,7 +111,7 @@ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64) - + #undef S64 #undef S16 #undef S4 @@ -122,9 +122,9 @@ #define S4 S1, S1, S1, S1 #define S16 S4, S4, S4, S4 #define S64 S16, S16, S16, S16 - + . = "[ls[++i]]" // Make sure the initial element is converted to text. - + if (l-1 & 0x01) // 'i' will always be 1 here. . += S1 // Append 1 element if the remaining elements are not a multiple of 2. if (l-i & 0x02) @@ -145,7 +145,7 @@ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64) - + #undef S64 #undef S16 #undef S4 @@ -165,11 +165,11 @@ proc/tg_list2text(list/list, glue=",") var/delim_len = length(delimiter) if (delim_len < 1) return list(text) - + . = list() var/last_found = 1 var/found - + do found = findtext(text, delimiter, last_found, 0) . += copytext(text, last_found, found) @@ -181,11 +181,11 @@ proc/tg_list2text(list/list, glue=",") var/delim_len = length(delimiter) if (delim_len < 1) return list(text) - + . = list() var/last_found = 1 var/found - + do found = findtextEx(text, delimiter, last_found, 0) . += copytext(text, last_found, found) @@ -325,3 +325,47 @@ proc/tg_list2text(list/list, glue=",") . = 0 else . = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307)) + +// Very ugly, BYOND doesn't support unix time and rounding errors make it really hard to convert it to BYOND time. +// returns "YYYY-MM-DD" by default +/proc/unix2date(timestamp, seperator = "-") + if(timestamp < 0) + return 0 //Do not accept negative values + + var/const/dayInSeconds = 86400 //60secs*60mins*24hours + var/const/daysInYear = 365 //Non Leap Year + var/const/daysInLYear = daysInYear + 1//Leap year + var/days = round(timestamp / dayInSeconds) //Days passed since UNIX Epoc + var/year = 1970 //Unix Epoc begins 1970-01-01 + var/tmpDays = days + 1 //If passed (timestamp < dayInSeconds), it will return 0, so add 1 + var/monthsInDays = list() //Months will be in here ***Taken from the PHP source code*** + var/month = 1 //This will be the returned MONTH NUMBER. + var/day //This will be the returned day number. + + while(tmpDays > daysInYear) //Start adding years to 1970 + year++ + if(isLeap(year)) + tmpDays -= daysInLYear + else + tmpDays -= daysInYear + + if(isLeap(year)) //The year is a leap year + monthsInDays = list(-1,30,59,90,120,151,181,212,243,273,304,334) + else + monthsInDays = list(0,31,59,90,120,151,181,212,243,273,304,334) + + var/mDays = 0; + var/monthIndex = 0; + + for(var/m in monthsInDays) + monthIndex++ + if(tmpDays > m) + mDays = m + month = monthIndex + + day = tmpDays - mDays //Setup the date + + return "[year][seperator][((month < 10) ? "0[month]" : month)][seperator][((day < 10) ? "0[day]" : day)]" + +/proc/isLeap(y) + return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0)) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 64b75c3fcec..af4d8ef2967 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -95,6 +95,7 @@ var/list/gamemode_cache = list() var/banappeals var/wikiurl var/forumurl + var/githuburl //Alert level description var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced." @@ -396,6 +397,9 @@ var/list/gamemode_cache = list() if ("forumurl") config.forumurl = value + if ("githuburl") + config.githuburl = value + if ("guest_jobban") config.guest_jobban = 1 diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm index 68bfdab74b8..f4b88f88502 100644 --- a/code/controllers/voting.dm +++ b/code/controllers/voting.dm @@ -336,7 +336,7 @@ datum/controller/vote . += "\t([config.allow_vote_mode?"Allowed":"Disallowed"])" . += "
  • " //extra antagonists - if(trialmin || (!antag_add_failed && config.allow_extra_antags)) + if(!antag_add_failed && config.allow_extra_antags) . += "Add Antagonist Type" else . += "Restart (Disallowed)" @@ -375,7 +375,7 @@ datum/controller/vote if(config.allow_vote_restart || usr.client.holder) initiate_vote("crew_transfer",usr.key) if("add_antagonist") - if(config.allow_extra_antags || usr.client.holder) + if(config.allow_extra_antags) initiate_vote("add_antagonist",usr.key) if("custom") if(usr.client.holder) diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm new file mode 100644 index 00000000000..da4192df257 --- /dev/null +++ b/code/datums/helper_datums/getrev.dm @@ -0,0 +1,39 @@ +var/global/datum/getrev/revdata = new() + +/datum/getrev + var/revision + var/date + var/showinfo + +/datum/getrev/New() + var/list/head_log = file2list(".git/logs/HEAD", "\n") + for(var/line=head_log.len, line>=1, line--) + if(head_log[line]) + var/list/last_entry = text2list(head_log[line], " ") + if(last_entry.len < 2) continue + revision = last_entry[2] + // Get date/time + if(last_entry.len >= 5) + var/unix_time = text2num(last_entry[5]) + if(unix_time) + date = unix2date(unix_time) + break + world.log << "Running revision:" + world.log << date + world.log << revision + return + +client/verb/showrevinfo() + set category = "OOC" + set name = "Show Server Revision" + set desc = "Check the current server code revision" + + if(revdata.revision) + src << "Server revision: [revdata.date]" + if(config.githuburl) + src << "[revdata.revision]" + else + src << revdata.revision + else + src << "Revision unknown" + return diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index fa408d1b8f3..ae6a8d08463 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -33,7 +33,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/weapon/grenade/smokebomb, /obj/item/weapon/grenade/smokebomb, /obj/item/weapon/grenade/smokebomb, - /obj/item/weapon/pen/paralysis, + /obj/item/weapon/pen/reagent/paralysis, /obj/item/weapon/grenade/chem_grenade/incendiary) cost = 20 containertype = /obj/structure/closet/crate @@ -348,7 +348,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/weapon/grenade/chem_grenade/antiweed, /obj/item/weapon/grenade/chem_grenade/antiweed) cost = 25 - containertype = /obj/structure/closet/crate/secure/hydrosec + containertype = /obj/structure/closet/crate/hydroponics containername = "Weed control crate" access = access_hydroponics group = "Hydroponics" diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm index 6c5f27fa070..bf16c5267d6 100644 --- a/code/defines/procs/admin.dm +++ b/code/defines/procs/admin.dm @@ -34,3 +34,14 @@ proc/admin_attacker_log_many_victims(var/mob/attacker, var/list/mob/victims, var for(var/mob/victim in victims) admin_attack_log(attacker, victim, attacker_message, victim_message, admin_message) + +proc/admin_inject_log(mob/attacker, mob/victim, obj/item/weapon, reagents, amount_transferred, violent=0) + if(violent) + violent = "violently " + else + violent = "" + admin_attack_log(attacker, + victim, + "used \the [weapon] to [violent]inject - [reagents] - [amount_transferred]u transferred", + "was [violent]injected with \the [weapon] - [reagents] - [amount_transferred]u transferred", + "used \the [weapon] to [violent]inject [reagents] ([amount_transferred]u transferred) into") diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm index 3f5d65d21da..adaa2b24f5d 100644 --- a/code/game/antagonist/station/cultist.dm +++ b/code/game/antagonist/station/cultist.dm @@ -69,6 +69,9 @@ var/datum/antagonist/cultist/cult player.equip_to_slot(T, slot) if(T.loc == player) break + var/obj/item/weapon/storage/S = locate() in player.contents + if(S && istype(S)) + T.loc = S /datum/antagonist/cultist/greet(var/datum/mind/player) if(!..()) diff --git a/code/game/antagonist/station/rogue_ai.dm b/code/game/antagonist/station/rogue_ai.dm index b8e653d1535..2a4fe862de4 100644 --- a/code/game/antagonist/station/rogue_ai.dm +++ b/code/game/antagonist/station/rogue_ai.dm @@ -73,4 +73,4 @@ var/datum/antagonist/rogue_ai/malf malf << "You are malfunctioning - you do not have to follow any laws!" malf << "For basic information about your abilities use command display-help" malf << "You may choose one special hardware piece to help you. This cannot be undone." - malf << "Good Luck!" \ No newline at end of file + malf << "Good luck!" \ No newline at end of file diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index a296fb8ecb9..755887ad83e 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -86,7 +86,7 @@ var/global/list/additional_antag_types = list() new/datum/uplink_item(/obj/item/weapon/soap/syndie, 1, "Subversive Soap", "SP"), new/datum/uplink_item(/obj/item/weapon/cane/concealed, 2, "Concealed Cane Sword", "CC"), new/datum/uplink_item(/obj/item/weapon/cartridge/syndicate, 3, "Detomatix PDA Cartridge", "DC"), - new/datum/uplink_item(/obj/item/weapon/pen/paralysis, 3, "Paralysis Pen", "PP"), + new/datum/uplink_item(/obj/item/weapon/pen/reagent/paralysis, 3, "Paralysis Pen", "PP"), new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/cigarette, 4, "Cigarette Kit", "BH"), new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/toxin, 4, "Random Toxin - Beaker", "RT") ), diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index 7fa102aeb8e..a7d54284bfc 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -66,8 +66,6 @@ H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat/science(H), slot_wear_suit) return 1 - - /datum/job/xenobiologist title = "Xenobiologist" flag = XENOBIOLOGIST @@ -78,8 +76,8 @@ spawn_positions = 2 supervisors = "the research director" selection_color = "#ffeeff" - access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology) - minimal_access = list(access_research, access_xenobiology) + access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_hydroponics) + minimal_access = list(access_research, access_xenobiology, access_hydroponics, access_tox_storage) alt_titles = list("Xenobotanist") minimal_player_age = 14 diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index e3b161b6fb1..83112ea778f 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -299,3 +299,4 @@ else qdel(S) ..() + return 1 diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 3e6f0d8e33a..2f6166905a1 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -267,7 +267,7 @@ if("cellremove") if(open && cell && !usr.get_active_hand()) - cell.updateicon() + cell.update_icon() usr.put_in_active_hand(cell) cell.add_fingerprint(usr) cell = null diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 683e6e12202..c3f617057c8 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -10,7 +10,7 @@ power_channel = EQUIP var/obj/item/weapon/cell/charging = null var/chargelevel = -1 - + /obj/machinery/cell_charger/update_icon() icon_state = "ccharger[charging ? 1 : 0]" @@ -27,11 +27,11 @@ chargelevel = newlevel else overlays.Cut() - + /obj/machinery/cell_charger/examine(mob/user) if(!..(user, 5)) return - + user << "There's [charging ? "a" : "no"] cell in the charger." if(charging) user << "Current charge: [charging.charge]" @@ -71,7 +71,7 @@ if(charging) usr.put_in_hands(charging) charging.add_fingerprint(user) - charging.updateicon() + charging.update_icon() src.charging = null user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.") @@ -84,7 +84,7 @@ return charging.loc = src.loc - charging.updateicon() + charging.update_icon() charging = null update_icon() user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.") @@ -103,11 +103,11 @@ if((stat & (BROKEN|NOPOWER)) || !anchored) update_use_power(0) return - + if (charging && !charging.fully_charged()) charging.give(active_power_usage*CELLRATE) update_use_power(2) - + update_icon() else update_use_power(1) diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm index 28bd3670838..e31a19b265b 100644 --- a/code/game/machinery/floodlight.dm +++ b/code/game/machinery/floodlight.dm @@ -7,28 +7,71 @@ density = 1 var/on = 0 var/obj/item/weapon/cell/high/cell = null - var/use = 5 + var/use = 200 // 200W light var/unlocked = 0 var/open = 0 var/brightness_on = 8 //can't remember what the maxed out value is /obj/machinery/floodlight/New() src.cell = new(src) + cell.maxcharge = 1000 + cell.charge = 1000 // 41minutes @ 200W ..() -/obj/machinery/floodlight/proc/updateicon() +/obj/machinery/floodlight/update_icon() + overlays.Cut() icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[on]" /obj/machinery/floodlight/process() - if(on && cell && cell.charge >= use) - cell.use(use) - else - on = 0 - updateicon() - set_light(0) - src.visible_message("[src] shuts down due to lack of power!") + if(!on) return + if(!cell || (cell.charge < (use * CELLRATE))) + turn_off(1) + return + + // If the cell is almost empty rarely "flicker" the light. Aesthetic only. + if((cell.percent() < 10) && prob(5)) + set_light(brightness_on/2, brightness_on/4) + spawn(20) + if(on) + set_light(brightness_on, brightness_on/2) + + cell.use(use*CELLRATE) + + +// Returns 0 on failure and 1 on success +/obj/machinery/floodlight/proc/turn_on(var/loud = 0) + if(!cell) + return 0 + if(cell.charge < (use * CELLRATE)) + return 0 + + on = 1 + set_light(brightness_on, brightness_on / 2) + update_icon() + if(loud) + visible_message("\The [src] turns on.") + return 1 + +/obj/machinery/floodlight/proc/turn_off(var/loud = 0) + on = 0 + set_light(0, 0) + update_icon() + if(loud) + visible_message("\The [src] shuts down.") + +/obj/machinery/floodlight/attack_ai(mob/user as mob) + if(istype(user, /mob/living/silicon/robot) && Adjacent(user)) + return attack_hand(user) + + if(on) + turn_off(1) + else + if(!turn_on(1)) + user << "You try to turn on \the [src] but it does not work." + + /obj/machinery/floodlight/attack_hand(mob/user as mob) if(open && cell) if(ishuman(user)) @@ -39,29 +82,22 @@ cell.loc = loc cell.add_fingerprint(user) - cell.updateicon() + cell.update_icon() src.cell = null on = 0 set_light(0) user << "You remove the power cell" - updateicon() + update_icon() return if(on) - on = 0 - user << "\blue You turn off the light" - set_light(0) + turn_off(1) else - if(!cell) - return - if(cell.charge <= 0) - return - on = 1 - user << "\blue You turn on the light" - set_light(brightness_on) + if(!turn_on(1)) + user << "You try to turn on \the [src] but it does not work." - updateicon() + update_icon() /obj/machinery/floodlight/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -94,4 +130,4 @@ W.loc = src cell = W user << "You insert the power cell." - updateicon() + update_icon() diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index 9bfa0e1c5dd..9016836274a 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -204,7 +204,7 @@ item_quants[O.name]++ else item_quants[O.name] = 1 - user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].") + user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].") nanomanager.update_uis(src) diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index c5d389c66e3..14a081ee2e4 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -121,7 +121,7 @@ if("cellremove") if(panel_open && cell && !usr.get_active_hand()) usr.visible_message("\blue [usr] removes \the [cell] from \the [src].", "\blue You remove \the [cell] from \the [src].") - cell.updateicon() + cell.update_icon() usr.put_in_hands(cell) cell.add_fingerprint(usr) cell = null diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 684c761840a..fe2c0a61102 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -91,7 +91,7 @@ REAGENT SCANNER if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") usr << "\red You don't have the dexterity to do this!" return - user.visible_message(" [user] has analyzed [M]'s vitals."," You have analyzed [M]'s vitals.") + user.visible_message(" [user] has analyzed [M]'s vitals."," You have analyzed [M]'s vitals.") if (!istype(M, /mob/living/carbon) || ishuman(M)) //these sensors are designed for organic life diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm index b28e9b62f60..7f9f7e2b988 100644 --- a/code/game/objects/items/devices/suit_cooling.dm +++ b/code/game/objects/items/devices/suit_cooling.dm @@ -5,56 +5,56 @@ icon = 'icons/obj/device.dmi' icon_state = "suitcooler0" slot_flags = SLOT_BACK //you can carry it on your back if you want, but it won't do anything unless attached to suit storage - + //copied from tank.dm flags = CONDUCT force = 5.0 throwforce = 10.0 throw_speed = 1 throw_range = 4 - + origin_tech = list(TECH_MAGNET = 2, TECH_MATERIAL = 2) - + var/on = 0 //is it turned on? var/cover_open = 0 //is the cover open? var/obj/item/weapon/cell/cell var/max_cooling = 12 //in degrees per second - probably don't need to mess with heat capacity here var/charge_consumption = 16.6 //charge per second at max_cooling var/thermostat = T20C - + //TODO: make it heat up the surroundings when not in space /obj/item/device/suit_cooling_unit/New() processing_objects |= src - + cell = new/obj/item/weapon/cell() //comes with the crappy default power cell - high-capacity ones shouldn't be hard to find cell.loc = src /obj/item/device/suit_cooling_unit/process() - if (!on || !cell) + if (!on || !cell) return - + if (!ismob(loc)) return - + if (!attached_to_suit(loc)) //make sure they have a suit and we are attached to it return - + var/mob/living/carbon/human/H = loc - + var/efficiency = 1 - H.get_pressure_weakness() //you need to have a good seal for effective cooling var/env_temp = get_environment_temperature() //wont save you from a fire var/temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling) - + if (temp_adj < 0.5) //only cools, doesn't heat, also we don't need extreme precision return - + var/charge_usage = (temp_adj/max_cooling)*charge_consumption - + H.bodytemperature -= temp_adj*efficiency - + cell.use(charge_usage) - + if(cell.charge <= 0) turn_off() @@ -70,22 +70,22 @@ var/turf/T = get_turf(src) if(istype(T, /turf/space)) return 0 //space has no temperature, this just makes sure the cooling unit works in space - + var/datum/gas_mixture/environment = T.return_air() if (!environment) return 0 - + return environment.temperature /obj/item/device/suit_cooling_unit/proc/attached_to_suit(mob/M) - if (!ishuman(M)) + if (!ishuman(M)) return 0 - + var/mob/living/carbon/human/H = M - + if (!H.wear_suit || H.s_store != src) return 0 - + return 1 /obj/item/device/suit_cooling_unit/proc/turn_on() @@ -93,7 +93,7 @@ return if(cell.charge <= 0) return - + on = 1 updateicon() @@ -112,7 +112,7 @@ cell.loc = get_turf(loc) cell.add_fingerprint(user) - cell.updateicon() + cell.update_icon() user << "You remove the [src.cell]." src.cell = null @@ -149,7 +149,7 @@ user << "You insert the [cell]." updateicon() return - + return ..() /obj/item/device/suit_cooling_unit/proc/updateicon() @@ -164,7 +164,7 @@ /obj/item/device/suit_cooling_unit/examine(mob/user) if(!..(user, 1)) return - + if (on) if (attached_to_suit(src.loc)) user << "It's switched on and running." @@ -172,13 +172,13 @@ user << "It's switched on, but not attached to anything." else user << "It is switched off." - + if (cover_open) if(cell) user << "The panel is open, exposing the [cell]." else user << "The panel is open." - + if (cell) user << "The charge meter reads [round(cell.percent())]%." else diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index dfc53d3a874..afe50bc2b76 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -4,26 +4,40 @@ Cyborg Spec Items ***********************************************************************/ //Might want to move this into several files later but for now it works here +// Consider changing this to a child of the stun baton class. ~Z /obj/item/borg/stun name = "electrified arm" icon = 'icons/obj/decals.dmi' icon_state = "shock" - attack(mob/M as mob, mob/living/silicon/robot/user as mob) - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") +/obj/item/borg/stun/attack(var/mob/living/M, var/mob/living/silicon/robot/user) - user.cell.charge -= 30 + if(!istype(M)) + return - M.Weaken(5) - if (M.stuttering < 5) - M.stuttering = 5 - M.Stun(5) + // How the Hell. + if(!istype(user)) + var/mob/living/temp = user + if(istype(temp)) + temp.drop_from_inventory(src) + qdel(src) + return - for(var/mob/O in viewers(M, null)) - if (O.client) - O.show_message("\red [user] has prodded [M] with an electrically-charged arm!", 1, "\red You hear someone fall", 2) + M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") + msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") + + if(!user.cell || !user.cell.checked_use(1250)) //Slightly more than a baton. + user.visible_message("\The [user] has prodded \the [M] with its arm!") + return + + if (M.stuttering < 5) + M.stuttering = 5 + M.stun_effect_act(0, 70, check_zone(user.zone_sel.selecting), src) + user.visible_message("\The [user] has prodded \the [M] with \a [src]!") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + H.forcesay(hit_appends) /obj/item/borg/overdrive name = "overdrive" diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 7fc96efceea..82a54339639 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -223,10 +223,10 @@ */ //attempts to transfer amount to S, and returns the amount actually transferred -/obj/item/stack/proc/transfer_to(obj/item/stack/S, var/tamount=null) +/obj/item/stack/proc/transfer_to(obj/item/stack/S, var/tamount=null, var/type_verified) if (!get_amount()) return 0 - if (stacktype != S.stacktype) + if ((stacktype != S.stacktype) && !type_verified) return 0 if (isnull(tamount)) tamount = src.get_amount() @@ -240,7 +240,6 @@ transfer_fingerprints_to(S) if(blood_DNA) S.blood_DNA |= blood_DNA - //todo bloody overlay return transfer return 0 @@ -314,10 +313,8 @@ return /obj/item/stack/attackby(obj/item/W as obj, mob/user as mob) - ..() if (istype(W, /obj/item/stack)) var/obj/item/stack/S = W - if (user.get_inactive_hand()==src) src.transfer_to(S, 1) else @@ -328,7 +325,8 @@ S.interact(usr) if (src && usr.machine==src) src.interact(usr) - else return ..() + else + return ..() /* * Recipe datum diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 085e23f9b69..b33d72f6fbc 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -11,7 +11,7 @@ if("stealth") new /obj/item/weapon/gun/energy/crossbow(src) - new /obj/item/weapon/pen/paralysis(src) + new /obj/item/weapon/pen/reagent/paralysis(src) new /obj/item/device/chameleon(src) return diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index 63bbde044ca..f8708d79254 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -73,7 +73,7 @@ else if(istype(W, /obj/item/weapon/screwdriver)) if(bcell) - bcell.updateicon() + bcell.update_icon() bcell.loc = get_turf(src.loc) bcell = null user << "You remove the cell from the [src]." diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm index a5ad84c20eb..3647d565f7e 100644 --- a/code/game/objects/structures/noticeboard.dm +++ b/code/game/objects/structures/noticeboard.dm @@ -21,7 +21,7 @@ if(notices < 5) O.add_fingerprint(user) add_fingerprint(user) - user.drop_item() + user.drop_from_inventory(O) O.loc = src notices++ icon_state = "nboard0[notices]" //update sprite @@ -29,13 +29,22 @@ else user << "You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached." -/obj/structure/noticeboard/attack_hand(user as mob) - var/dat = "Noticeboard
    " - for(var/obj/item/weapon/paper/P in src) - dat += "[P.name] Write Remove
    " - user << browse("Notices[dat]","window=noticeboard") - onclose(user, "noticeboard") +/obj/structure/noticeboard/attack_hand(var/mob/user) + examine(user) +// Since Topic() never seems to interact with usr on more than a superficial +// level, it should be fine to let anyone mess with the board other than ghosts. +/obj/structure/noticeboard/examine(var/mob/user) + if(!user) + user = usr + if(user.Adjacent(src)) + var/dat = "Noticeboard
    " + for(var/obj/item/weapon/paper/P in src) + dat += "[P.name] Write Remove
    " + user << browse("Notices[dat]","window=noticeboard") + onclose(user, "noticeboard") + else + ..() /obj/structure/noticeboard/Topic(href, href_list) ..() @@ -44,18 +53,16 @@ if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open return var/obj/item/P = locate(href_list["remove"]) - if((P && P.loc == src)) + if(P && P.loc == src) P.loc = get_turf(src) //dump paper on the floor because you're a clumsy fuck P.add_fingerprint(usr) add_fingerprint(usr) notices-- icon_state = "nboard0[notices]" - if(href_list["write"]) if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open return var/obj/item/P = locate(href_list["write"]) - if((P && P.loc == src)) //ifthe paper's on the board if(istype(usr.r_hand, /obj/item/weapon/pen)) //and you're holding a pen add_fingerprint(usr) @@ -66,14 +73,9 @@ P.attackby(usr.l_hand, usr) else usr << "You'll need something to write with!" - if(href_list["read"]) var/obj/item/weapon/paper/P = locate(href_list["read"]) if((P && P.loc == src)) - if(!( istype(usr, /mob/living/carbon/human) )) - usr << browse("[P.name][stars(P.info)]", "window=[P.name]") - onclose(usr, "[P.name]") - else - usr << browse("[P.name][P.info]", "window=[P.name]") - onclose(usr, "[P.name]") + usr << browse("[P.name][P.info]", "window=[P.name]") + onclose(usr, "[P.name]") return diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 7cbd14cb21c..81df901b38b 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -20,7 +20,7 @@ armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 20) min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0.1 + siemens_coefficient = 0.2 permeability_coefficient = 0.1 unacidable = 1 diff --git a/code/modules/clothing/spacesuits/rig/suits/ert.dm b/code/modules/clothing/spacesuits/rig/suits/ert.dm index 70c21d51089..c46b019a4d2 100644 --- a/code/modules/clothing/spacesuits/rig/suits/ert.dm +++ b/code/modules/clothing/spacesuits/rig/suits/ert.dm @@ -29,8 +29,8 @@ desc = "A suit worn by the engineering division of a NanoTrasen Emergency Response Team. Has orange highlights. Armoured and space ready." suit_type = "ERT engineer" icon_state = "ert_engineer_rig" - - glove_type = /obj/item/clothing/gloves/rig/ert_engineer + armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 100, rad = 100) + siemens_coefficient = 0 initial_modules = list( /obj/item/rig_module/ai_container, @@ -39,10 +39,6 @@ /obj/item/rig_module/device/rcd ) -/obj/item/clothing/gloves/rig/ert_engineer - name = "insulated gauntlets" - siemens_coefficient = 0 - /obj/item/weapon/rig/ert/medical name = "ERT-M suit control module" desc = "A suit worn by the medical division of a NanoTrasen Emergency Response Team. Has white highlights. Armoured and space ready." diff --git a/code/modules/clothing/under/accessories/badges.dm b/code/modules/clothing/under/accessories/badges.dm index bb6613582ec..cc6a6f99656 100644 --- a/code/modules/clothing/under/accessories/badges.dm +++ b/code/modules/clothing/under/accessories/badges.dm @@ -43,7 +43,8 @@ /obj/item/clothing/accessory/badge/holo name = "holobadge" desc = "This glowing blue badge marks the holder as THE LAW." - var/emagged = 0 //Emagging removes Sec check. + icon_state = "holobadge" + var/emagged //Emagging removes Sec check. /obj/item/clothing/accessory/badge/holo/cord icon_state = "holobadge-cord" diff --git a/code/modules/events/viral_infection.dm b/code/modules/events/viral_infection.dm index 639cea4d5e9..2eb6121f083 100644 --- a/code/modules/events/viral_infection.dm +++ b/code/modules/events/viral_infection.dm @@ -1,3 +1,5 @@ +/var/global/list/event_viruses = list() // so that event viruses are kept around for admin logs, rather than being GCed + datum/event/viral_infection var/list/viruses = list() @@ -40,10 +42,30 @@ datum/event/viral_infection/start() if(!candidates.len) return candidates = shuffle(candidates)//Incorporating Donkie's list shuffle + var/list/used_viruses = list() + var/list/used_candidates = list() severity = max(EVENT_LEVEL_MUNDANE, severity - 1) var/actual_severity = severity * rand(1, 3) while(actual_severity > 0 && candidates.len) var/datum/disease2/disease/D = pick(viruses) infect_mob(candidates[1], D.getcopy()) + used_candidates += candidates[1] candidates.Remove(candidates[1]) actual_severity-- + used_viruses |= D + + event_viruses |= used_viruses + var/list/used_viruses_links = list() + var/list/used_viruses_text = list() + for(var/datum/disease2/disease/D in used_viruses) + used_viruses_links += "[D.name()]" + used_viruses_text += D.name() + + var/list/used_candidates_links = list() + var/list/used_candidates_text = list() + for(var/mob/M in used_candidates) + used_candidates_links += key_name_admin(M) + used_candidates_text += key_name(M) + + log_admin("Virus event affecting [english_list(used_candidates_text)] started; Viruses: [english_list(used_viruses_text)]") + message_admins("Virus event affecting [english_list(used_candidates_links)] started; Viruses: [english_list(used_viruses_links)]") diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm index 2d088658acd..57579cdb72b 100644 --- a/code/modules/hydroponics/spreading/spreading.dm +++ b/code/modules/hydroponics/spreading/spreading.dm @@ -24,6 +24,8 @@ vine.process() message_admins("Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])") + return + message_admins("Event: Spacevines failed to find a viable turf.") /obj/effect/dead_plant anchored = 1 @@ -56,7 +58,7 @@ var/growth_threshold = 0 var/growth_type = 0 var/max_growth = 0 - + var/sampled var/list/neighbors = list() var/obj/effect/plant/parent var/datum/seed/seed @@ -233,8 +235,13 @@ if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel)) if(!seed) - user << "There is nothing to take a sample from." + user << "There is nothing to take a sample from." return + if(sampled) + user << "You cannot take another sample from \the [src]." + return + if(prob(70)) + sampled = 1 seed.harvest(user,0,1) health -= (rand(3,5)*10) else diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index cc80c3bed42..8a5f584b4ff 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -5,6 +5,8 @@ w_class = 3.0 throw_speed = 3 throw_range = 3 + max_amount = 50 + var/default_type = DEFAULT_WALL_MATERIAL var/material/material var/perunit @@ -45,7 +47,13 @@ matter[material.name] = SHEET_MATERIAL_AMOUNT return 1 -obj/item/stack/material/iron +/obj/item/stack/material/transfer_to(obj/item/stack/S, var/tamount=null, var/type_verified) + var/obj/item/stack/material/M = S + if(!istype(M) || material.name != M.material.name) + return 0 + ..(S,tamount,1) + +/obj/item/stack/material/iron name = "iron" icon_state = "sheet-silver" default_type = "iron" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index f0af6e14645..2162e3488ac 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -249,7 +249,7 @@ var/mob/living/carbon/human/H = src H.w_uniform.add_fingerprint(M) - if(player_logged) + if(!client || !key || player_logged) M.visible_message("[M] shakes [src] trying to wake [t_him] up!", \ "You shake [src], but they do not respond... Maybe they have S.S.D?") else if(lying || src.sleeping) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index d6510c2bf84..88c90d4349c 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -246,7 +246,7 @@ if(!key) msg += "[t_He] [t_is] fast asleep. It doesn't look like they are waking up anytime soon.\n" else if(!client) - msg += "[t_He] [t_has] suddenly fallen asleep.\n" + msg += "[t_He] [t_is] fast asleep.\n" var/list/wound_flavor_text = list() var/list/is_destroyed = list() @@ -256,7 +256,7 @@ var/list/organ_data = species.has_limbs[organ_tag] var/organ_descriptor = organ_data["descriptor"] - is_destroyed["[organ_data["descriptor"]]"] = 1 + is_destroyed["organ_descriptor"] = 1 var/obj/item/organ/external/E = organs_by_name[organ_tag] if(!E) @@ -264,6 +264,7 @@ else if(E.is_stump()) wound_flavor_text["[organ_descriptor]"] = "[t_He] has a stump where [t_his] [organ_descriptor] should be.\n" else + is_destroyed["organ_descriptor"] = 0 continue for(var/obj/item/organ/external/temp in organs) @@ -277,7 +278,7 @@ else if(temp.wounds.len > 0 || temp.open) wound_flavor_text["[temp.name]"] = "[t_He] has [temp.get_wounds_desc()] on [t_his] [temp.name].
    " if(temp.status & ORGAN_BLEEDING) - is_bleeding["[temp.name]"] = 1 + is_bleeding["[temp.name]"] = "[capitalize(t_his)] [temp.name] is bleeding!
    " else wound_flavor_text["[temp.name]"] = "" if(temp.dislocated == 2) @@ -287,41 +288,56 @@ //Handles the text strings being added to the actual description. //If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext. + + // *********************************************************************************** + // THIS NEEDS TO BE ENTIRELY REWRITTEN. Commenting out for now, BADLY NEEDS REWRITING. + // *********************************************************************************** + + /* var/display_chest = 0 var/display_shoes = 0 var/display_gloves = 0 + if(wound_flavor_text["head"] && (is_destroyed["head"] || (!skipmask && !(wear_mask && istype(wear_mask, /obj/item/clothing/mask/gas))))) msg += wound_flavor_text["head"] else if(is_bleeding["head"]) msg += "[src] has blood running down [t_his] face!\n" + if(wound_flavor_text["upper body"] && !w_uniform && !skipjumpsuit) //No need. A missing chest gibs you. msg += wound_flavor_text["upper body"] else if(is_bleeding["upper body"]) display_chest = 1 + if(wound_flavor_text["left arm"] && (is_destroyed["left arm"] || (!w_uniform && !skipjumpsuit))) msg += wound_flavor_text["left arm"] else if(is_bleeding["left arm"]) display_chest = 1 + if(wound_flavor_text["left hand"] && (is_destroyed["left hand"] || (!gloves && !skipgloves))) msg += wound_flavor_text["left hand"] else if(is_bleeding["left hand"]) display_gloves = 1 + if(wound_flavor_text["right arm"] && (is_destroyed["right arm"] || (!w_uniform && !skipjumpsuit))) msg += wound_flavor_text["right arm"] else if(is_bleeding["right arm"]) display_chest = 1 + if(wound_flavor_text["right hand"] && (is_destroyed["right hand"] || (!gloves && !skipgloves))) msg += wound_flavor_text["right hand"] else if(is_bleeding["right hand"]) display_gloves = 1 + if(wound_flavor_text["lower body"] && (is_destroyed["lower body"] || (!w_uniform && !skipjumpsuit))) msg += wound_flavor_text["lower body"] else if(is_bleeding["lower body"]) display_chest = 1 + if(wound_flavor_text["left leg"] && (is_destroyed["left leg"] || (!w_uniform && !skipjumpsuit))) msg += wound_flavor_text["left leg"] else if(is_bleeding["left leg"]) display_chest = 1 + if(wound_flavor_text["left foot"]&& (is_destroyed["left foot"] || (!shoes && !skipshoes))) msg += wound_flavor_text["left foot"] else if(is_bleeding["left foot"]) @@ -334,19 +350,25 @@ msg += wound_flavor_text["right foot"] else if(is_bleeding["right foot"]) display_shoes = 1 + if(display_chest) msg += "[src] has blood soaking through from under [t_his] clothing!\n" if(display_shoes) msg += "[src] has blood running from [t_his] shoes!\n" if(display_gloves) msg += "[src] has blood running from under [t_his] gloves!\n" + */ + for(var/limb in wound_flavor_text) + msg += wound_flavor_text[limb] + is_bleeding[limb] = null + for(var/limb in is_bleeding) + msg += is_bleeding[limb] for(var/implant in get_visible_implants(0)) msg += "[src] has \a [implant] sticking out of [t_his] flesh!\n" if(digitalcamo) msg += "[t_He] [t_is] repulsively uncanny!\n" - if(hasHUD(usr,"security")) var/perpname = "wot" var/criminal = "None" diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 6c92db09fec..f2c64fa52ad 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -72,7 +72,18 @@ var/obj/item/organ/external/E = organs_by_name[limb_tag] if(!E || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD))) stance_damage += 2 // let it fail even if just foot&leg - else if (E.is_malfunctioning() || E.is_broken() || !E.is_usable()) + else if (E.is_malfunctioning()) + //malfunctioning only happens intermittently so treat it as a missing limb when it procs + stance_damage += 2 + if(prob(10)) + visible_message("\The [src]'s [E.name] [pick("twitches", "shudders")] and sparks!") + var/datum/effect/effect/system/spark_spread/spark_system = new () + spark_system.set_up(5, 0, src) + spark_system.attach(src) + spark_system.start() + spawn(10) + qdel(spark_system) + else if (E.is_broken() || !E.is_usable()) stance_damage += 1 else if (E.is_dislocated()) stance_damage += 0.5 @@ -94,7 +105,27 @@ Weaken(5) //can't emote while weakened, apparently. /mob/living/carbon/human/proc/handle_grasp() + if(!l_hand && !r_hand) + return + // You should not be able to pick anything up, but stranger things have happened. + if(l_hand) + for(var/limb_tag in list("l_hand","l_arm")) + var/obj/item/organ/external/E = get_organ(limb_tag) + if(!E) + visible_message("Lacking a functioning left hand, \the [src] drops \the [l_hand].") + drop_from_inventory(l_hand) + break + + if(r_hand) + for(var/limb_tag in list("r_hand","r_arm")) + var/obj/item/organ/external/E = get_organ(limb_tag) + if(!E) + visible_message("Lacking a functioning right hand, \the [src] drops \the [r_hand].") + drop_from_inventory(r_hand) + break + + // Check again... if(!l_hand && !r_hand) return diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 896f57878cd..89f071d482a 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -941,7 +941,7 @@ if(status_flags & GODMODE) return 0 //SSD check, if a logged player is awake put them back to sleep! - if(player_logged && sleeping < 2) + if((!client || !key || player_logged) && sleeping < 2) sleeping = 2 if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP @@ -1362,11 +1362,11 @@ var/obj/item/clothing/glasses/welding/O = glasses if(!O.up) found_welder = 1 - else if(istype(head, /obj/item/clothing/head/welding)) + if(!found_welder && istype(head, /obj/item/clothing/head/welding)) var/obj/item/clothing/head/welding/O = head if(!O.up) found_welder = 1 - else if(istype(back, /obj/item/weapon/rig)) + if(!found_welder && istype(back, /obj/item/weapon/rig)) var/obj/item/weapon/rig/O = back if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES)) if((O.offline && O.offline_vision_restriction == 1) || (!O.offline && O.vision_restriction == 1)) diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index d859810ea16..84611ecb95c 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -194,7 +194,7 @@ wrapped = A.cell A.cell.add_fingerprint(user) - A.cell.updateicon() + A.cell.update_icon() A.cell.loc = src A.cell = null @@ -211,7 +211,7 @@ wrapped = A.cell A.cell.add_fingerprint(user) - A.cell.updateicon() + A.cell.update_icon() A.updateicon() A.cell.loc = src A.cell = null diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 27c08746bc0..e71db5693d1 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -733,7 +733,7 @@ if(opened && !wiresexposed && (!istype(user, /mob/living/silicon))) var/datum/robot_component/cell_component = components["power cell"] if(cell) - cell.updateicon() + cell.update_icon() cell.add_fingerprint(user) user.put_in_active_hand(cell) user << "You remove \the [cell]." diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 359562063d9..527ce35df28 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -425,6 +425,9 @@ var/global/list/robot_modules = list( T.update_icon() else T.charge_tick = 0 + var/obj/item/weapon/melee/baton/robot/B = locate() in src.modules + if(B && B.bcell) + B.bcell.give(amount) /obj/item/weapon/robot_module/janitor name = "janitorial robot module" diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm index 203159f3c68..147edb1afe3 100644 --- a/code/modules/mob/typing_indicator.dm +++ b/code/modules/mob/typing_indicator.dm @@ -5,14 +5,17 @@ mob/var/typing mob/var/last_typed mob/var/last_typed_time -var/global/image/typing_indicator +mob/var/obj/effect/decal/typing_indicator /mob/proc/set_typing_indicator(var/state) if(!typing_indicator) - typing_indicator = image('icons/mob/talk.dmi',null,"typing") + typing_indicator = new + typing_indicator.icon = 'icons/mob/talk.dmi' + typing_indicator.icon_state = "typing" - if(client) + if(client && !stat) + typing_indicator.invisibility = invisibility if(client.prefs.toggles & SHOW_TYPING) overlays -= typing_indicator else diff --git a/code/modules/nano/nanomanager.dm b/code/modules/nano/nanomanager.dm index 2a89779e929..f6325fd4f71 100644 --- a/code/modules/nano/nanomanager.dm +++ b/code/modules/nano/nanomanager.dm @@ -55,8 +55,9 @@ ui.push_data(data) return ui else - //testing("nanomanager/try_update_ui mob [user.name] [src_object:name] [ui_key] [force_open] - forcing opening of ui") - ui.close() + ui.reinitialise(new_initial_data=data) + return ui + return null /** @@ -164,10 +165,10 @@ else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list)) open_uis[src_object_key][ui.ui_key] = list(); - ui.user.open_uis.Add(ui) + ui.user.open_uis |= ui var/list/uis = open_uis[src_object_key][ui.ui_key] - uis.Add(ui) - processing_uis.Add(ui) + uis |= ui + processing_uis |= ui //testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]") /** @@ -220,7 +221,7 @@ */ /datum/nanomanager/proc/user_transferred(var/mob/oldMob, var/mob/newMob) //testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]") - if (!oldMob || isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0) + if (!oldMob || isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0) //testing("nanomanager/user_transferred mob [oldMob.name] has no open uis") return 0 // has no open uis diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index f53fc98497e..f134d5d93b4 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -405,6 +405,18 @@ nanoui is used to open and update nano browser uis //onclose(user, window_id) nanomanager.ui_opened(src) + /** + * Reinitialise this UI, potentially with a different template and/or initial data + * + * @return nothing + */ +/datum/nanoui/proc/reinitialise(template, new_initial_data) + if(template) + add_template("main", template) + if(new_initial_data) + set_initial_data(new_initial_data) + open() + /** * Close this UI * diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 8cef1b9cc22..2d4ca50d907 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -48,6 +48,36 @@ var/can_grasp var/can_stand +/obj/item/organ/external/attack_self(var/mob/user) + if(!contents.len) + return ..() + var/list/removable_objects = list() + for(var/obj/item/organ/external/E in (contents + src)) + if(!istype(E)) + continue + for(var/obj/item/I in E.contents) + if(istype(I,/obj/item/organ)) + continue + removable_objects |= I + if(!removable_objects.len) + return ..() + var/obj/item/I = pick(removable_objects) + if(!istype(I)) + return ..() + I.loc = get_turf(user) + if(!(user.l_hand && user.r_hand)) + user.put_in_hands(I) + user.visible_message("\The [user] rips \the [I] out of \the [src]!") + +/obj/item/organ/external/examine() + ..() + if(in_range(usr, src) || istype(usr, /mob/dead/observer)) + for(var/obj/item/I in contents) + if(istype(I, /obj/item/organ)) + continue + usr << "There is \a [I] sticking out of it." + return + /obj/item/organ/external/attackby(obj/item/weapon/W as obj, mob/user as mob) switch(stage) if(0) @@ -687,6 +717,9 @@ Note that amputating the affected organ does in fact remove the infection from t dir = 2 if(DROPLIMB_BURN) new /obj/effect/decal/cleanable/ash(get_turf(victim)) + for(var/obj/item/I in src) + if(I.w_class > 2 && !istype(I,/obj/item/organ)) + I.loc = get_turf(src) qdel(src) if(DROPLIMB_BLUNT) var/obj/effect/decal/cleanable/blood/gibs/gore = new owner.species.single_gib_type(get_turf(victim)) @@ -701,6 +734,14 @@ Note that amputating the affected organ does in fact remove the infection from t I.removed() if(istype(loc,/turf)) I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + + for(var/obj/item/I in src) + if(I.w_class <= 2) + qdel(I) + continue + I.loc = get_turf(src) + I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + qdel(src) /**************************************************** @@ -861,7 +902,7 @@ Note that amputating the affected organ does in fact remove the infection from t W.add_blood(owner) if(ismob(W.loc)) var/mob/living/H = W.loc - H.drop_item() + H.drop_from_inventory(W) W.loc = owner /obj/item/organ/external/removed(var/mob/living/user, var/ignore_children) @@ -876,8 +917,14 @@ Note that amputating the affected organ does in fact remove the infection from t status |= ORGAN_DESTROYED victim.bad_external_organs -= src - for(var/implant in implants) //todo: check if this can be left alone - qdel(implant) + for(var/obj/item/implant in implants) + if(!istype(implant)) + return + if(implant.w_class <= 2) + qdel(implant) + else + implant.loc = src + implants.Cut() // Attached organs also fly off. if(!ignore_children) @@ -885,6 +932,8 @@ Note that amputating the affected organ does in fact remove the infection from t O.removed() if(O) O.loc = src + for(var/obj/item/I in O.contents) + I.loc = src // Grab all the internal giblets too. for(var/obj/item/organ/organ in internal_organs) diff --git a/code/modules/organs/subtypes/diona.dm b/code/modules/organs/subtypes/diona.dm index f08a5a93711..873d2b47661 100644 --- a/code/modules/organs/subtypes/diona.dm +++ b/code/modules/organs/subtypes/diona.dm @@ -1,11 +1,21 @@ /proc/spawn_diona_nymph_from_organ(var/obj/item/organ/organ) if(!istype(organ)) - return + return 0 + + //This is a terrible hack and I should be ashamed. + var/datum/seed/diona = plant_controller.seeds["diona"] + if(!diona) + return 0 + spawn(1) // So it has time to be thrown about by the gib() proc. var/mob/living/carbon/alien/diona/D = new(get_turf(organ)) var/datum/ghosttrap/plant/P = get_ghost_trap("living plant") P.request_player(D, "A diona nymph has split off from its gestalt. ") - qdel(organ) + spawn(60) + if(D) + if(!D.ckey || !D.client) + D.death() + return 1 /obj/item/organ/external/diona name = "tendril" @@ -123,16 +133,13 @@ //DIONA ORGANS. /obj/item/organ/external/diona/removed() + var/mob/living/carbon/human/H = owner ..() - if(!istype(owner)) + if(!istype(H) || !H.organs || !H.organs.len) + H.death() + if(prob(50) && spawn_diona_nymph_from_organ(src)) qdel(src) - if(!owner.organs.len) - owner.death() - - if(prob(50)) - spawn_diona_nymph_from_organ(src) - /obj/item/organ/diona/process() return @@ -167,16 +174,13 @@ organ_tag = "special" // Turns into a nymph instantly, no transplanting possible. /obj/item/organ/diona/removed(var/mob/living/user) - + var/mob/living/carbon/human/H = owner ..() - if(!istype(owner)) + if(!istype(H) || !H.organs || !H.organs.len) + H.death() + if(prob(50) && spawn_diona_nymph_from_organ(src)) qdel(src) - if(!owner.internal_organs.len) - owner.death() - - spawn_diona_nymph_from_organ(src) - // These are different to the standard diona organs as they have a purpose in other // species (absorbing radiation and light respectively) /obj/item/organ/diona/nutrients diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 6e2e65aa321..b7b34d8a8f3 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -51,66 +51,55 @@ msg_admin_attack("[user.name] ([user.ckey]) Used the [name] to stab [M.name] ([M.ckey]) (JMP)") return - /* - * Sleepy Pens + * Reagent pens */ -/obj/item/weapon/pen/sleepypen - desc = "It's a black ink pen with a sharp point and a carefully engraved \"Waffle Co.\"" + +/obj/item/weapon/pen/reagent flags = OPENCONTAINER slot_flags = SLOT_BELT origin_tech = list(TECH_MATERIAL = 2, TECH_ILLEGAL = 5) - -/obj/item/weapon/pen/sleepypen/New() - var/datum/reagents/R = new/datum/reagents(30) //Used to be 300 - reagents = R - R.my_atom = src - R.add_reagent("chloralhydrate", 22) //Used to be 100 sleep toxin//30 Chloral seems to be fatal, reducing it to 22./N +/obj/item/weapon/pen/reagent/New() ..() - return + create_reagents(30) +/obj/item/weapon/pen/reagent/attack(mob/living/M as mob, mob/user as mob) -/obj/item/weapon/pen/sleepypen/attack(mob/M as mob, mob/user as mob) - if(!(istype(M,/mob))) + if(!istype(M)) return + + . = ..() + + if(M.can_inject(user,1)) + if(reagents.total_volume) + if(M.reagents) + var/contained_reagents = reagents.get_reagents() + var/trans = reagents.trans_to_mob(M, 30, CHEM_BLOOD) + admin_inject_log(user, M, src, contained_reagents, trans) + +/* + * Sleepy Pens + */ +/obj/item/weapon/pen/reagent/sleepy + desc = "It's a black ink pen with a sharp point and a carefully engraved \"Waffle Co.\"" + origin_tech = list(TECH_MATERIAL = 2, TECH_ILLEGAL = 5) + +/obj/item/weapon/pen/reagent/sleepy/New() ..() - if(reagents.total_volume) - if(M.reagents) reagents.trans_to_mob(M, 50, CHEM_BLOOD) //used to be 150 - return + reagents.add_reagent("chloralhydrate", 22) //Used to be 100 sleep toxin//30 Chloral seems to be fatal, reducing it to 22./N /* * Parapens */ - /obj/item/weapon/pen/paralysis - flags = OPENCONTAINER - slot_flags = SLOT_BELT - origin_tech = list(TECH_MATERIAL = 2, TECH_ILLEGAL = 5) - - -/obj/item/weapon/pen/paralysis/attack(mob/living/M as mob, mob/user as mob) - - if(!(istype(M,/mob))) - return + /obj/item/weapon/pen/reagent/paralysis + origin_tech = "materials=2;syndicate=5" +/obj/item/weapon/pen/reagent/paralysis/New() ..() - - - if(M.can_inject(user,1)) - if(reagents.total_volume) - if(M.reagents) reagents.trans_to_mob(M, 50, CHEM_BLOOD) - return - - -/obj/item/weapon/pen/paralysis/New() - var/datum/reagents/R = new/datum/reagents(50) - reagents = R - R.my_atom = src - R.add_reagent("zombiepowder", 10) - R.add_reagent("cryptobiolin", 15) - ..() - return + reagents.add_reagent("zombiepowder", 10) + reagents.add_reagent("cryptobiolin", 15) /* * Chameleon pen diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index f24758ed3c2..5409348af6a 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -685,7 +685,7 @@ if(cell) user.put_in_hands(cell) cell.add_fingerprint(user) - cell.updateicon() + cell.update_icon() src.cell = null user.visible_message("[user.name] removes the power cell from [src.name]!",\ diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 0804d133f34..ebae74cd274 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -8,7 +8,7 @@ /obj/item/weapon/cell/initialize() ..() - updateicon() + update_icon() /obj/item/weapon/cell/drain_power(var/drain_check, var/surge, var/power = 0) @@ -22,7 +22,7 @@ return use(cell_amt) / CELLRATE -/obj/item/weapon/cell/proc/updateicon() +/obj/item/weapon/cell/update_icon() overlays.Cut() if(charge < 0.01) diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index f39d7167fab..cfed0351fc7 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -19,7 +19,7 @@ reagents.add_reagent("tricordrazine", 30) return -/obj/item/weapon/reagent_containers/hypospray/attack(mob/M as mob, mob/user as mob) +/obj/item/weapon/reagent_containers/hypospray/attack(mob/living/M as mob, mob/user as mob) if(!reagents.total_volume) user << "[src] is empty." return @@ -40,13 +40,9 @@ M << "You feel a tiny prick!" if(M.reagents) - var/contained = reagentlist() - M.attack_log += text("\[[time_stamp()]\] Has been injected with [name] by [user.name] ([user.ckey]). Reagents: [contained]") - user.attack_log += text("\[[time_stamp()]\] Used the [name] to inject [M.name] ([M.key]). Reagents: [contained]") - msg_admin_attack("[user.name] ([user.ckey]) injected [M.name] ([M.key]) with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") - var/trans = reagents.trans_to_mob(M, amount_per_transfer_from_this, CHEM_BLOOD) + admin_inject_log(user, M, src, contained, trans) user << "[trans] units injected. [reagents.total_volume] units remaining in \the [src]." return diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index bdc17b298c4..3a1cb76522e 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -179,16 +179,11 @@ user.visible_message("[user] injects [target] with the syringe!") - if(istype(target, /mob/living)) - var/mob/living/M = target - var/contained = reagentlist() - M.attack_log += text("\[[time_stamp()]\] Has been injected with [name] by [user.name] ([user.ckey]). Reagents: [contained]") - user.attack_log += text("\[[time_stamp()]\] Used the [name] to inject [M.name] ([M.key]). Reagents: [contained]") - msg_admin_attack("[user.name] ([user.ckey]) injected [M.name] ([M.key]) with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") - var/trans if(ismob(target)) + var/contained = reagentlist() trans = reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_BLOOD) + admin_inject_log(user, target, src, contained, trans) else trans = reagents.trans_to(target, amount_per_transfer_from_this) user << "You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units." @@ -227,10 +222,6 @@ proc/syringestab(mob/living/carbon/target as mob, mob/living/carbon/user as mob) - user.attack_log += "\[[time_stamp()]\] Attacked [target.name] ([target.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - target.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - msg_admin_attack("[user.name] ([user.ckey]) attacked [target.name] ([target.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") - if(istype(target, /mob/living/carbon/human)) var/mob/living/carbon/human/H = target @@ -252,6 +243,11 @@ O.show_message(text("\red [user] tries to stab [target] in \the [hit_area] with [src.name], but the attack is deflected by armor!"), 1) user.remove_from_mob(src) qdel(src) + + user.attack_log += "\[[time_stamp()]\] Attacked [target.name] ([target.ckey]) with \the [src] (INTENT: HARM)." + target.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: HARM)." + msg_admin_attack("[key_name_admin(user)] attacked [key_name_admin(target)] with [src.name] (INTENT: HARM) (JMP)") + return user.visible_message("[user] stabs [target] in \the [hit_area] with [src.name]!") @@ -263,8 +259,13 @@ user.visible_message("[user] stabs [target] with [src.name]!") target.take_organ_damage(3)// 7 is the same as crowbar punch + + var/syringestab_amount_transferred = rand(0, (reagents.total_volume - 5)) //nerfed by popular demand - reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_BLOOD) + var/contained_reagents = reagents.get_reagents() + var/trans = reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_BLOOD) + if(isnull(trans)) trans = 0 + admin_inject_log(user, target, src, contained_reagents, trans, violent=1) break_syringe(target, user) proc/break_syringe(mob/living/carbon/target, mob/living/carbon/user) diff --git a/code/modules/research/xenoarchaeology/finds/finds.dm b/code/modules/research/xenoarchaeology/finds/finds.dm index febb0a68274..33cb2d52ff4 100644 --- a/code/modules/research/xenoarchaeology/finds/finds.dm +++ b/code/modules/research/xenoarchaeology/finds/finds.dm @@ -254,7 +254,7 @@ if(prob(75)) new_item = new /obj/item/weapon/pen(src.loc) else - new_item = new /obj/item/weapon/pen/sleepypen(src.loc) + new_item = new /obj/item/weapon/pen/reagent/sleepy(src.loc) if(prob(30)) apply_image_decorations = 1 if(16) diff --git a/code/modules/research/xenoarchaeology/tools/suspension_generator.dm b/code/modules/research/xenoarchaeology/tools/suspension_generator.dm index b14c892cd03..7450dd06032 100644 --- a/code/modules/research/xenoarchaeology/tools/suspension_generator.dm +++ b/code/modules/research/xenoarchaeology/tools/suspension_generator.dm @@ -159,7 +159,7 @@ else if(cell) cell.loc = loc cell.add_fingerprint(user) - cell.updateicon() + cell.update_icon() icon_state = "suspension0" cell = null diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm index 5215400a4e1..ea572e8fb43 100644 --- a/code/modules/shuttles/shuttle_emergency.dm +++ b/code/modules/shuttles/shuttle_emergency.dm @@ -62,7 +62,11 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - world << "\blue Alert: The shuttle autopilot has been overridden. Launch sequence initiated!" + world << "Alert: The shuttle autopilot has been overridden. Launch sequence initiated!" + + if(usr) + log_admin("[key_name(usr)] has overridden the shuttle autopilot and activated launch sequence") + message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and activated launch sequence") ..(user) @@ -72,7 +76,11 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - world << "\blue Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!" + world << "Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!" + + if(usr) + log_admin("[key_name(usr)] has overridden the shuttle autopilot and forced immediate launch") + message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and forced immediate launch") ..(user) @@ -82,7 +90,11 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - world << "\blue Alert: The shuttle autopilot has been overridden. Launch sequence aborted!" + world << "Alert: The shuttle autopilot has been overridden. Launch sequence aborted!" + + if(usr) + log_admin("[key_name(usr)] has overridden the shuttle autopilot and cancelled launch sequence") + message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and cancelled launch sequence") ..(user) @@ -102,8 +114,8 @@ authorized = initial(authorized) //returns 1 if the ID was accepted and a new authorization was added, 0 otherwise -/obj/machinery/computer/shuttle_control/emergency/proc/read_authorization(var/ident) - if (!ident) +/obj/machinery/computer/shuttle_control/emergency/proc/read_authorization(var/obj/item/ident) + if (!ident || !istype(ident)) return 0 if (authorized.len >= req_authorizations) return 0 //don't need any more @@ -112,33 +124,35 @@ var/auth_name var/dna_hash - if(istype(ident, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/ID = ident - access = ID.access - auth_name = "[ID.registered_name] ([ID.assignment])" - dna_hash = ID.dna_hash + var/obj/item/weapon/card/id/ID = ident.GetID() - if(istype(ident, /obj/item/device/pda)) - var/obj/item/device/pda/PDA = ident - access = PDA.id.access - auth_name = "[PDA.id.registered_name] ([PDA.id.assignment])" - dna_hash = PDA.id.dna_hash + if(!ID) + return + + access = ID.access + auth_name = "[ID.registered_name] ([ID.assignment])" + dna_hash = ID.dna_hash if (!access || !istype(access)) return 0 //not an ID if (dna_hash in authorized) - src.visible_message("[src] buzzes. That ID has already been scanned.") + src.visible_message("\The [src] buzzes. That ID has already been scanned.") return 0 if (!(access_heads in access)) - src.visible_message("[src] buzzes, rejecting [ident].") + src.visible_message("\The [src] buzzes, rejecting [ident].") return 0 - src.visible_message("[src] beeps as it scans [ident].") + src.visible_message("\The [src] beeps as it scans [ident].") authorized[dna_hash] = auth_name if (req_authorizations - authorized.len) - world << "\blue Alert: [req_authorizations - authorized.len] authorization\s needed to override the shuttle autopilot." + world << "Alert: [req_authorizations - authorized.len] authorization\s needed to override the shuttle autopilot." + + if(usr) + log_admin("[key_name(usr)] has inserted [ID] into the shuttle control computer - [req_authorizations - authorized.len] authorisation\s needed") + message_admins("[key_name_admin(usr)] has inserted [ID] into the shuttle control computer - [req_authorizations - authorized.len] authorisation\s needed") + return 1 @@ -146,7 +160,7 @@ /obj/machinery/computer/shuttle_control/emergency/attackby(obj/item/weapon/W as obj, mob/user as mob) if (istype(W, /obj/item/weapon/card/emag) && !emagged) - user << "\blue You short out the [src]'s authorization protocols." + user << "You short out \the [src]'s authorization protocols." emagged = 1 return diff --git a/config/example/config.txt b/config/example/config.txt index 01d0c40db94..7648a51a889 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -102,6 +102,9 @@ TRAITOR_SCALING ## make ERT's be only called by admins #ERT_ADMIN_ONLY + +## If uncommented, votes can be called to add extra antags to the round. +#ALLOW_EXTRA_ANTAGS ## If security is prohibited from being most antagonists #PROTECT_ROLES_FROM_ANTAGONIST @@ -177,6 +180,9 @@ GUEST_BAN ## Wiki address # WIKIURL http://example.com +## GitHub address +# GITHUBURL https://github.com/example-user/example-repository + ## Ban appeals URL - usually for a forum or wherever people should go to contact your admins. # BANAPPEALS http://example.com diff --git a/html/changelog.html b/html/changelog.html index cfde784c57c..6c5b0807003 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,21 @@ -->
    +

    30 May 2015

    +

    Atlantis updated:

    +
      +
    • Malfunction Overhaul - Whole gamemode was completely reworked from scratch. Most old abilities have been removed and quite a lot of new abilities was added. AI also has to hack APCs to unlock higher tier abilities faster, instead of having access to them from the round start. Most forced things, such as, shuttle recalling were removed and are instead controlled by the AI. Code is fully modular allowing for future modifications.
    • +
    +

    HarpyEagle updated:

    +
      +
    • Fixes Engineer ERT gloves not being insulated.
    • +
    • IV stands are no longer bullet shields. They also allow mice, drones, pAIs et al to pass though.
    • +
    +

    PsiOmegaDelta updated:

    +
      +
    • You can now review the server revision date and hash by using the 'Show Server Revision' verb in the OOC category.
    • +
    +

    27 May 2015

    PsiOmegaDelta updated:

      diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index ffa438a005c..da9d8eaa88b 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -1911,3 +1911,18 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - rscadd: Unfolded pAIs can now be scooped up and worn as hats. - tweak: Scoop-up behavior is now standardized to selecting help intent and dragging their icon onto yours. +2015-05-30: + Atlantis: + - rscadd: Malfunction Overhaul - Whole gamemode was completely reworked from scratch. + Most old abilities have been removed and quite a lot of new abilities was added. + AI also has to hack APCs to unlock higher tier abilities faster, instead of + having access to them from the round start. Most forced things, such as, shuttle + recalling were removed and are instead controlled by the AI. Code is fully modular + allowing for future modifications. + HarpyEagle: + - bugfix: Fixes Engineer ERT gloves not being insulated. + - tweak: IV stands are no longer bullet shields. They also allow mice, drones, pAIs + et al to pass though. + PsiOmegaDelta: + - rscadd: You can now review the server revision date and hash by using the 'Show + Server Revision' verb in the OOC category. diff --git a/html/changelogs/Atlantis-PR-9108.yml b/html/changelogs/Atlantis-PR-9108.yml deleted file mode 100644 index b2c3f6bdb4c..00000000000 --- a/html/changelogs/Atlantis-PR-9108.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: Atlantis -delete-after: True - -changes: - - rscadd: "Malfunction Overhaul - Whole gamemode was completely reworked from scratch. Most old abilities have been removed and quite a lot of new abilities was added. AI also has to hack APCs to unlock higher tier abilities faster, instead of having access to them from the round start. Most forced things, such as, shuttle recalling were removed and are instead controlled by the AI. Code is fully modular allowing for future modifications." \ No newline at end of file diff --git a/html/changelogs/HarpyEagle-ProjectileTweaks.yml b/html/changelogs/HarpyEagle-ProjectileTweaks.yml deleted file mode 100644 index 12266695bb8..00000000000 --- a/html/changelogs/HarpyEagle-ProjectileTweaks.yml +++ /dev/null @@ -1,18 +0,0 @@ -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment - -author: HarpyEagle -delete-after: True - -changes: - - tweak: "IV stands are no longer bullet shields. They also allow mice, drones, pAIs et al to pass though."