From 72dbce88cec9d9f3124a0c3778746501347176ab Mon Sep 17 00:00:00 2001 From: Atlantiscze Date: Thu, 17 Jul 2014 18:01:19 +0200 Subject: [PATCH 01/28] Fixes #5570 Also de-copypasted charger code, as i had the opportunity. --- code/game/machinery/recharger.dm | 52 +++++++++----------------------- 1 file changed, 15 insertions(+), 37 deletions(-) diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index a5d9a6ce1d..307db25240 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -9,6 +9,9 @@ obj/machinery/recharger idle_power_usage = 4 active_power_usage = 250 var/obj/item/charging = null + var/icon_state_charged = "recharger2" + var/icon_state_charging = "recharger1" + var/icon_state_idle = "recharger0" obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob) if(istype(user,/mob/living/silicon)) @@ -71,28 +74,28 @@ obj/machinery/recharger/process() var/obj/item/weapon/gun/energy/E = charging if(E.power_supply.charge < E.power_supply.maxcharge) E.power_supply.give(100) - icon_state = "recharger1" + icon_state = icon_state_charging use_power(250) else - icon_state = "recharger2" + icon_state = icon_state_charged return if(istype(charging, /obj/item/weapon/melee/baton)) var/obj/item/weapon/melee/baton/B = charging if(B.charges < initial(B.charges)) B.charges++ - icon_state = "recharger1" + icon_state = icon_state_charging use_power(150) else - icon_state = "recharger2" + icon_state = icon_state_charged return if(istype(charging, /obj/item/device/laptop)) var/obj/item/device/laptop/L = charging if(L.stored_computer.battery.charge < L.stored_computer.battery.maxcharge) L.stored_computer.battery.give(100) - icon_state = "recharger1" + icon_state = icon_state_charging use_power(250) else - icon_state = "recharger2" + icon_state = icon_state_charged return obj/machinery/recharger/emp_act(severity) @@ -112,40 +115,15 @@ obj/machinery/recharger/emp_act(severity) obj/machinery/recharger/update_icon() //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier. if(charging) - icon_state = "recharger1" + icon_state = icon_state_charging else - icon_state = "recharger0" + icon_state = icon_state_idle +// Atlantis: No need for that copy-pasta code, just use var to store icon_states instead. obj/machinery/recharger/wallcharger name = "wall recharger" icon = 'icons/obj/stationobjs.dmi' icon_state = "wrecharger0" - -obj/machinery/recharger/wallcharger/process() - if(stat & (NOPOWER|BROKEN) || !anchored) - return - - if(charging) - if(istype(charging, /obj/item/weapon/gun/energy)) - var/obj/item/weapon/gun/energy/E = charging - if(E.power_supply.charge < E.power_supply.maxcharge) - E.power_supply.give(100) - icon_state = "wrecharger1" - use_power(250) - else - icon_state = "wrecharger2" - return - if(istype(charging, /obj/item/weapon/melee/baton)) - var/obj/item/weapon/melee/baton/B = charging - if(B.charges < initial(B.charges)) - B.charges++ - icon_state = "wrecharger1" - use_power(150) - else - icon_state = "wrecharger2" - -obj/machinery/recharger/wallcharger/update_icon() - if(charging) - icon_state = "wrecharger1" - else - icon_state = "wrecharger0" \ No newline at end of file + icon_state_idle = "wrecharger0" + icon_state_charging = "wrecharger1" + icon_state_charged = "wrecharger2" \ No newline at end of file From 4096b26c8d6f427385ff7394738595a0c01726cb Mon Sep 17 00:00:00 2001 From: Atlantiscze Date: Thu, 17 Jul 2014 19:03:31 +0200 Subject: [PATCH 02/28] Fixes #5553 Camera network key itself is useless without security camera program. Created hidden version of this program and added it to each laptop. In short: it works. --- code/WorkInProgress/computer3/NTOS.dm | 29 ++++++++++--------- .../computer3/computers/camera.dm | 4 +++ code/WorkInProgress/computer3/file.dm | 2 +- code/WorkInProgress/computer3/lapvend.dm | 2 ++ 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/code/WorkInProgress/computer3/NTOS.dm b/code/WorkInProgress/computer3/NTOS.dm index 0b921ad43b..f6dc2697a8 100644 --- a/code/WorkInProgress/computer3/NTOS.dm +++ b/code/WorkInProgress/computer3/NTOS.dm @@ -22,20 +22,21 @@ var/dat = "" var/i = 0 for(var/datum/file/F in filelist) - i++ - if(i==1) - dat += "" - if(i>= 6) - i = 0 - dat += "" - continue - dat += {" - "} + if(!F.hidden_file) + i++ + if(i==1) + dat += "" + if(i>= 6) + i = 0 + dat += "" + continue + dat += {" + "} dat += "
-
-
- [F.name] -
-
+
+
+ [F.name] +
+
" return dat diff --git a/code/WorkInProgress/computer3/computers/camera.dm b/code/WorkInProgress/computer3/computers/camera.dm index 4da54340c1..0883680f5c 100644 --- a/code/WorkInProgress/computer3/computers/camera.dm +++ b/code/WorkInProgress/computer3/computers/camera.dm @@ -275,3 +275,7 @@ else usr << "The screen turns to static." return + + // Atlantis: Required for camnetkeys to work. +/datum/file/program/security/hidden + hidden_file = 1 \ No newline at end of file diff --git a/code/WorkInProgress/computer3/file.dm b/code/WorkInProgress/computer3/file.dm index 3693579067..849312ec50 100644 --- a/code/WorkInProgress/computer3/file.dm +++ b/code/WorkInProgress/computer3/file.dm @@ -13,7 +13,7 @@ var/image = 'icons/ntos/file.png' // determines the icon to use, found in icons/ntos var/obj/machinery/computer3/computer // the parent computer, if fixed var/obj/item/part/computer/storage/device // the device that is containing this file - + var/hidden_file = 0 // Prevents file from showing up on NTOS program list. var/drm = 0 // Copy protection, called by copy() and move() var/readonly = 0 // Edit protection, called by edit(), which is just a failcheck proc diff --git a/code/WorkInProgress/computer3/lapvend.dm b/code/WorkInProgress/computer3/lapvend.dm index d36af863d1..747078edcd 100644 --- a/code/WorkInProgress/computer3/lapvend.dm +++ b/code/WorkInProgress/computer3/lapvend.dm @@ -320,6 +320,8 @@ newlap.spawn_files += (/datum/file/camnet_key/creed) newlap.spawn_files += (/datum/file/program/arcade) newlap.spawn_files += (/datum/file/camnet_key/entertainment) + //Atlantis: Each laptop gets "invisible" program/security - REQUIRED for camnetkeys to work. + newlap.spawn_files += (/datum/file/program/security/hidden) newlap.update_spawn_files() /obj/machinery/lapvend/proc/calc_reimburse(var/obj/item/device/laptop/L) From 1e512fdde2e663adb2582a988fc00505e712ef6c Mon Sep 17 00:00:00 2001 From: Atlantiscze Date: Fri, 18 Jul 2014 00:47:39 +0200 Subject: [PATCH 03/28] Fixes #5569, Fixes #5571 - Reworked card reader code, it's cleaner and less copypaste now - Updated medical records, security records and HoP card computer to work with the update. It's however possible i missed something, can't go through all computers in game. Tell me if you find something that's broken due to this, i will fix it ASAP. - Security records color for "none" security status changed a bit so it doesn't burn eyes of anyone trying to read it (issue #5571 - white on light green? Bad choice imo) - Multi-card readers now actually WORK for laptops. This includes security records (issue #5569) and medical records (same case, just not reported). You still have to insert your card into read slot, if you insert it into wrong slot notification will be shown that you should use read slot instead of write one. --- code/WorkInProgress/computer3/component.dm | 144 +++++++++++++++--- .../computer3/computers/card.dm | 8 +- .../computer3/computers/medical.dm | 27 +++- .../computer3/computers/security.dm | 36 ++++- 4 files changed, 181 insertions(+), 34 deletions(-) diff --git a/code/WorkInProgress/computer3/component.dm b/code/WorkInProgress/computer3/component.dm index 8dc2ec835b..501bbc973e 100644 --- a/code/WorkInProgress/computer3/component.dm +++ b/code/WorkInProgress/computer3/component.dm @@ -91,29 +91,127 @@ return ..(I,user) - proc/insert(var/obj/item/weapon/card/card) + // cardslot.insert(card, slot) + // card: The card obj you want to insert (usually your ID) + // slot: Which slot to insert into (1: reader, 2: writer, 3: auto), 3 default + proc/insert(var/obj/item/weapon/card/card, var/slot = 3) if(!computer) return 0 - if(reader != null) - usr << "There is already something in the slot!" + // This shouldn't happen, just in case.. + if(slot == 2 && !dualslot) + usr << "This device has only one card slot" return 0 - if(istype(card,/obj/item/weapon/card/emag)) // emag reader slot - usr << "You insert \the [card], and the computer grinds, sparks, and beeps. After a moment, the card ejects itself." - computer.emagged = 1 - return 1 - var/mob/living/L = usr - L.drop_item() - card.loc = src - reader = card - proc/remove() - reader.loc = loc - var/mob/living/carbon/human/user = usr - if(istype(user) && !user.get_active_hand()) - user.put_in_hands(reader) - else - reader.loc = computer.loc - reader = null + if(istype(card,/obj/item/weapon/card/emag)) // emag reader slot + if(!writer) + usr << "You insert \the [card], and the computer grinds, sparks, and beeps. After a moment, the card ejects itself." + computer.emagged = 1 + return 1 + else + usr << "You are unable to insert \the [card], as the reader slot is occupied" + + var/mob/living/L = usr + switch(slot) + if(1) + if(equip_to_reader(card, L)) + usr << "You insert the card into reader slot" + else + usr << "There is already something in the reader slot." + if(2) + if(equip_to_writer(card, L)) + usr << "You insert the card into writer slot" + else + usr << "There is already something in the reader slot." + if(3) + if(equip_to_reader(card, L)) + usr << "You insert the card into reader slot" + else if (equip_to_writer(card, L) && dualslot) + usr << "You insert the card into writer slot" + else if (dualslot) + usr << "There is already something in both slots." + else + usr << "There is already something in the reader slot." + + + // Usage of insert() preferred, as it also tells result to the user. + proc/equip_to_reader(var/obj/item/weapon/card/card, var/mob/living/L) + if(!reader) + L.drop_item() + card.loc = src + reader = card + return 1 + return 0 + + proc/equip_to_writer(var/obj/item/weapon/card/card, var/mob/living/L) + if(!writer && dualslot) + L.drop_item() + card.loc = src + writer = card + return 1 + return 0 + + // cardslot.remove(slot) + // slot: Which slot to remove card(s) from (1: reader only, 2: writer only, 3: both [works even with one card], 4: reader and if empty then writer ), 3 default + proc/remove(var/slot = 3) + var/mob/living/L = usr + switch(slot) + if(1) + if (remove_reader(L)) + L << "You remove the card from reader slot" + else + L << "There is no card in the reader slot" + if(2) + if (remove_writer(L)) + L << "You remove the card from writer slot" + else + L << "There is no card in the writer slot" + if(3) + if (remove_reader(L)) + if (remove_writer(L)) + L << "You remove cards from both slots" + else + L << "You remove the card from reader slot" + else + if(remove_writer(L)) + L << "You remove the card from writer slot" + else + L << "There are no cards in both slots" + if(4) + if (!remove_reader(L)) + if (remove_writer(L)) + L << "You remove the card from writer slot" + else if (!dualslot) + L << "There is no card in the reader slot" + else + L << "There are no cards in both slots" + else + L << "You remove the card from reader slot" + + + proc/remove_reader(var/mob/living/L) + if(reader) + reader.loc = loc + if(istype(L) && !L.get_active_hand()) + L.put_in_hands(reader) + else + reader.loc = computer.loc + reader = null + return 1 + return 0 + + proc/remove_writer(var/mob/living/L) + if(writer && dualslot) + writer.loc = loc + if(istype(L) && !L.get_active_hand()) + L.put_in_hands(writer) + else + writer.loc = computer.loc + writer = null + return 1 + return 0 + + + // Authorizes the user based on the computer's requirements proc/authenticate() @@ -133,6 +231,13 @@ desc = "Contains slots for inserting magnetic swipe cards for reading and writing." dualslot = 1 + + /* + // Atlantis: Reworked card manipulation a bit. + // No need for separated code for dual and single readers. + // Both is handled in single-slot reader code now, thanks to the "dualslot" var. + // Leaving this code here if someone wants to somehow use it, just uncomment. + insert(var/obj/item/weapon/card/card,var/slot = 0) if(!computer) return 0 @@ -194,5 +299,6 @@ user.put_in_hands(card) else card.loc = computer.loc +*/ diff --git a/code/WorkInProgress/computer3/computers/card.dm b/code/WorkInProgress/computer3/computers/card.dm index 6080b59643..5acb7c9de2 100644 --- a/code/WorkInProgress/computer3/computers/card.dm +++ b/code/WorkInProgress/computer3/computers/card.dm @@ -253,9 +253,9 @@ if("remove" in href_list) var/which = href_list["remove"] if(which == "writer") - computer.cardslot.remove(computer.cardslot.writer) + computer.cardslot.remove(2) else - computer.cardslot.remove(computer.cardslot.reader) + computer.cardslot.remove(1) auth = 0 if("insert" in href_list) @@ -264,9 +264,9 @@ var/which = href_list["insert"] if(which == "writer") - computer.cardslot.insert(card,1) - else computer.cardslot.insert(card,2) + else + computer.cardslot.insert(card,1) if("print" in href_list) if (printing) diff --git a/code/WorkInProgress/computer3/computers/medical.dm b/code/WorkInProgress/computer3/computers/medical.dm index ee55a857b2..7fc5da1232 100644 --- a/code/WorkInProgress/computer3/computers/medical.dm +++ b/code/WorkInProgress/computer3/computers/medical.dm @@ -23,6 +23,7 @@ req_one_access = list(access_medical, access_forensics_lockers) var/obj/item/weapon/card/id/scan = null + var/obj/item/weapon/card/id/scan2 = null var/authenticated = null var/rank = null var/screen = null @@ -56,7 +57,12 @@ if (temp) dat = text("[src.temp]

Clear Screen") else - dat = text("Confirm Identity: []
", src, (src.scan ? text("[]", src.scan.name) : "----------")) + dat = text("Confirm Identity (R): []
", src, (scan ? text("[]", scan.name) : "----------")) + if (computer.cardslot.dualslot) + dat += text("Check Identity (W): []
", src, (scan2 ? text("[]", scan2.name) : "----------")) + if(scan2 && !scan) + dat += text("
Insert card into reader slot to log in.

") + if (src.authenticated) switch(src.screen) if(1.0) @@ -165,19 +171,32 @@ if (href_list["temp"]) src.temp = null - if (href_list["scan"]) + if (href_list["cardr"]) if (scan) if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) - computer.cardslot.remove(scan) + computer.cardslot.remove(1) else scan.loc = get_turf(src) scan = null else var/obj/item/I = usr.get_active_hand() if (istype(I, /obj/item/weapon/card/id)) - computer.cardslot.insert(I) + computer.cardslot.insert(I, 1) scan = I + if (href_list["cardw"]) + if (scan2) + if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) + computer.cardslot.remove(2) + else + scan2.loc = get_turf(src) + scan2 = null + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/weapon/card/id)) + computer.cardslot.insert(I, 2) + scan2 = I + else if (href_list["logout"]) src.authenticated = null src.screen = null diff --git a/code/WorkInProgress/computer3/computers/security.dm b/code/WorkInProgress/computer3/computers/security.dm index f161b10cab..f193b07139 100644 --- a/code/WorkInProgress/computer3/computers/security.dm +++ b/code/WorkInProgress/computer3/computers/security.dm @@ -19,6 +19,7 @@ req_one_access = list(access_security, access_forensics_lockers) var/obj/item/weapon/card/id/scan = null + var/obj/item/weapon/card/id/scan2 = null var/authenticated = null var/rank = null var/screen = null @@ -49,9 +50,13 @@ return usr.set_machine(src) scan = computer.cardslot.reader + + if (computer.cardslot.dualslot) + scan2 = computer.cardslot.writer + if(!interactable()) return - return + if (computer.z > 6) usr << "\red Unable to establish a connection: \black You're too far away from the station!" return @@ -60,7 +65,11 @@ if (temp) dat = text("[]

Clear Screen", temp, src) else - dat = text("Confirm Identity: []
", src, (scan ? text("[]", scan.name) : "----------")) + dat = text("Confirm Identity (R): []
", src, (scan ? text("[]", scan.name) : "----------")) + if (computer.cardslot.dualslot) + dat += text("Check Identity (W): []
", src, (scan2 ? text("[]", scan2.name) : "----------")) + if(scan2 && !scan) + dat += text("
Insert card into reader slot to log in.

") if (authenticated) switch(screen) if(1.0) @@ -100,9 +109,9 @@ if("Released") background = "'background-color:#3BB9FF;'" if("None") - background = "'background-color:#00FF7F;'" - if("") background = "'background-color:#00FF00;'" + if("") + background = "'background-color:#00FF7F;'" crimstat = "No Record." dat += text("[]", background, src, R, R.fields["name"]) dat += text("[]", R.fields["id"]) @@ -236,19 +245,32 @@ What a mess.*/ active1 = null active2 = null - if("Confirm Identity") + if("Confirm Identity R") if (scan) if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) - computer.cardslot.remove(scan) + computer.cardslot.remove(1) else scan.loc = get_turf(src) scan = null else var/obj/item/I = usr.get_active_hand() if (istype(I, /obj/item/weapon/card/id)) - computer.cardslot.insert(I) + computer.cardslot.insert(I, 1) scan = I + if("Confirm Identity W") + if (scan2) + if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) + computer.cardslot.remove(2) + else + scan2.loc = get_turf(src) + scan2 = null + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/weapon/card/id)) + computer.cardslot.insert(I, 2) + scan2 = I + if("Log Out") authenticated = null screen = null From 95a45a646f7523d53bd54c013df04be58a750605 Mon Sep 17 00:00:00 2001 From: Atlantiscze Date: Fri, 18 Jul 2014 12:14:33 +0200 Subject: [PATCH 04/28] Fixes #5572 - Detective-vended laptops now have medical records program installed. --- code/WorkInProgress/computer3/lapvend.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/WorkInProgress/computer3/lapvend.dm b/code/WorkInProgress/computer3/lapvend.dm index 747078edcd..5c4f56ad72 100644 --- a/code/WorkInProgress/computer3/lapvend.dm +++ b/code/WorkInProgress/computer3/lapvend.dm @@ -305,9 +305,10 @@ newlap.spawn_files += (/datum/file/program/card_comp) if(access_heads in C.access) newlap.spawn_files += (/datum/file/program/communications) - if(access_medical in C.access) - newlap.spawn_files += (/datum/file/program/crew) + if((access_medical in C.access) || (access_forensics_lockers in C.access)) //Gives detective the medical records program, but not the crew monitoring one. newlap.spawn_files += (/datum/file/program/med_data) + if (access_medical in C.access) + newlap.spawn_files += (/datum/file/program/crew) if(access_engine in C.access) newlap.spawn_files += (/datum/file/program/powermon) if(access_research in C.access) From 9b71eb1fe6d7105ed7b1a37c537861d1c2ae55d0 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Fri, 18 Jul 2014 11:40:49 -0400 Subject: [PATCH 05/28] Removes organ_failure random event --- baystation12.dme | 1 - code/modules/events/organ_failure.dm | 44 ---------------------------- 2 files changed, 45 deletions(-) delete mode 100644 code/modules/events/organ_failure.dm diff --git a/baystation12.dme b/baystation12.dme index de02865c78..365ed1718b 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -835,7 +835,6 @@ #include "code\modules\events\money_hacker.dm" #include "code\modules\events\money_lotto.dm" #include "code\modules\events\money_spam.dm" -#include "code\modules\events\organ_failure.dm" #include "code\modules\events\prison_break.dm" #include "code\modules\events\radiation_storm.dm" #include "code\modules\events\rogue_drones.dm" diff --git a/code/modules/events/organ_failure.dm b/code/modules/events/organ_failure.dm deleted file mode 100644 index f51c463328..0000000000 --- a/code/modules/events/organ_failure.dm +++ /dev/null @@ -1,44 +0,0 @@ -datum/event/organ_failure - var/severity = 1 - -datum/event/organ_failure/setup() - announceWhen = rand(0, 300) - endWhen = announceWhen + 1 - severity = rand(1, 3) - -datum/event/organ_failure/announce() - command_alert("Confirmed outbreak of level [rand(3,7)] biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - world << sound('sound/AI/outbreak5.ogg') - -datum/event/organ_failure/start() - var/list/candidates = list() //list of candidate keys - for(var/mob/living/carbon/human/G in player_list) - if(G.mind && G.mind.current && G.mind.current.stat != DEAD && G.health > 70 && G.internal_organs) - candidates += G - if(!candidates.len) return - candidates = shuffle(candidates)//Incorporating Donkie's list shuffle - - while(severity > 0 && candidates.len) - var/mob/living/carbon/human/C = candidates[1] - - var/acute = prob(15) - if (prob(75)) - //internal organ infection - var/datum/organ/internal/I = pick(C.internal_organs) - - if (acute) - I.germ_level = max(INFECTION_LEVEL_TWO, I.germ_level) - else - I.germ_level = max(rand(INFECTION_LEVEL_ONE,INFECTION_LEVEL_ONE*2), I.germ_level) - else - //external organ infection - var/datum/organ/external/O = pick(C.organs) - - if (acute) - O.germ_level = max(INFECTION_LEVEL_TWO, O.germ_level) - else - O.germ_level = max(rand(INFECTION_LEVEL_ONE,INFECTION_LEVEL_ONE*2), O.germ_level) - - C.bad_external_organs |= O - - severity-- From 98259688804d5d197e5a83ba160ccbaf163a2237 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Fri, 18 Jul 2014 12:02:39 -0400 Subject: [PATCH 06/28] Fixes lingering reference to organ_failure --- code/modules/events/event_dynamic.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm index 3db6f6137f..7ca50ad9eb 100644 --- a/code/modules/events/event_dynamic.dm +++ b/code/modules/events/event_dynamic.dm @@ -76,7 +76,6 @@ var/list/event_last_fired = list() possibleEvents[/datum/event/radiation_storm] = active_with_role["Medical"] * 10 possibleEvents[/datum/event/spontaneous_appendicitis] = active_with_role["Medical"] * 10 possibleEvents[/datum/event/viral_infection] = active_with_role["Medical"] * 10 - possibleEvents[/datum/event/organ_failure] = active_with_role["Medical"] * 50 possibleEvents[/datum/event/prison_break] = active_with_role["Security"] * 50 if(active_with_role["Security"] > 0) From b3a99cefcfb7533ba0687bf81ce915b5397dd9f5 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Fri, 18 Jul 2014 12:07:43 -0400 Subject: [PATCH 07/28] Fixes #5666 --- code/game/verbs/ooc.dm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index cead05c53e..ecae608f32 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -131,9 +131,12 @@ var/global/normal_ooc_colour = "#002eb8" var/list/heard = get_mobs_in_view(7, src.mob) var/mob/S = src.mob + var/display_name = S.key if(S.stat != DEAD) display_name = S.name + + // Handle non-admins for(var/mob/M in heard) if(!M.client) continue @@ -149,6 +152,12 @@ var/global/normal_ooc_colour = "#002eb8" else display_name = holder.fakekey C << "LOOC: [display_name]: [msg]" + + // Now handle admins + display_name = S.key + if(S.stat != DEAD) + display_name = "[S.name]/([S.key])" + for(var/client/C in admins) if(C.prefs.toggles & CHAT_LOOC) var/prefix = "(R)LOOC" From ccc73ddf69c20039e6aed9912c16b2e3027dc986 Mon Sep 17 00:00:00 2001 From: Mloc-Hibernia Date: Fri, 18 Jul 2014 21:08:01 +0000 Subject: [PATCH 08/28] modularize ban system Signed-off-by: Mloc-Hibernia --- code/modules/admin/IsBanned.dm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 9548c279a0..59e4182ac5 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -1,3 +1,4 @@ +#ifndef OVERRIDE_BAN_SYSTEM //Blocks an attempt to connect before even creating our client datum thing. world/IsBanned(key,address,computer_id) if(ckey(key) in admin_datums) @@ -79,3 +80,6 @@ world/IsBanned(key,address,computer_id) if (failedip) message_admins("[key] has logged in with a blank ip in the ban check.") return ..() //default pager ban stuff +#endif +#undef OVERRIDE_BAN_SYSTEM + From 361609cacda14c71d7dea4bf3a730a87ed028959 Mon Sep 17 00:00:00 2001 From: Walter0o Date: Sat, 19 Jul 2014 23:22:28 +0200 Subject: [PATCH 09/28] should fix #5692 untested, but seems like a simple derp bug --- code/game/mecha/mecha_construction_paths.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index c80eb656cb..e9c6d644a8 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -1273,6 +1273,7 @@ else user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") holder.icon_state = "odysseus10" + if(2) if(diff==FORWARD) user.visible_message("[user] secures external armor layer.", "You secure external reinforced armor layer.") holder.icon_state = "odysseus13" @@ -1293,4 +1294,4 @@ spawn_result() ..() feedback_inc("mecha_odysseus_created",1) - return \ No newline at end of file + return From eb2ec423455b5aea30e0936efbae180c810009be Mon Sep 17 00:00:00 2001 From: Whitellama Date: Sat, 19 Jul 2014 16:22:09 -0700 Subject: [PATCH 10/28] Fixed #5697, grammatical error with empty glasses, cans, condiment containers --- code/modules/reagents/reagent_containers/food/cans.dm | 2 +- code/modules/reagents/reagent_containers/food/condiment.dm | 2 +- code/modules/reagents/reagent_containers/food/drinks.dm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/reagents/reagent_containers/food/cans.dm b/code/modules/reagents/reagent_containers/food/cans.dm index b83b7623f5..118b8cf6a2 100644 --- a/code/modules/reagents/reagent_containers/food/cans.dm +++ b/code/modules/reagents/reagent_containers/food/cans.dm @@ -17,7 +17,7 @@ var/fillevel = gulp_size if(!R.total_volume || !R) - user << "\red None of [src] left, oh no!" + user << "\red The [src.name] is empty!" return 0 if(M == user) diff --git a/code/modules/reagents/reagent_containers/food/condiment.dm b/code/modules/reagents/reagent_containers/food/condiment.dm index dccb59a3e7..ee5be182dd 100644 --- a/code/modules/reagents/reagent_containers/food/condiment.dm +++ b/code/modules/reagents/reagent_containers/food/condiment.dm @@ -24,7 +24,7 @@ var/datum/reagents/R = src.reagents if(!R || !R.total_volume) - user << "\red None of [src] left, oh no!" + user << "\red The [src.name] is empty!" return 0 if(M == user) diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm index a9aa234060..1a0fba6426 100644 --- a/code/modules/reagents/reagent_containers/food/drinks.dm +++ b/code/modules/reagents/reagent_containers/food/drinks.dm @@ -23,7 +23,7 @@ var/fillevel = gulp_size if(!R.total_volume || !R) - user << "\red None of [src] left, oh no!" + user << "\red The [src.name] is empty!" return 0 if(M == user) From 5cfe7d9dd870d3e3cdba775961880a44eaa76e23 Mon Sep 17 00:00:00 2001 From: Atlantiscze Date: Sun, 20 Jul 2014 01:55:11 +0200 Subject: [PATCH 11/28] Fixes #5670 - This also includes other vending machines than laptop vendor. They now actually take money from your account instead of pretending to do so and giving stuff for free. No moar spess communism. - Vending machines now ask for PIN code only if your account settings require it (ie: Security levels 1 or 2. Default is 0 - only ID card swipe) --- code/WorkInProgress/computer3/lapvend.dm | 196 ++++++++++++----------- code/game/machinery/vending.dm | 89 +++++----- 2 files changed, 152 insertions(+), 133 deletions(-) diff --git a/code/WorkInProgress/computer3/lapvend.dm b/code/WorkInProgress/computer3/lapvend.dm index 747078edcd..36ca07118d 100644 --- a/code/WorkInProgress/computer3/lapvend.dm +++ b/code/WorkInProgress/computer3/lapvend.dm @@ -213,58 +213,66 @@ if (istype(I, /obj/item/weapon/card/id)) var/obj/item/weapon/card/id/C = I visible_message("[usr] swipes a card through [src].") - if(vendor_account) - var/attempt_pin = input("Enter pin code", "Vendor transaction") as num - var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) - if(D) - var/transaction_amount = total() - if(transaction_amount <= D.money) - - //transfer the money - D.money -= transaction_amount - vendor_account.money += transaction_amount - - //Transaction logs - var/datum/transaction/T = new() - T.target_name = "[vendor_account.owner_name] (via [src.name])" - T.purpose = "Purchase of Laptop" - if(transaction_amount > 0) - T.amount = "([transaction_amount])" - else - T.amount = "[transaction_amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - D.transaction_log.Add(T) - // - T = new() - T.target_name = D.owner_name - T.purpose = "Purchase of Laptop" - T.amount = "[transaction_amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - vendor_account.transaction_log.Add(T) - - newlap = new /obj/machinery/computer3/laptop/vended(src.loc) - - choose_progs(C) - vend() - popup.close() - newlap.close_computer() - newlap = null - cardreader = 0 - floppy = 0 - radionet = 0 - camera = 0 - network = 0 - power = 0 + var/datum/money_account/CH = get_account(C.associated_account_number) + if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2) + if(vendor_account) + var/attempt_pin = input("Enter pin code", "Vendor transaction") as num + var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) + if(D) + transfer_and_vend(D, C) else - usr << "\icon[src]You don't have that much money!" + usr << "\icon[src]Unable to access account. Check security settings and try again." else - usr << "\icon[src]Unable to access account. Check security settings and try again." + usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." else - usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." + transfer_and_vend(CH, C) + + +// Transfers money and vends the laptop. +/obj/machinery/lapvend/proc/transfer_and_vend(var/datum/money_account/D, var/obj/item/weapon/card/C) + var/transaction_amount = total() + if(transaction_amount <= D.money) + + //transfer the money + D.money -= transaction_amount + vendor_account.money += transaction_amount + //Transaction logs + var/datum/transaction/T = new() + T.target_name = "[vendor_account.owner_name] (via [src.name])" + T.purpose = "Purchase of Laptop" + if(transaction_amount > 0) + T.amount = "([transaction_amount])" + else + T.amount = "[transaction_amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + D.transaction_log.Add(T) + // + T = new() + T.target_name = D.owner_name + T.purpose = "Purchase of Laptop" + T.amount = "[transaction_amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + vendor_account.transaction_log.Add(T) + + newlap = new /obj/machinery/computer3/laptop/vended(src.loc) + + choose_progs(C) + vend() + popup.close() + newlap.close_computer() + newlap = null + cardreader = 0 + floppy = 0 + radionet = 0 + camera = 0 + network = 0 + power = 0 + else + usr << "\icon[src]You don't have that much money!" /obj/machinery/lapvend/proc/total() var/total = 0 @@ -352,49 +360,53 @@ if (istype(I, /obj/item/weapon/card/id)) var/obj/item/weapon/card/id/C = I visible_message("[usr] swipes a card through [src].") - if(vendor_account) - var/attempt_pin = input("Enter pin code", "Vendor transaction") as num - var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) - if(D) - var/transaction_amount = total() - - //transfer the money - D.money += transaction_amount - vendor_account.money -= transaction_amount - - //Transaction logs - var/datum/transaction/T = new() - T.target_name = "[vendor_account.owner_name] (via [src.name])" - T.purpose = "Return purchase of Laptop" - if(transaction_amount > 0) - T.amount = "([transaction_amount])" + var/datum/money_account/CH = get_account(C.associated_account_number) + if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2) + if(vendor_account) + var/attempt_pin = input("Enter pin code", "Vendor transaction") as num + var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) + if(D) + transfer_and_reimburse(D) else - T.amount = "[transaction_amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - D.transaction_log.Add(T) - // - T = new() - T.target_name = D.owner_name - T.purpose = "Return purchase of Laptop" - T.amount = "[transaction_amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - vendor_account.transaction_log.Add(T) - - del(relap) - - vendmode = 0 - cardreader = 0 - floppy = 0 - radionet = 0 - camera = 0 - network = 0 - power = 0 - + usr << "\icon[src]Unable to access account. Check security settings and try again." else - usr << "\icon[src]Unable to access account. Check security settings and try again." + usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." else - usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." \ No newline at end of file + transfer_and_reimburse(CH) + +/obj/machinery/lapvend/proc/transfer_and_reimburse(var/datum/money_account/D) + var/transaction_amount = total() + //transfer the money + D.money += transaction_amount + vendor_account.money -= transaction_amount + + //Transaction logs + var/datum/transaction/T = new() + T.target_name = "[vendor_account.owner_name] (via [src.name])" + T.purpose = "Return purchase of Laptop" + if(transaction_amount > 0) + T.amount = "([transaction_amount])" + else + T.amount = "[transaction_amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + D.transaction_log.Add(T) + // + T = new() + T.target_name = D.owner_name + T.purpose = "Return purchase of Laptop" + T.amount = "[transaction_amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + vendor_account.transaction_log.Add(T) + + del(relap) + vendmode = 0 + cardreader = 0 + floppy = 0 + radionet = 0 + camera = 0 + network = 0 + power = 0 \ No newline at end of file diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 5dd31a036e..009ab4c809 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -187,53 +187,60 @@ if (istype(I, /obj/item/weapon/card/id)) var/obj/item/weapon/card/id/C = I visible_message("[usr] swipes a card through [src].") - if(check_accounts) - if(vendor_account) - var/attempt_pin = input("Enter pin code", "Vendor transaction") as num - var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) - if(D) - var/transaction_amount = currently_vending.price - if(transaction_amount <= D.money) - - //transfer the money - D.money -= transaction_amount - vendor_account.money += transaction_amount - - //create entries in the two account transaction logs - var/datum/transaction/T = new() - T.target_name = "[vendor_account.owner_name] (via [src.name])" - T.purpose = "Purchase of [currently_vending.product_name]" - if(transaction_amount > 0) - T.amount = "([transaction_amount])" - else - T.amount = "[transaction_amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - D.transaction_log.Add(T) - // - T = new() - T.target_name = D.owner_name - T.purpose = "Purchase of [currently_vending.product_name]" - T.amount = "[transaction_amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - vendor_account.transaction_log.Add(T) - - // Vend the item - src.vend(src.currently_vending, usr) - currently_vending = null + var/datum/money_account/CH = get_account(C.associated_account_number) + if (CH) // Only proceed if card contains proper account number. + if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2) + if(vendor_account) + var/attempt_pin = input("Enter pin code", "Vendor transaction") as num + var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2) + transfer_and_vend(D) else - usr << "\icon[src]You don't have that much money!" + usr << "\icon[src]Unable to access account. Check security settings and try again." else - usr << "\icon[src]Unable to access account. Check security settings and try again." + //Just Vend it. + transfer_and_vend(CH) else - //Just Vend it. + usr << "\icon[src]Error: Unable to access your account. Please contact technical support if problem persists." + +/obj/machinery/vending/proc/transfer_and_vend(var/datum/money_account/acc) + if(acc) + var/transaction_amount = currently_vending.price + if(transaction_amount <= acc.money) + + //transfer the money + acc.money -= transaction_amount + vendor_account.money += transaction_amount + + //create entries in the two account transaction logs + var/datum/transaction/T = new() + T.target_name = "[vendor_account.owner_name] (via [src.name])" + T.purpose = "Purchase of [currently_vending.product_name]" + if(transaction_amount > 0) + T.amount = "([transaction_amount])" + else + T.amount = "[transaction_amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + acc.transaction_log.Add(T) + // + T = new() + T.target_name = acc.owner_name + T.purpose = "Purchase of [currently_vending.product_name]" + T.amount = "[transaction_amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + vendor_account.transaction_log.Add(T) + + // Vend the item src.vend(src.currently_vending, usr) currently_vending = null + else + usr << "\icon[src]You don't have that much money!" else - usr << "\icon[src]Unable to access vendor account. Please record the machine ID and call CentComm Support." + usr << "\icon[src]Error: Unable to access your account. Please contact technical support if problem persists." + /obj/machinery/vending/attack_paw(mob/user as mob) return attack_hand(user) From 97e3b0e38e4599e6d85efba16f57d55013842faf Mon Sep 17 00:00:00 2001 From: Whitellama Date: Sat, 19 Jul 2014 17:01:28 -0700 Subject: [PATCH 12/28] Gave gardeners access to the rest of the hydroponics pasture, fixing #5690 --- maps/tgstation2.dmm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maps/tgstation2.dmm b/maps/tgstation2.dmm index d7b9db15d2..82877105a9 100644 --- a/maps/tgstation2.dmm +++ b/maps/tgstation2.dmm @@ -1649,7 +1649,7 @@ "aFK" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/wall,/area/storage/tools) "aFL" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/manifold/hidden/supply,/turf/simulated/wall,/area/maintenance/port) "aFM" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/turf/simulated/wall,/area/storage/tools) -"aFN" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/door/airlock/glass{name = "Hydroponics Pasture"; req_access_txt = "28"},/turf/simulated/floor,/area/hydroponics) +"aFN" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/door/airlock/glass{name = "Hydroponics Pasture"; req_access_txt = "35"},/turf/simulated/floor,/area/hydroponics) "aFO" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/turf/simulated/wall,/area/crew_quarters/locker) "aFP" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24},/turf/simulated/floor/plating,/area/maintenance/port) "aFQ" = (/obj/machinery/door/airlock/command{name = "Conference Room"; req_access = null; req_access_txt = "19"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/wood,/area/bridge/meeting_room) From 342a187c8bf856a86bf281c03a758250ff012afb Mon Sep 17 00:00:00 2001 From: Whitellama Date: Sat, 19 Jul 2014 18:33:30 -0700 Subject: [PATCH 13/28] Eating with utensils now produces the eating sound, fixed #5687 --- code/game/objects/items/weapons/kitchen.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index 4181ef6e20..5d72495520 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -32,7 +32,7 @@ /obj/item/weapon/kitchen/utensil/New() if (prob(60)) src.pixel_y = rand(0, 4) - + create_reagents(5) return @@ -58,7 +58,7 @@ for(var/mob/O in viewers(M, null)) O.show_message(text("\blue [] feeds [] some [] from \the []", user, M, loaded, src), 1) M.reagents.add_reagent("nutriment", 1) - + playsound(M.loc,'sound/items/eatfood.ogg', rand(10,40), 1) overlays.Cut() return From e8c4ad07bb20a3aa07934830b8d9c301750b731c Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sat, 19 Jul 2014 22:08:31 -0400 Subject: [PATCH 14/28] Adds a system for refitting species clothing --- code/game/machinery/suit_storage_unit.dm | 16 +++------------- code/game/objects/items.dm | 12 ++++++++++++ code/game/objects/items/devices/modkit.dm | 19 ++++++++++--------- code/modules/clothing/clothing.dm | 21 +++++++++++++++++++++ 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 7e6f1e3f7e..2db29d4ab0 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -1064,19 +1064,9 @@ if(!target_species || !target_department) return - switch(target_species) - if("Skrell") - if(helmet) helmet.species_restricted = list("Skrell") - if(suit) suit.species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox") - if("Human") - if(helmet) helmet.species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox","Skrell") - if(suit) suit.species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox") - if("Unathi") - if(helmet) helmet.species_restricted = list("Unathi") - if(suit) suit.species_restricted = list("Unathi") - if("Tajaran") - if(helmet) helmet.species_restricted = list("Tajaran") - if(suit) suit.species_restricted = list("Tajaran") + if(target_species) + if(helmet) helmet.refit_for_species(target_species) + if(suit) suit.refit_for_species(target_species) switch(target_department) if("Engineering") diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6beb98c40c..935760efdb 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -49,6 +49,18 @@ var/list/sprite_sheets = null var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc. + /* Species-specific sprite sheets for object and inhand sprites + Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called. + */ + var/list/sprite_sheets_obj = null + + //Inhand is not as big a deal as the object sprites, so I'm not sure if these are worth the extra vars. + //Maybe in the future: + //var/list/sprite_sheets_inhand_l = null + //var/list/sprite_sheets_inhand_r = null + //var/icon_l_hand = 'icons/mob/items_lefthand.dmi' + //var/icon_r_hand = 'icons/mob/items_righthand.dmi' + /obj/item/device icon = 'icons/obj/device.dmi' diff --git a/code/game/objects/items/devices/modkit.dm b/code/game/objects/items/devices/modkit.dm index dd7c1231f4..bbab8870b1 100644 --- a/code/game/objects/items/devices/modkit.dm +++ b/code/game/objects/items/devices/modkit.dm @@ -7,7 +7,7 @@ desc = "A kit containing all the needed tools and parts to modify a hardsuit for another user." icon_state = "modkit" var/parts = MODKIT_FULL - var/list/target_species = list("Human","Skrell") + var/target_species = null var/list/permitted_types = list( /obj/item/clothing/head/helmet/space/rig, @@ -38,20 +38,21 @@ var/obj/item/clothing/I = O if(istype(I)) - I.species_restricted = target_species.Copy() + if (target_species) + I.refit_for_species(target_species) + else + I.refit_for_species("Human") parts-- if(!parts) user.drop_from_inventory(src) del(src) +/obj/item/device/modkit/examine() + ..() + usr << "It looks as though it modifies hardsuits to fit the following [target_species? target_species : "Human"] users." + /obj/item/device/modkit/tajaran name = "tajaran hardsuit modification kit" desc = "A kit containing all the needed tools and parts to modify a hardsuit for another user. This one looks like it's meant for Tajara." - target_species = list("Tajaran") - -/obj/item/device/modkit/examine() - ..() - usr << "It looks as though it modifies hardsuits to fit the following users:" - for(var/species in target_species) - usr << "- [species]" \ No newline at end of file + target_species = "Tajaran" \ No newline at end of file diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 034fede96a..5ad55ff557 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -32,6 +32,27 @@ return 1 +/obj/item/clothing/proc/refit_for_species(var/target_species) + switch(target_species) + if("Human", "Skrell") //humanoid bodytypes + species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox") + else + species_restricted = list(target_species) + + if (sprite_sheets_obj && (target_species in sprite_sheets_obj)) + icon = sprite_sheets_obj[target_species] + +/obj/item/clothing/head/helmet/refit_for_species(var/target_species) + switch(target_species) + if("Human") + species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox") + else + species_restricted = list(target_species) + + if (sprite_sheets_obj && (target_species in sprite_sheets_obj)) + icon = sprite_sheets_obj[target_species] + + //Ears: headsets, earmuffs and tiny objects /obj/item/clothing/ears name = "ears" From 266d8d25fa191a0420e8749a788a76cac1372580 Mon Sep 17 00:00:00 2001 From: Whitellama Date: Sat, 19 Jul 2014 19:11:30 -0700 Subject: [PATCH 15/28] Fixed #5685: Changelings now gain the species needed to transform when acquiring DNA using the extract DNA sting --- code/game/gamemodes/changeling/changeling_powers.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index c338b2e42d..be2bb88a17 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -844,11 +844,13 @@ var/list/datum/dna/hivemind_bank = list() if(!changeling) return 0 - var/mob/living/carbon/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting) + var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting) if(!T) return 0 T.dna.real_name = T.real_name changeling.absorbed_dna |= T.dna + if(T.species && !(T.species.name in changeling.absorbed_species)) + changeling.absorbed_species += T.species.name feedback_add_details("changeling_powers","ED") return 1 \ No newline at end of file From fced4969805a8b1ddae675127de0b04854c78cea Mon Sep 17 00:00:00 2001 From: Walter0o Date: Sun, 20 Jul 2014 04:21:48 +0200 Subject: [PATCH 16/28] fixes simple_animals using FEA instead of ZAS i can't believe after all this time animals still use FEA instead of ZAS. this should fix the "random" animal deaths. --- .../mob/living/simple_animal/simple_animal.dm | 76 +++++++++---------- 1 file changed, 35 insertions(+), 41 deletions(-) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 906acdbfb2..0360de52b0 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -141,48 +141,42 @@ //Atmos var/atmos_suitable = 1 - var/atom/A = src.loc - if(isturf(A)) - var/turf/T = A - var/areatemp = T.temperature - if( abs(areatemp - bodytemperature) > 40 ) - var/diff = areatemp - bodytemperature - diff = diff / 5 - //world << "changed from [bodytemperature] by [diff] to [bodytemperature + diff]" - bodytemperature += diff + var/atom/A = src.loc - if(istype(T,/turf/simulated)) - var/turf/simulated/ST = T - if(ST.air) - var/tox = ST.air.phoron - var/oxy = ST.air.oxygen - var/n2 = ST.air.nitrogen - var/co2 = ST.air.carbon_dioxide - - if(min_oxy) - if(oxy < min_oxy) - atmos_suitable = 0 - if(max_oxy) - if(oxy > max_oxy) - atmos_suitable = 0 - if(min_tox) - if(tox < min_tox) - atmos_suitable = 0 - if(max_tox) - if(tox > max_tox) - atmos_suitable = 0 - if(min_n2) - if(n2 < min_n2) - atmos_suitable = 0 - if(max_n2) - if(n2 > max_n2) - atmos_suitable = 0 - if(min_co2) - if(co2 < min_co2) - atmos_suitable = 0 - if(max_co2) - if(co2 > max_co2) - atmos_suitable = 0 + if(istype(A,/turf)) + var/turf/T = A + + var/datum/gas_mixture/Environment = T.return_air() + + if(Environment) + + if( abs(Environment.temperature - bodytemperature) > 40 ) + bodytemperature += ((Environment.temperature - bodytemperature) / 5) + + if(min_oxy) + if(Environment.oxygen < min_oxy) + atmos_suitable = 0 + if(max_oxy) + if(Environment.oxygen > max_oxy) + atmos_suitable = 0 + if(min_tox) + if(Environment.phoron < min_tox) + atmos_suitable = 0 + if(max_tox) + if(Environment.phoron > max_tox) + atmos_suitable = 0 + if(min_n2) + if(Environment.nitrogen < min_n2) + atmos_suitable = 0 + if(max_n2) + if(Environment.nitrogen > max_n2) + atmos_suitable = 0 + if(min_co2) + if(Environment.carbon_dioxide < min_co2) + atmos_suitable = 0 + if(max_co2) + if(Environment.carbon_dioxide > max_co2) + atmos_suitable = 0 //Atmos effect if(bodytemperature < minbodytemp) From 4c6017cfaaea2791f5d7290e2c58567dcb1f3457 Mon Sep 17 00:00:00 2001 From: Walter0o Date: Sun, 20 Jul 2014 04:37:42 +0200 Subject: [PATCH 17/28] fixes borer infest and detatch --- .../modules/mob/living/simple_animal/borer.dm | 78 ++++++++++++++++--- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/code/modules/mob/living/simple_animal/borer.dm b/code/modules/mob/living/simple_animal/borer.dm index 19ad62d4ae..e90b13993b 100644 --- a/code/modules/mob/living/simple_animal/borer.dm +++ b/code/modules/mob/living/simple_animal/borer.dm @@ -31,7 +31,7 @@ desc = "A small, quivering sluglike creature." speak_emote = list("chirrups") emote_hear = list("chirrups") - response_help = "pokes the" + response_help = "pokes" response_disarm = "prods the" response_harm = "stomps on the" icon_state = "brainslug" @@ -234,14 +234,45 @@ src << "\red You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system." host << "\red You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours." + // host -> brain + var/h2b_id = host.computer_id + var/h2b_ip= host.lastKnownIP + host.computer_id = null + host.lastKnownIP = null + + del(host_brain) + host_brain = new(src) + host_brain.ckey = host.ckey + + if(!host_brain.computer_id) + host_brain.computer_id = h2b_id + + if(!host_brain.lastKnownIP) + host_brain.lastKnownIP = h2b_ip + + // self -> host + var/s2h_id = src.computer_id + var/s2h_ip= src.lastKnownIP + src.computer_id = null + src.lastKnownIP = null + host.ckey = src.ckey + + if(!host.computer_id) + host.computer_id = s2h_id + + if(!host.lastKnownIP) + host.lastKnownIP = s2h_ip + controlling = 1 host.verbs += /mob/living/carbon/proc/release_control host.verbs += /mob/living/carbon/proc/punish_host host.verbs += /mob/living/carbon/proc/spawn_larvae + return + /mob/living/simple_animal/borer/verb/secrete_chemicals() set category = "Alien" set name = "Secrete Chemicals" @@ -329,20 +360,45 @@ mob/living/simple_animal/borer/proc/detatch() host.verbs -= /mob/living/carbon/proc/punish_host host.verbs -= /mob/living/carbon/proc/spawn_larvae - if(host_brain.ckey) + + if(host_brain && host_brain.ckey) + + // host -> self + var/h2s_id = host.computer_id + var/h2s_ip= host.lastKnownIP + host.computer_id = null + host.lastKnownIP = null + src.ckey = host.ckey + + if(!src.computer_id) + src.computer_id = h2s_id + + if(!host_brain.lastKnownIP) + src.lastKnownIP = h2s_ip + + // brain -> host + var/b2h_id = host_brain.computer_id + var/b2h_ip= host_brain.lastKnownIP + host_brain.computer_id = null + host_brain.lastKnownIP = null + host.ckey = host_brain.ckey - host_brain.ckey = null - host_brain.name = "host brain" - host_brain.real_name = "host brain" + + if(!host.computer_id) + host.computer_id = b2h_id + + if(!host.lastKnownIP) + host.lastKnownIP = b2h_ip + + del(host_brain) var/mob/living/H = host + H.status_flags &= ~PASSEMOTES + host = null - for(var/atom/A in H.contents) - if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder)) - return - H.status_flags &= ~PASSEMOTES + return /mob/living/simple_animal/borer/verb/infest() set category = "Alien" @@ -408,8 +464,6 @@ mob/living/simple_animal/borer/proc/detatch() var/datum/organ/external/head = H.get_organ("head") head.implants += src - host_brain.name = M.name - host_brain.real_name = M.real_name host.status_flags |= PASSEMOTES return @@ -503,4 +557,4 @@ mob/living/simple_animal/borer/proc/transfer_personality(var/client/candidate) src.mind = candidate.mob.mind src.ckey = candidate.ckey if(src.mind) - src.mind.assigned_role = "Cortical Borer" \ No newline at end of file + src.mind.assigned_role = "Cortical Borer" From 70b1d8dc655195fba916b9655f849702a753e474 Mon Sep 17 00:00:00 2001 From: Walter0o Date: Sun, 20 Jul 2014 04:40:58 +0200 Subject: [PATCH 18/28] borer detatch fixes --- code/modules/mob/living/living.dm | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 9865901886..4cfad2504a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -486,14 +486,8 @@ B.host.adjustBrainLoss(rand(5,10)) H << "\red With an immense exertion of will, you regain control of your body!" B.host << "\red You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you." - B.controlling = 0 - B.ckey = B.host.ckey - B.host.ckey = H.ckey - - H.ckey = null - H.name = "host brain" - H.real_name = "host brain" + B.detatch() verbs -= /mob/living/carbon/proc/release_control verbs -= /mob/living/carbon/proc/punish_host From 9be8f496ae27ab3cbca0540f45ffd646f9e0c61e Mon Sep 17 00:00:00 2001 From: Walter0o Date: Sun, 20 Jul 2014 04:42:14 +0200 Subject: [PATCH 19/28] borer detatch fixes --- code/modules/mob/living/carbon/carbon.dm | 26 +++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index a3c9babd97..7659dc8d57 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -423,23 +423,17 @@ var/mob/living/simple_animal/borer/B = has_brain_worms() - if(!B) - return - - if(B.controlling) + if(B && B.host_brain) src << "\red You withdraw your probosci, releasing control of [B.host_brain]" - B.host_brain << "\red Your vision swims as the alien parasite releases control of your body." - B.ckey = ckey - B.controlling = 0 - if(B.host_brain.ckey) - ckey = B.host_brain.ckey - B.host_brain.ckey = null - B.host_brain.name = "host brain" - B.host_brain.real_name = "host brain" - verbs -= /mob/living/carbon/proc/release_control - verbs -= /mob/living/carbon/proc/punish_host - verbs -= /mob/living/carbon/proc/spawn_larvae + B.detatch() + + verbs -= /mob/living/carbon/proc/release_control + verbs -= /mob/living/carbon/proc/punish_host + verbs -= /mob/living/carbon/proc/spawn_larvae + + else + src << "\red ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !" //Brain slug proc for tormenting the host. /mob/living/carbon/proc/punish_host() @@ -486,4 +480,4 @@ else src << "You do not have enough chemicals stored to reproduce." - return \ No newline at end of file + return From 789d3e4d54eb22ebc28536437cf7652f3ff6cd47 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sat, 19 Jul 2014 22:20:30 -0400 Subject: [PATCH 20/28] Fixes modkits Fixes modkits not tracking suit/helmet parts, not checking allowed parts, and not checking if the clothing needs to be modified. --- code/game/objects/items/devices/modkit.dm | 34 +++++++++++++++-------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/code/game/objects/items/devices/modkit.dm b/code/game/objects/items/devices/modkit.dm index bbab8870b1..2921559a63 100644 --- a/code/game/objects/items/devices/modkit.dm +++ b/code/game/objects/items/devices/modkit.dm @@ -22,11 +22,20 @@ del(src) return - /* TODO: list comparison - if(istype(O,to_type)) - user << "[O] is already modified." + var/allowed = 0 + for (var/permitted_type in permitted_types) + if(istype(O, permitted_type)) + allowed = 1 + + var/obj/item/clothing/I = O + if (!istype(I) || !allowed) + user << "[src] is unable to modify that." return - */ + + var/excluding = ("exclude" in I.species_restricted) + var/in_list = (target_species in I.species_restricted) + if (excluding ^ in_list) + user << "[I] is already modified." if(!isturf(O.loc)) user << "[O] must be safely placed on the ground for modification." @@ -36,14 +45,17 @@ user.visible_message("\red [user] opens \the [src] and modifies \the [O].","\red You open \the [src] and modify \the [O].") - var/obj/item/clothing/I = O - if(istype(I)) - if (target_species) - I.refit_for_species(target_species) - else - I.refit_for_species("Human") + if (target_species) + I.refit_for_species(target_species) + else + I.refit_for_species("Human") - parts-- + + if (istype(I, /obj/item/clothing/head/helmet)) + parts &= ~MODKIT_HELMET + if (istype(I, /obj/item/clothing/suit)) + parts &= ~MODKIT_SUIT + if(!parts) user.drop_from_inventory(src) del(src) From 3d9f1754cd6413f2efdd8407aab133dce3cc4729 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sat, 19 Jul 2014 23:02:26 -0400 Subject: [PATCH 21/28] Updates eng rig path, adds obj sprites Adds object sprite sheets for tajaran, unathi and skrell hardsuits, where the icons were available (just engineering and syndie hardsuits for now). Makes engineering hardsuits a subtype of the parent rig type, so it is now possible to update eng hardsuits without affecting every other hardsuit type. --- code/modules/awaymissions/corpse.dm | 4 +- code/modules/clothing/spacesuits/rig.dm | 55 ++++++++++++++++--- icons/obj/clothing/species/skrell/hats.dmi | Bin 0 -> 876 bytes icons/obj/clothing/species/skrell/suits.dmi | Bin 0 -> 447 bytes icons/obj/clothing/species/tajaran/hats.dmi | Bin 0 -> 2340 bytes icons/obj/clothing/species/tajaran/suits.dmi | Bin 0 -> 863 bytes icons/obj/clothing/species/unathi/hats.dmi | Bin 0 -> 2013 bytes icons/obj/clothing/species/unathi/suits.dmi | Bin 0 -> 452 bytes maps/tgstation2.dmm | 10 ++-- 9 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 icons/obj/clothing/species/skrell/hats.dmi create mode 100644 icons/obj/clothing/species/skrell/suits.dmi create mode 100644 icons/obj/clothing/species/tajaran/hats.dmi create mode 100644 icons/obj/clothing/species/tajaran/suits.dmi create mode 100644 icons/obj/clothing/species/unathi/hats.dmi create mode 100644 icons/obj/clothing/species/unathi/suits.dmi diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index e9304976cc..b90fbe5b7f 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -161,9 +161,9 @@ corpseidaccess = "Station Engineer" /obj/effect/landmark/corpse/engineer/rig - corpsesuit = /obj/item/clothing/suit/space/rig + corpsesuit = /obj/item/clothing/suit/space/rig/engineering corpsemask = /obj/item/clothing/mask/breath - corpsehelmet = /obj/item/clothing/head/helmet/space/rig + corpsehelmet = /obj/item/clothing/head/helmet/space/rig/engineering /obj/effect/landmark/corpse/clown name = "Clown" diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index 995e116717..4009d1a8f8 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -1,10 +1,10 @@ //Regular rig suits /obj/item/clothing/head/helmet/space/rig - name = "engineering hardsuit helmet" - desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding." + name = "hardsuit helmet" + desc = "A special helmet designed for work in a hazardous, low-pressure environment." icon_state = "rig0-engineering" item_state = "eng_helm" - armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 20) allowed = list(/obj/item/device/flashlight) var/brightness_on = 4 //luminosity when on var/on = 0 @@ -49,13 +49,13 @@ SetLuminosity(brightness_on) /obj/item/clothing/suit/space/rig - name = "engineering hardsuit" - desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding." + name = "hardsuit" + desc = "A special space suit for environments that might pose hazards beyond just the vacuum of space. Provides more protection than a standard space suit." icon_state = "rig-engineering" item_state = "eng_hardsuit" slowdown = 1 - armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd) + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 20) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit) heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE @@ -292,21 +292,46 @@ ..() +//Engineering rig +/obj/item/clothing/head/helmet/space/rig/engineering + name = "engineering hardsuit helmet" + desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding." + icon_state = "rig0-engineering" + item_state = "eng_helm" + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) + sprite_sheets_obj = list( + "Tajaran" = 'icons/obj/clothing/species/tajaran/hats.dmi', + ) + +/obj/item/clothing/suit/space/rig/engineering + name = "engineering hardsuit" + desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding." + icon_state = "rig-engineering" + item_state = "eng_hardsuit" + slowdown = 1 + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd) + sprite_sheets_obj = list( + "Tajaran" = 'icons/obj/clothing/species/tajaran/suits.dmi', + ) + //Chief Engineer's rig -/obj/item/clothing/head/helmet/space/rig/elite +/obj/item/clothing/head/helmet/space/rig/engineering/chief name = "advanced hardsuit helmet" desc = "An advanced helmet designed for work in a hazardous, low pressure environment. Shines with a high polish." icon_state = "rig0-white" item_state = "ce_helm" item_color = "white" sprite_sheets = null + sprite_sheets_obj = null -/obj/item/clothing/suit/space/rig/elite +/obj/item/clothing/suit/space/rig/engineering/chief icon_state = "rig-white" name = "advanced hardsuit" desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish." item_state = "ce_hardsuit" sprite_sheets = null + sprite_sheets_obj = null //Mining rig /obj/item/clothing/head/helmet/space/rig/mining @@ -336,6 +361,13 @@ siemens_coefficient = 0.6 var/obj/machinery/camera/camera species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox") + sprite_sheets_obj = list( + "Tajaran" = 'icons/obj/clothing/species/tajaran/hats.dmi', + "Unathi" = 'icons/obj/clothing/species/unathi/hats.dmi', + "Skrell" = 'icons/obj/clothing/species/skrell/hats.dmi', + ) + + /obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user) if(camera) ..(user) @@ -362,6 +394,11 @@ allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs) siemens_coefficient = 0.6 species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox") + sprite_sheets_obj = list( + "Tajaran" = 'icons/obj/clothing/species/tajaran/suits.dmi', + "Unathi" = 'icons/obj/clothing/species/unathi/suits.dmi', + "Skrell" = 'icons/obj/clothing/species/skrell/suits.dmi', + ) //Wizard Rig diff --git a/icons/obj/clothing/species/skrell/hats.dmi b/icons/obj/clothing/species/skrell/hats.dmi new file mode 100644 index 0000000000000000000000000000000000000000..10d3e059cfed2261ea25bef2f82d4c93e5a91c47 GIT binary patch literal 876 zcmV-y1C#uTP)Tb*ElE9MJ&5_LvVUNZc0tZTQ;+ZO1OPSaf3p&9u9|g zX@8ejl&Dmgm`s7$c{CyUTX?=; zjQ@;|!C+N6JX%sjj{lCC!)150TZ{jTnZ#vSNkNakUwOo1ivNmtx?WdCKx2GUg1~fi zqEU~$UXZ(8WPVg)1OuUPIDe{Mq^w)ADHDH9I<|sHnUF|#xLvN4P*ej0WD^UbYBYDH zXQFL3R0IQLUon52Sz`|ge?2qiw0qkC0004WQchCV=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+(=$pS zoZ^zil2jm5sVFnuK)1LuFC{ZoiHkEOv#1y-YRJWzR+N~V3SlFwH6)-`S;5uM1?&(2 zBvL5=^F%-70005ANkl55QdxXHU_-92)0@k5v_`X_kE!OFZ}<%$4x=U zF)7OMNtYSA>=WL+*-bs~ABD)tf6K=f@XZ&P`1~~z&q{zMAXfkaIUxf#Hzh!&Kq;f( z6o8;moGcasC-;0I`2R*gp%4xMF(s#GX2aQ;X*uQK!bem{R3hRh`rq3m{6H4x%9Z&_ zd9Ek}i+fQd080QdKnX!ak;NAllcnXAcx8DhSzNHVCn7+I393LbXOZO~TCIigT7A8~ z5r?%^i}MaCLRGPVssg4C2b)Q_wcXfh>~4k0rprP4#X;(D&`iR(wYPuJVh2r!1CgfO z17eL5rm3(Th{L1g_~bM`J2_6y4=v6s0J;A>1)c@>z~&e7^6HwWaD8%wNq)iZK4uRp^)7(Hpon^cOS^_`tzQul3=N@4Q&n$i}$T`9=o>?4> zmoJ3-2*bG9fV=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+ z(=$pSoZ^zil2jm5sVFmDx41GdB{Nlti!&v&s2C_{$iH{I&!j9b${h8i)2`XBTMPB!f5Kso(6*yx_Hp0AFo zbsz-^dSC@K3(DuVolw&al>vbr-vsXq8&EfO=zmayuB)+ pex?Ab{kOpVF-QPb2gKHAatB{`Hm!Djox%VB002ovPDHLkV1hiZy5j%< literal 0 HcmV?d00001 diff --git a/icons/obj/clothing/species/tajaran/hats.dmi b/icons/obj/clothing/species/tajaran/hats.dmi new file mode 100644 index 0000000000000000000000000000000000000000..81d8a5810d8e65bbab520d548311c5696ac9ff1a GIT binary patch literal 2340 zcmV+<3ETFGP)V=-0C=30jIj#BFcd}Sysx;lb0t;RERrG_+J7kInY_UWFQMY!J9Kdp-R^;N zZjZ}!4Ga7nXk)GNC~!C*ESaaomf>(ZlF2M7w;gI*8^fVfNp|3pq%f_h&Hv8`z<~N)-O>{JYy@T0Hz5=na33Mv)tf0G|K=2vtc$K~#90?V4L`6IU9? ze-2KZ8OKgy?3gqJV>v)JEVpv+C76~=WI|IZYtoq*cp4NyA)waFWxb^>aXHz1qN4ZF4^#}gkf6QQqB`W(=( zYfEy`v_V?$7O`{Jr^uz$Tc5Hiw z(dY~(d@|01(ay0|8%;e%;T5pO3Ki%3$ z>3j%X98^56;yoY|2@e+si>3`yX%zsdvPAMM-DB*O0Ll9 zbV!m!d1(>wp!kd325hrep%+psxxBOpNs`htMG2!CAc_K!NSM>}_u#q~1RxNUxqj&s zmZfVlW`OHjkkj+`3@;ZU>q4KTFUvAl?Qb(!SPek=)P+RDA+!b)(Qt_JsS5!ZEUf0L z{cU7fR;;gR2AE8fS%2?CzNp-nHsMiR*MfXexsUbtKE!02tVmobB?be_y1(Je&~iGu zVzl2lpAm1rah{H@7+;2#v#k3YN(=_YV`udsWLdfG51+oUtT*-FfE%MaIgnm} zX7kR5oIDI|-r1lzdHe`EosOyBZ=%V$jgGDu9^U{b+~DyI(9sp6$+?ZG-)};v({b|n z5ykq7p927FHXFR@;5w54SbKOn*8{0*)0>V|d;+mpEUKiP zqG$!;%3fcw0V7EOSSnJk+o#*Pedjg+Ql|tkA;nLm zepUuNoP<$dn7-E+j*m%vEaX~0YXcrlWURvDC0F`mHsF7S{J+H1PC#w)2B@8Y+T;yT zI{~%H8=!UqYLhoW?F7^&Z-Ckfs7>AgwG&XAtPE({`0i6rT}O+Lmx<6KwOr(BR=K{APF}8_a{9(@Aj3oSX z=JN57pIebwHp6AjMCfO=2OKS&%B@I@uZR4stJ342GnaK$dcGbOKUz37>jV@bqz+$> z8f|I)wKb)5)-PghP3Z%Dqb;Mq5=J#(WcsxT)od&5A~2NXr@klvOQWe5BYx_O5*SLd zt+0z0p*p9_plSQo=gO+76_b-L~IxRL*2%_wxllw8ofqFE1^i{@5A(-l3~J&yqLaj5vr+o zf5MI3`*|(iKBl4{gQzj+m}!a=a=WS6>?B|@BiqX;sL-Q9LqUZe*sHh=Z{3%x!+`hg<)KWjxR zng~fr65UZ4Opxe~5|WZ=MHBs>wW1#=qSxog{MG9(0NtbQ0a-lWt$zd(SY4Lg~bjB z$KodfeuYj*GZ zdrIGTpZ;hVy{4FC?+|)TaZ2BJKck;gvOXQ&vEh$N0JHJIt7u(){Q!LYx4%yKF?p`_ z$9z0KlE_$v$4jpC^X~_!oq*cp4NyA)waFWxb^>aXH$d$K)aJh(KG3jLwMeG`0000< KMNUMnLSTY>z;t+W!D$u!nYO6`cQuc4?@Tg*Po4 zu7)?D5xAQG0004WQchCV=-0C=2JR&a84_w-Y6 z@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5sVFmDH#ILk zGcPr@C^IiziHkEOv#1y-W5~ssR+N~V3SpzDFRsi>$xOwiR9V5*&jsuj0N@oWo-i6* z%K!iZ6-h)vR7i={Rbg|RFbuVjE!!&~TtlF+txMYf{~ITh<+czxyW6)Z*El_)m#6n6 z$C&>sphPv>pmlOMi;bEmA7cCxWALQrv3U^$C-pB4YW1Ow5TpFHK}Bc~yB-<)4pj<1 zv=pU-NNw;+en|Y<=Ml%;zj7M14hSY`VFJ>67*00vIOj3XBPV-$K%lsQAiPOEEb$Rx z=u+x=%$P^+Q|gWY6iB`q;#&k^LXRq}DXmgJZ$g6QA3W$72@1gUbt(Wr@d&`Y8bN5b zM(PdYx9|6P?-!Ae;2lV$T>Mc+|z;5*~d0$kBAj% z{a6!gt5gD(2_j5OZJ}|_EC4Ke>JNAiFabQwz%4j`B7ZP`X4dQ5GEBg7)+itkc3?zh z7tPfPVW2s1qrk&SUaS+4X_SSEP!9cpRc5fWoy?z9RMh$LtIW)=pu)PAJ{!SkzKB&Z^kpsE9ZB0PbRyR0?@zY(62ke#Yd p;tk;$gYxt6_copf)#l(I<0qE*98wZ-1%Chl002ovPDHLkV1mSSa8dvO literal 0 HcmV?d00001 diff --git a/icons/obj/clothing/species/unathi/hats.dmi b/icons/obj/clothing/species/unathi/hats.dmi new file mode 100644 index 0000000000000000000000000000000000000000..66a740039ce7946f3896ed9a0543e0336bf0ecd4 GIT binary patch literal 2013 zcmV<32O{{1P)V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex7wuvIWN;^NFm z%}mcIfpCgT5=&AQY!#G>GSdxoi!1X|GEFs|@93 z6L{J9+JKb=drtmXt`?D(#o_A=c+o)Z$lEf%eHmB{4h0*~cIxE3MfwL5^V;XlTTQG5 zhk^`fJ9SdFzW0I1_HQ&b$$-}iK)`F|MpIL6!PfUa5Nlz=T5(v?fQ1VKe5UIx)?aNC z){?`rYe0K2D4YH2y!31KtF#A$|Fc@KnjF6LyFj|g06@lSe4+S74QM-cQr6XO0%l!r z4+dqO5OhW~g0EHa*K79(zE(wNM59iK+#G?=((ty~Rvt-5JiN>k**$8h801)u3qknh^fadf_Zk%YGo-=3Rjh!o$J&Q+w_#>NZ z%c$7qrY|;4h1bSlO2uAXf>X5o7X^cya(TIk3yQF4dlHNaGK-sc&(Q_|qfcN9> zocPX&M$L)ign@%?9su^Tm&;rRAly0(KGs#sNYsbzcvH#3NRIF2t8%Ok_Oy~#sTO({UHE*PCpqN;C=Sw&F$s$r{Z1& zbK>2AU0G*mu*ifcEn@2KJuoYH`gKejEJ$5v#y*T|Vg{)QL{ev38A2vAC@w2ez*Oe} z*a1uc;e{p?ybU({Rn}K;p-u>z{VMP7tfo!~-rZUK)YwXpC%zu|mSu;BOm!Jbi3N|( zj>Bj`-Q>ZgfHUBt$fV#3xF~g5v6=*yic&mg1w*9+S?R#ww*%|~{B!4YXR`|m+y&f6 z4-+nNPy~#({eW(uh`rPUQJ|a42w=K(m@wcTpMc+VtW{q!Hjq|YYHuT*l#*-Q_!27v***cJ414>unb^vf&3?$N$ zoE;SenxVlR7h$46Ql0O&k_k$p|O>5($`?66$S5$y&3 z;j7-mz~An(LAdC-bQ3fke~*iD%5mYsfde;gJb3Wka6(2h&==*E4L%~1Nh-g$pXZ4O z5KH|paP>lm92=kD(#21yf6%`q`S8X7`uik;&h7wX)1c43@!s~Y=i6`Wpu}!x z=4a(giic$w0C3@>UrPY*GahmVf7AlNfp?CriTE6c&NGr3$-0kz4}gfLkTw${o?`GP zhhauy`(=&&SuZ}%!m>W29C+uLxO$;OX1B(COt0aUpU0v3sJMEeLvAiL&Hj+rPFsuF v)7&EHdVc&uEGq;4AMvICCb&|3iF3UAMS0FC{ZoiHkEOv#1y-XvoExR+N~V3SlcNxca$(%?1G2bQ}h~ zMpbtJ007`gL_t(2k#&$=PQx$^fSaCRb{6$@j<*BEkq?kD*5@qr0F{uq0OI^0P?Hpa z-~8$G?=buw24D}+`@>E^k)6Vp*`8YN;aN0cC8L+bbQNC((K8$`BAdd|(%Z^5R2FKL>(40Tg{hhj!IH&nZI*?zkx7;G0D&n0c5_YX_WTZa_yx@HUwi@y4