diff --git a/baystation12.dme b/baystation12.dme index 4d2eac3f53..3d52f63fb5 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 331c00dd37..2dfcfcdf81 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 69d01e3d35..50f55703d3 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 478700d5f8..216a45ee1c 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 64b75c3fce..af4d8ef296 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 68bfdab74b..f4b88f8850 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 0000000000..da4192df25 --- /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 fa408d1b8f..ae6a8d0846 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 6c5f27fa07..bf16c5267d 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 3f5d65d21d..adaa2b24f5 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 b8e653d153..2a4fe862de 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 a296fb8ecb..755887ad83 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 7fa102aeb8..a7d54284bf 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 e3b161b6fb..83112ea778 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 3e6f0d8e33..2f6166905a 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 683e6e1220..c3f617057c 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 28bd367083..e31a19b265 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 9bfa0e1c5d..9016836274 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 c5d389c66e..14a081ee2e 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 684c761840..fe2c0a6110 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 b28e9b62f6..7f9f7e2b98 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 dfc53d3a87..afe50bc2b7 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 7fc96efcee..82a5433963 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 085e23f9b6..b33d72f6fb 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 63bbde044c..f8708d7925 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 a5ad84c20e..3647d565f7 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 7cbd14cb21..81df901b38 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 70c21d5108..c46b019a4d 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 bb6613582e..cc6a6f9965 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 639cea4d5e..2eb6121f08 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 2d088658ac..57579cdb72 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 cc80c3bed4..8a5f584b4f 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 f0af6e1464..2162e3488a 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 d6510c2bf8..88c90d4349 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 6c92db09fe..f2c64fa52a 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 896f57878c..89f071d482 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 d859810ea1..84611ecb95 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 27c08746bc..e71db5693d 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 359562063d..527ce35df2 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 203159f3c6..147edb1afe 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 2a89779e92..f6325fd4f7 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 f53fc98497..f134d5d93b 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 8cef1b9cc2..2d4ca50d90 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 f08a5a9371..873d2b4766 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 6e2e65aa32..b7b34d8a8f 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 f24758ed3c..5409348af6 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 0804d133f3..ebae74cd27 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 f39d7167fa..cfed0351fc 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 bdc17b298c..3a1cb76522 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 febb0a6827..33cb2d52ff 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 b14c892cd0..7450dd0603 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 5215400a4e..ea572e8fb4 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 01d0c40db9..7648a51a88 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 cfde784c57..6c5b080700 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 ffa438a005..da9d8eaa88 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 b2c3f6bdb4..0000000000 --- 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 12266695bb..0000000000 --- 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."