diff --git a/baystation12.dme b/baystation12.dme
index 8afada0ac4c..cda15ea108a 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1470,6 +1470,7 @@
#include "code\modules\modular_computers\hardware\nano_printer.dm"
#include "code\modules\modular_computers\hardware\network_card.dm"
#include "code\modules\modular_computers\hardware\portable_hard_drive.dm"
+#include "code\modules\modular_computers\hardware\processor_unit.dm"
#include "code\modules\modular_computers\hardware\tesla_link.dm"
#include "code\modules\modular_computers\NTNet\NTNet.dm"
#include "code\modules\modular_computers\NTNet\NTNet_relay.dm"
diff --git a/code/game/antagonist/outsider/actors.dm b/code/game/antagonist/outsider/actors.dm
index 013d7348fb4..7d5deb39e76 100644
--- a/code/game/antagonist/outsider/actors.dm
+++ b/code/game/antagonist/outsider/actors.dm
@@ -48,6 +48,9 @@ var/datum/antagonist/actor/actor
if(!MayRespawn(1))
return
+ var/choice = alert("Are you sure you'd like to join as an actor?", "Confirmation","Yes", "No")
+ if(choice != "Yes")
+ return
if(istype(usr,/mob/dead/observer) || istype(usr,/mob/new_player))
if(actor.current_antagonists.len >= actor.hard_cap)
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 67873874a27..cf7b1bbd94a 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -54,7 +54,7 @@
//give them an account in the station database
var/species_modifier = (H.species ? economic_species_modifier[H.species.type] : 2)
- if(species_modifier == 0)
+ if(!species_modifier)
species_modifier = economic_species_modifier[/datum/species/human]
var/money_amount = (rand(5,50) + rand(5, 50)) * loyalty * economic_modifier * species_modifier
diff --git a/code/game/machinery/computer/arcade_orion.dm b/code/game/machinery/computer/arcade_orion.dm
index 32fe89966fb..b713e69fb2d 100644
--- a/code/game/machinery/computer/arcade_orion.dm
+++ b/code/game/machinery/computer/arcade_orion.dm
@@ -85,6 +85,8 @@
view = ORION_VIEW_MAIN
/obj/machinery/computer/arcade/orion_trail/attack_hand(mob/user)
+ if(..())
+ return
var/dat = ""
if(event == null)
newgame()
diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm
index 4c44bcd4eeb..0ae1d2ceea1 100644
--- a/code/game/machinery/robot_fabricator.dm
+++ b/code/game/machinery/robot_fabricator.dm
@@ -71,47 +71,47 @@ Please wait until completion...
if (!src.operating)
var/part_type = text2num(href_list["make"])
- var/build_type = ""
+ var/build_type = null
var/build_time = 200
var/build_cost = 25000
switch (part_type)
if (1)
- build_type = "/obj/item/robot_parts/l_arm"
+ build_type = /obj/item/robot_parts/l_arm
build_time = 200
build_cost = 25000
if (2)
- build_type = "/obj/item/robot_parts/r_arm"
+ build_type = /obj/item/robot_parts/r_arm
build_time = 200
build_cost = 25000
if (3)
- build_type = "/obj/item/robot_parts/l_leg"
+ build_type = /obj/item/robot_parts/l_leg
build_time = 200
build_cost = 25000
if (4)
- build_type = "/obj/item/robot_parts/r_leg"
+ build_type = /obj/item/robot_parts/r_leg
build_time = 200
build_cost = 25000
if (5)
- build_type = "/obj/item/robot_parts/chest"
+ build_type = /obj/item/robot_parts/chest
build_time = 350
build_cost = 50000
if (6)
- build_type = "/obj/item/robot_parts/head"
+ build_type = /obj/item/robot_parts/head
build_time = 350
build_cost = 50000
if (7)
- build_type = "/obj/item/robot_parts/robot_suit"
+ build_type = /obj/item/robot_parts/robot_suit
build_time = 600
build_cost = 75000
- var/building = text2path(build_type)
+ var/building = build_type
if (!isnull(building))
if (src.metal_amount >= build_cost)
src.operating = 1
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index ccd660e5b6e..35ad6db8677 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -10,6 +10,7 @@
var/burn_point = null
var/burning = null
var/hitsound = null
+ var/storage_cost = null
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
var/no_attack_log = 0 //If it's an item we don't want to log attack_logs with, set this to 1
pass_flags = PASSTABLE
@@ -339,7 +340,7 @@ var/list/global/slot_flags_enumeration = list(
var/allow = 0
if(H.back && istype(H.back, /obj/item/weapon/storage/backpack))
var/obj/item/weapon/storage/backpack/B = H.back
- if(B.contents.len < B.storage_slots && w_class <= B.max_w_class)
+ if(B.can_be_inserted(src,1))
allow = 1
if(!allow)
return 0
@@ -614,6 +615,6 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
usr.visible_message("[zoomdevicename ? "[usr] looks up from the [src.name]" : "[usr] lowers the [src.name]"].")
return
-
+
/obj/item/proc/pwr_drain()
- return 0 // Process Kill
+ return 0 // Process Kill
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index a2707fd01f0..019bc2dece1 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -64,7 +64,7 @@
return
if(XRAY in M.mutations)
user << "\The [M] pupils give an eerie glow!"
- if(vision.is_bruised())
+ if(vision.damage)
user << "There's visible damage to [M]'s [vision.name]!"
else if(M.eye_blurry)
user << "\The [M]'s pupils react slower than normally."
@@ -79,7 +79,7 @@
user << "\The [M]'s pupils narrow slightly, but are still very dilated."
else
user << "\The [M]'s pupils narrow."
-
+
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //can be used offensively
flick("flash", M.flash)
else
diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm
index 218d2fb21cf..01ce9f87c8c 100644
--- a/code/game/objects/items/weapons/cosmetics.dm
+++ b/code/game/objects/items/weapons/cosmetics.dm
@@ -78,6 +78,4 @@
item_state = "purplecomb"
/obj/item/weapon/haircomb/attack_self(mob/user)
- if(user.r_hand == src || user.l_hand == src)
- user.visible_message(text("[] uses [] to comb their hair with incredible style and sophistication. What a [].", user, src, user.gender == FEMALE ? "lady" : "guy"))
- return
+ user.visible_message("[user] uses [src] to comb their hair with incredible style and sophistication. What a [user.gender == FEMALE ? "lady" : "guy"].")
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm
index f204a971feb..98e5c172c33 100644
--- a/code/game/objects/items/weapons/policetape.dm
+++ b/code/game/objects/items/weapons/policetape.dm
@@ -22,6 +22,19 @@ var/list/tape_roll_applications = list()
var/tape_dir = 0
var/icon_base = "tape"
+/obj/item/tape/update_icon()
+ //Possible directional bitflags: 0 (AIRLOCK), 1 (NORTH), 2 (SOUTH), 4 (EAST), 8 (WEST), 3 (VERTICAL), 12 (HORIZONTAL)
+ switch (tape_dir)
+ if(0) // AIRLOCK
+ icon_state = "[icon_base]_door_[crumpled]"
+ if(3) // VERTICAL
+ icon_state = "[icon_base]_v_[crumpled]"
+ if(12) // HORIZONTAL
+ icon_state = "[icon_base]_h_[crumpled]"
+ else // END POINT (1|2|4|8)
+ icon_state = "[icon_base]_dir_[crumpled]"
+ dir = tape_dir
+
/obj/item/tape/New()
..()
if(!hazard_overlays)
@@ -93,19 +106,26 @@ var/list/tape_roll_applications = list()
/obj/item/taperoll/update_icon()
overlays.Cut()
+ var/image/overlay = image(icon = src.icon)
+ overlay.appearance_flags = RESET_COLOR
if(ismob(loc))
if(!start)
- overlays += "start"
+ overlay.icon_state = "start"
else
- overlays += "stop"
+ overlay.icon_state = "stop"
+ overlays += overlay
/obj/item/taperoll/dropped(mob/user)
- ..()
update_icon()
+ return ..()
/obj/item/taperoll/pickup(mob/user)
- ..()
update_icon()
+ return ..()
+
+/obj/item/taperoll/attack_hand()
+ update_icon()
+ return ..()
/obj/item/taperoll/attack_self(mob/user as mob)
if(!start)
@@ -142,13 +162,13 @@ var/list/tape_roll_applications = list()
for(var/dir in list(NORTH, SOUTH))
if (possible_dirs & dir)
TP.tape_dir += dir
- TP.icon_state = "[TP.icon_base]_[TP.tape_dir]"
+ TP.update_icon()
if(possible_dirs & (EAST|WEST))
var/obj/item/tape/TP = new tape_type(start)
for(var/dir in list(EAST, WEST))
if (possible_dirs & dir)
TP.tape_dir += dir
- TP.icon_state = "[TP.icon_base]_[TP.tape_dir]"
+ TP.update_icon()
start = null
update_icon()
usr << "You finish placing \the [src]."
@@ -207,8 +227,8 @@ var/list/tape_roll_applications = list()
break
if(!tapetest)
var/obj/item/tape/T = new tape_type(cur)
- T.icon_state = "[T.icon_base]_[tape_dir]"
T.tape_dir = tape_dir
+ T.update_icon()
if(tape_dir & SOUTH)
T.layer += 0.1 // Must always show above other tapes
if(cur == end)
@@ -227,7 +247,7 @@ var/list/tape_roll_applications = list()
var/turf/T = get_turf(A)
var/obj/item/tape/P = new tape_type(T.x,T.y,T.z)
P.loc = locate(T.x,T.y,T.z)
- P.icon_state = "[src.icon_base]_door"
+ P.update_icon()
P.layer = 3.2
user << "You finish placing \the [src]."
@@ -251,7 +271,7 @@ var/list/tape_roll_applications = list()
/obj/item/tape/proc/crumple()
if(!crumpled)
crumpled = 1
- icon_state = "[icon_state]_c"
+ update_icon()
name = "crumpled [name]"
/obj/item/tape/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index d3c26d453c7..29a62117f35 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -22,8 +22,8 @@
)
w_class = 4
slot_flags = SLOT_BACK
- max_w_class = 3
- max_storage_space = 28
+ max_w_class = 4
+ max_storage_space = 16
/obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (src.use_sound)
@@ -53,6 +53,7 @@
icon_state = "holdingpack"
max_w_class = 4
max_storage_space = 56
+ storage_cost = 29
New()
..()
@@ -77,7 +78,6 @@
icon_state = "giftbag0"
item_state = "giftbag"
w_class = 4.0
- storage_slots = 20
max_w_class = 3
max_storage_space = 400 // can store a ton of shit!
item_state_slots = null
diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm
index 33fa1d6d7ea..476bf1a67eb 100644
--- a/code/game/objects/items/weapons/storage/bags.dm
+++ b/code/game/objects/items/weapons/storage/bags.dm
@@ -34,7 +34,6 @@
w_class = 4
max_w_class = 2
- storage_slots = 21
can_hold = list() // any
cant_hold = list(/obj/item/weapon/disk/nuclear)
@@ -61,7 +60,6 @@
w_class = 4
max_w_class = 2
- storage_slots = 21
can_hold = list() // any
cant_hold = list(/obj/item/weapon/disk/nuclear)
@@ -76,8 +74,7 @@
icon_state = "satchel"
slot_flags = SLOT_BELT | SLOT_POCKET
w_class = 3
- storage_slots = 50
- max_storage_space = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class
+ max_storage_space = 100
max_w_class = 3
can_hold = list(/obj/item/weapon/ore)
@@ -90,8 +87,7 @@
name = "plant bag"
icon = 'icons/obj/hydroponics_machines.dmi'
icon_state = "plantbag"
- storage_slots = 50; //the number of plant pieces it can carry.
- max_storage_space = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * plants.w_class
+ max_storage_space = 100
max_w_class = 3
w_class = 2
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/grown,/obj/item/seeds,/obj/item/weapon/grown)
@@ -111,6 +107,7 @@
var/capacity = 300; //the number of sheets it can carry.
w_class = 3
+ storage_slots = 7
allow_quick_empty = 1 // this function is superceded
New()
@@ -193,7 +190,7 @@
var/col_count = min(7,storage_slots) -1
if (adjusted_contents > 7)
row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width.
- src.standard_orient_objs(row_num, col_count, numbered_contents)
+ src.slot_orient_objs(row_num, col_count, numbered_contents)
return
@@ -248,8 +245,7 @@
icon = 'icons/obj/storage.dmi'
icon_state = "cashbag"
desc = "A bag for carrying lots of cash. It's got a big dollar sign printed on the front."
- storage_slots = 50; //the number of cash pieces it can carry.
- max_storage_space = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * cash.w_class
+ max_storage_space = 100
max_w_class = 3
w_class = 2
can_hold = list(/obj/item/weapon/coin,/obj/item/weapon/spacecash)
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index d9bf95dd72a..20771cdb069 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -4,6 +4,8 @@
icon = 'icons/obj/clothing/belts.dmi'
icon_state = "utilitybelt"
item_state = "utility"
+ storage_slots = 7
+ max_w_class = 3
slot_flags = SLOT_BELT
attack_verb = list("whipped", "lashed", "disciplined")
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/belt.dmi')
@@ -112,7 +114,6 @@
desc = "Can hold security gear like handcuffs and flashes."
icon_state = "securitybelt"
item_state = "security"
- storage_slots = 7
max_w_class = 3
max_storage_space = 28
can_hold = list(
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index 1372270bb91..843784345cb 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -478,7 +478,6 @@
desc = "Drymate brand monkey cubes. Just add water!"
icon = 'icons/obj/food.dmi'
icon_state = "monkeycubebox"
- storage_slots = 7
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/monkeycube)
New()
..()
@@ -592,11 +591,10 @@
desc = "Eight wrappers of fun! Ages 8 and up. Not suitable for children."
icon = 'icons/obj/toy.dmi'
icon_state = "spbox"
- storage_slots = 8
can_hold = list(/obj/item/toy/snappop)
New()
..()
- for(var/i=1; i <= storage_slots; i++)
+ for(var/i=1; i <= 8; i++)
new /obj/item/toy/snappop(src)
/obj/item/weapon/storage/box/matches
@@ -605,14 +603,13 @@
icon = 'icons/obj/cigarettes.dmi'
icon_state = "matchbox"
item_state = "zippo"
- storage_slots = 10
w_class = 1
slot_flags = SLOT_BELT
can_hold = list(/obj/item/weapon/flame/match)
New()
..()
- for(var/i=1; i <= storage_slots; i++)
+ for(var/i=1; i <= 10; i++)
new /obj/item/weapon/flame/match(src)
attackby(obj/item/weapon/flame/match/W as obj, mob/user as mob)
@@ -630,7 +627,7 @@
icon_state = "syringe"
New()
..()
- for (var/i; i < storage_slots; i++)
+ for (var/i; i < 7; i++)
new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src)
/obj/item/weapon/storage/box/lights
@@ -676,7 +673,6 @@
icon = 'icons/obj/storage.dmi'
icon_state = "portafreezer"
item_state = "medicalpack"
- storage_slots=7
max_w_class = 3
can_hold = list(/obj/item/organ, /obj/item/weapon/reagent_containers/food, /obj/item/weapon/reagent_containers/glass)
max_storage_space = 21
diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm
index 29926c4cbef..909cfb502d1 100644
--- a/code/game/objects/items/weapons/storage/fancy.dm
+++ b/code/game/objects/items/weapons/storage/fancy.dm
@@ -69,14 +69,13 @@
icon_state = "candlebox5"
icon_type = "candle"
item_state = "candlebox5"
- storage_slots = 5
throwforce = 2
slot_flags = SLOT_BELT
/obj/item/weapon/storage/fancy/candle_box/New()
..()
- for(var/i=1; i <= storage_slots; i++)
+ for(var/i=1; i <= 5; i++)
new /obj/item/weapon/flame/candle(src)
return
@@ -90,7 +89,6 @@
icon = 'icons/obj/crayons.dmi'
icon_state = "crayonbox"
w_class = 2.0
- storage_slots = 6
icon_type = "crayon"
can_hold = list(
/obj/item/weapon/pen/crayon
diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm
index a76fb4f1a1f..40a05659ec1 100644
--- a/code/game/objects/items/weapons/storage/firstaid.dm
+++ b/code/game/objects/items/weapons/storage/firstaid.dm
@@ -161,7 +161,6 @@
can_hold = list(/obj/item/weapon/reagent_containers/pill,/obj/item/weapon/dice,/obj/item/weapon/paper)
allow_quick_gather = 1
use_to_pickup = 1
- storage_slots = 14
use_sound = null
/obj/item/weapon/storage/pill_bottle/antitox
diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm
index c904907f640..c900a2a8c8b 100644
--- a/code/game/objects/items/weapons/storage/lockbox.dm
+++ b/code/game/objects/items/weapons/storage/lockbox.dm
@@ -8,7 +8,6 @@
w_class = 4
max_w_class = 3
max_storage_space = 14 //The sum of the w_classes of all the items in this storage item.
- storage_slots = 4
req_access = list(access_armory)
var/locked = 1
var/broken = 0
diff --git a/code/game/objects/items/weapons/storage/misc.dm b/code/game/objects/items/weapons/storage/misc.dm
index eb63c96cb8b..e024e6ca5c8 100644
--- a/code/game/objects/items/weapons/storage/misc.dm
+++ b/code/game/objects/items/weapons/storage/misc.dm
@@ -15,7 +15,6 @@
icon = 'icons/obj/food.dmi'
icon_state = "donutbox"
name = "donut box"
- storage_slots = 6
var/startswith = 6
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/donut)
foldable = /obj/item/stack/material/cardboard
diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm
index 73e3fb0108c..3950ea89093 100644
--- a/code/game/objects/items/weapons/storage/secure.dm
+++ b/code/game/objects/items/weapons/storage/secure.dm
@@ -33,7 +33,7 @@
attackby(obj/item/weapon/W as obj, mob/user as mob)
if(locked)
- if (emag_act(INFINITY, user, "You slice through the lock of \the [src]"))
+ if (istype(W, /obj/item/weapon/melee/energy/blade) && emag_act(INFINITY, user, "You slice through the lock of \the [src]"))
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src.loc)
spark_system.start()
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index 8a9c00ce3bd..c6ee578dcee 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -12,10 +12,16 @@
var/list/can_hold = new/list() //List of objects which this item can store (if set, it can't store anything else)
var/list/cant_hold = new/list() //List of objects which this item can't store (in effect only if can_hold isn't set)
var/list/is_seeing = new/list() //List of mobs which are currently seeing the contents of this item's storage
- var/max_w_class = 2 //Max size of objects that this object can store (in effect only if can_hold isn't set)
- var/max_storage_space = 14 //The sum of the storage costs of all the items in this storage item.
- var/storage_slots = 7 //The number of storage slots in this container.
+ var/max_w_class = 3 //Max size of objects that this object can store (in effect only if can_hold isn't set)
+ var/max_storage_space = 8 //The sum of the storage costs of all the items in this storage item.
+ var/storage_slots = null //The number of storage slots in this container.
var/obj/screen/storage/boxes = null
+ var/obj/screen/storage/storage_start = null //storage UI
+ var/obj/screen/storage/storage_continue = null
+ var/obj/screen/storage/storage_end = null
+ var/obj/screen/storage/stored_start = null
+ var/obj/screen/storage/stored_continue = null
+ var/obj/screen/storage/stored_end = null
var/obj/screen/close/closer = null
var/use_to_pickup //Set this to make it possible to use this item in an inverse way, so you can have the item in your hand and click items on the floor to pick them up.
var/display_contents_with_number //Set this to make the storage item group contents of the same type and display them as a number.
@@ -27,6 +33,12 @@
/obj/item/weapon/storage/Destroy()
close_all()
qdel(boxes)
+ qdel(src.storage_start)
+ qdel(src.storage_continue)
+ qdel(src.storage_end)
+ qdel(src.stored_start)
+ qdel(src.stored_continue)
+ qdel(src.stored_end)
qdel(closer)
..()
@@ -90,11 +102,19 @@
if(user.s_active)
user.s_active.hide_from(user)
user.client.screen -= src.boxes
+ user.client.screen -= src.storage_start
+ user.client.screen -= src.storage_continue
+ user.client.screen -= src.storage_end
user.client.screen -= src.closer
user.client.screen -= src.contents
- user.client.screen += src.boxes
user.client.screen += src.closer
user.client.screen += src.contents
+ if(storage_slots)
+ user.client.screen += src.boxes
+ else
+ user.client.screen += src.storage_start
+ user.client.screen += src.storage_continue
+ user.client.screen += src.storage_end
user.s_active = src
is_seeing |= user
return
@@ -104,6 +124,9 @@
if(!user.client)
return
user.client.screen -= src.boxes
+ user.client.screen -= src.storage_start
+ user.client.screen -= src.storage_continue
+ user.client.screen -= src.storage_end
user.client.screen -= src.closer
user.client.screen -= src.contents
if(user.s_active == src)
@@ -155,7 +178,7 @@
return
//This proc draws out the inventory and places the items on it. It uses the standard position.
-/obj/item/weapon/storage/proc/standard_orient_objs(var/rows, var/cols, var/list/obj/item/display_contents)
+/obj/item/weapon/storage/proc/slot_orient_objs(var/rows, var/cols, var/list/obj/item/display_contents)
var/cx = 4
var/cy = 2+rows
src.boxes.screen_loc = "4:16,2:16 to [4+cols]:16,[2+rows]:16"
@@ -181,6 +204,51 @@
src.closer.screen_loc = "[4+cols+1]:16,2:16"
return
+/obj/item/weapon/storage/proc/space_orient_objs(var/list/obj/item/display_contents)
+
+ var/baseline_max_storage_space = 16 //should be equal to default backpack capacity
+ var/storage_cap_width = 2 //length of sprite for start and end of the box representing total storage space
+ var/stored_cap_width = 4 //length of sprite for start and end of the box representing the stored item
+ var/storage_width = min( round( 224 * max_storage_space/baseline_max_storage_space ,1) ,284) //length of sprite for the box representing total storage space
+
+ storage_start.overlays.Cut()
+
+ var/matrix/M = matrix()
+ M.Scale((storage_width-storage_cap_width*2+3)/32,1)
+ src.storage_continue.transform = M
+
+ src.storage_start.screen_loc = "4:16,2:16"
+ src.storage_continue.screen_loc = "4:[storage_cap_width+(storage_width-storage_cap_width*2)/2+2],2:16"
+ src.storage_end.screen_loc = "4:[19+storage_width-storage_cap_width],2:16"
+
+ var/startpoint = 0
+ var/endpoint = 1
+
+ for(var/obj/item/O in contents)
+ startpoint = endpoint + 1
+ endpoint += storage_width * O.get_storage_cost()/max_storage_space
+
+ var/matrix/M_start = matrix()
+ var/matrix/M_continue = matrix()
+ var/matrix/M_end = matrix()
+ M_start.Translate(startpoint,0)
+ M_continue.Scale((endpoint-startpoint-stored_cap_width*2)/32,1)
+ M_continue.Translate(startpoint+stored_cap_width+(endpoint-startpoint-stored_cap_width*2)/2 - 16,0)
+ M_end.Translate(endpoint-stored_cap_width,0)
+ src.stored_start.transform = M_start
+ src.stored_continue.transform = M_continue
+ src.stored_end.transform = M_end
+ storage_start.overlays += src.stored_start
+ storage_start.overlays += src.stored_continue
+ storage_start.overlays += src.stored_end
+
+ O.screen_loc = "4:[round((startpoint+endpoint)/2)+2],2:16"
+ O.maptext = ""
+ O.layer = 20
+
+ src.closer.screen_loc = "4:[storage_width+19],2:16"
+ return
+
/datum/numbered_display
var/obj/item/sample_object
var/number
@@ -212,12 +280,14 @@
adjusted_contents++
numbered_contents.Add( new/datum/numbered_display(I) )
- //var/mob/living/carbon/human/H = user
- var/row_num = 0
- var/col_count = min(7,storage_slots) -1
- if (adjusted_contents > 7)
- row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width.
- src.standard_orient_objs(row_num, col_count, numbered_contents)
+ if(storage_slots == null)
+ src.space_orient_objs(numbered_contents)
+ else
+ var/row_num = 0
+ var/col_count = min(7,storage_slots) -1
+ if (adjusted_contents > 7)
+ row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width.
+ src.slot_orient_objs(row_num, col_count, numbered_contents)
return
//This proc return 1 if the item can be picked up and 0 if it can't.
@@ -225,12 +295,12 @@
/obj/item/weapon/storage/proc/can_be_inserted(obj/item/W as obj, stop_messages = 0)
if(!istype(W)) return //Not an item
- if(usr.isEquipped(W) && !usr.canUnEquip(W))
+ if(usr && usr.isEquipped(W) && !usr.canUnEquip(W))
return 0
if(src.loc == W)
return 0 //Means the item is already in the storage item
- if(contents.len >= storage_slots)
+ if(storage_slots != null && contents.len >= storage_slots)
if(!stop_messages)
usr << "[src] is full, make some space."
return 0 //Storage item is full
@@ -254,9 +324,9 @@
usr << "[src] cannot hold [W]."
return 0
- if (W.w_class > max_w_class)
+ if (max_w_class != null && W.w_class > max_w_class)
if(!stop_messages)
- usr << "[W] is too big for this [src]."
+ usr << "[W] is too long for this [src]."
return 0
var/total_storage_space = W.get_storage_cost()
@@ -265,7 +335,7 @@
if(total_storage_space > max_storage_space)
if(!stop_messages)
- usr << "[src] is full, make some space."
+ usr << "[src] is too full, make some space."
return 0
if(W.w_class >= src.w_class && (istype(W, /obj/item/weapon/storage)))
@@ -442,12 +512,48 @@
else
verbs -= /obj/item/weapon/storage/verb/toggle_gathering_mode
+ spawn(5)
+ var/total_storage_space = 0
+ for(var/obj/item/I in contents)
+ total_storage_space += I.get_storage_cost()
+ max_storage_space = max(total_storage_space,max_storage_space) //prevents spawned containers from being too small for their contents
+
src.boxes = new /obj/screen/storage( )
src.boxes.name = "storage"
src.boxes.master = src
src.boxes.icon_state = "block"
src.boxes.screen_loc = "7,7 to 10,8"
src.boxes.layer = 19
+
+ src.storage_start = new /obj/screen/storage( )
+ src.storage_start.name = "storage"
+ src.storage_start.master = src
+ src.storage_start.icon_state = "storage_start"
+ src.storage_start.screen_loc = "7,7 to 10,8"
+ src.storage_start.layer = 19
+ src.storage_continue = new /obj/screen/storage( )
+ src.storage_continue.name = "storage"
+ src.storage_continue.master = src
+ src.storage_continue.icon_state = "storage_continue"
+ src.storage_continue.screen_loc = "7,7 to 10,8"
+ src.storage_continue.layer = 19
+ src.storage_end = new /obj/screen/storage( )
+ src.storage_end.name = "storage"
+ src.storage_end.master = src
+ src.storage_end.icon_state = "storage_end"
+ src.storage_end.screen_loc = "7,7 to 10,8"
+ src.storage_end.layer = 19
+
+ src.stored_start = new /obj //we just need these to hold the icon
+ src.stored_start.icon_state = "stored_start"
+ src.stored_start.layer = 19
+ src.stored_continue = new /obj
+ src.stored_continue.icon_state = "stored_continue"
+ src.stored_continue.layer = 19
+ src.stored_end = new /obj
+ src.stored_end.icon_state = "stored_end"
+ src.stored_end.layer = 19
+
src.closer = new /obj/screen/close( )
src.closer.master = src
src.closer.icon_state = "x"
@@ -516,4 +622,20 @@
return depth
/obj/item/proc/get_storage_cost()
- return 2**(w_class-1) //1,2,4,8,16,...
+ if (storage_cost)
+ return storage_cost
+ else
+ if(w_class == 1)
+ return 1
+ if(w_class == 2)
+ return 2
+ if(w_class == 3)
+ return 4
+ if(w_class == 4)
+ return 8
+ if(w_class == 5)
+ return 16
+ else
+ return 1000
+
+ //return 2**(w_class-1) //1,2,4,8,16,...
diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm
index 02ce84f0726..11dcdc8879a 100644
--- a/code/game/objects/items/weapons/storage/toolbox.dm
+++ b/code/game/objects/items/weapons/storage/toolbox.dm
@@ -11,7 +11,7 @@
throw_range = 7
w_class = 4
max_w_class = 3
- max_storage_space = 14 //can hold 7 w_class-2 items or up to 3 w_class-3 items (with 1 w_class-2 item as change).
+ max_storage_space = 14 //enough to hold all starting contents
origin_tech = list(TECH_COMBAT = 1)
attack_verb = list("robusted")
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 5b46e990f0b..fcd5693d76d 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -127,7 +127,6 @@
/obj/item/weapon/storage/box/syndie_kit/chameleon
name = "chameleon kit"
desc = "Comes with all the clothes you need to impersonate most people. Acting lessons sold seperately."
- storage_slots = 10
/obj/item/weapon/storage/box/syndie_kit/chameleon/New()
..()
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index aced90f9bb6..261aa3266a8 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -30,7 +30,7 @@
/obj/structure/mirror/bullet_act(var/obj/item/projectile/Proj)
-
+
if(prob(Proj.get_structure_damage() * 2))
if(!shattered)
shatter()
@@ -64,6 +64,13 @@
user.visible_message("[user] hits [src] and bounces off!")
return 1
+/obj/structure/mirror/Destroy()
+ for(var/user in ui_users)
+ var/datum/nano_module/appearance_changer/AC = ui_users[user]
+ qdel(AC)
+ ui_users.Cut()
+ ..()
+
// The following mirror is ~special~.
/obj/structure/mirror/raider
name = "cracked mirror"
@@ -91,3 +98,27 @@
raiders.update_access(vox)
qdel(user)
..()
+
+/obj/item/weapon/mirror
+ name = "mirror"
+ desc = "A SalonPro Nano-Mirror(TM) brand mirror! Now a portable version."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "mirror"
+ var/list/ui_users = list()
+
+/obj/item/weapon/mirror/attack_self(mob/user as mob)
+ if(ishuman(user))
+ var/datum/nano_module/appearance_changer/AC = ui_users[user]
+ if(!AC)
+ AC = new(src, user)
+ AC.name = "SalonPro Nano-Mirror™"
+ AC.flags = APPEARANCE_HAIR
+ ui_users[user] = AC
+ AC.ui_interact(user)
+
+/obj/item/weapon/mirror/Destroy()
+ for(var/user in ui_users)
+ var/datum/nano_module/appearance_changer/AC = ui_users[user]
+ qdel(AC)
+ ui_users.Cut()
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 8a9e29a0da2..58f89dc3fff 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -413,6 +413,9 @@
req_access = list(access_crematorium)
id = 1
+/obj/machinery/button/crematorium/update_icon()
+ return
+
/obj/machinery/button/crematorium/attack_hand(mob/user as mob)
if(..())
return
diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm
index c8cc2660c97..118f2277695 100644
--- a/code/game/turfs/simulated/floor_attackby.dm
+++ b/code/game/turfs/simulated/floor_attackby.dm
@@ -57,13 +57,13 @@
var/decl/flooring/F = flooring_types[flooring_type]
if(!F.build_type)
continue
- if((S.type == F.build_type) || (S.build_type == F.build_type))
+ if(ispath(S.type, F.build_type) || ispath(S.build_type, F.build_type))
use_flooring = F
break
if(!use_flooring)
return
// Do we have enough?
- if(use_flooring.build_cost && S.amount < use_flooring.build_cost)
+ if(use_flooring.build_cost && S.get_amount() < use_flooring.build_cost)
user << "You require at least [use_flooring.build_cost] [S.name] to complete the [use_flooring.descriptor]."
return
// Stay still and focus...
diff --git a/code/modules/alarm/alarm_handler.dm b/code/modules/alarm/alarm_handler.dm
index afa45d7649c..9cf52add77b 100644
--- a/code/modules/alarm/alarm_handler.dm
+++ b/code/modules/alarm/alarm_handler.dm
@@ -50,6 +50,11 @@
/datum/alarm_handler/proc/major_alarms()
return alarms
+/datum/alarm_handler/proc/has_major_alarms()
+ if(alarms && alarms.len)
+ return 1
+ return 0
+
/datum/alarm_handler/proc/minor_alarms()
return alarms
diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm
index e236c523890..680e6221523 100644
--- a/code/modules/client/preference_setup/general/03_body.dm
+++ b/code/modules/client/preference_setup/general/03_body.dm
@@ -180,7 +180,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
return mob_species && (mob_species.appearance_flags & flag)
/datum/category_item/player_setup_item/general/body/OnTopic(var/href,var/list/href_list, var/mob/user)
- var/mob_species = all_species[pref.species]
+ var/datum/species/mob_species = all_species[pref.species]
if(href_list["random"])
pref.randomize_appearance_for()
@@ -217,7 +217,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
continue
if(pref.gender == FEMALE && S.gender == MALE)
continue
- if(!(pref.species in S.species_allowed))
+ if(!(mob_species.get_bodytype() in S.species_allowed))
continue
valid_hairstyles[hairstyle] = hair_styles_list[hairstyle]
@@ -235,7 +235,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
continue
if(pref.gender == FEMALE && S.gender == MALE)
continue
- if(!(pref.species in S.species_allowed))
+ if(!(mob_species.get_bodytype() in S.species_allowed))
continue
valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle]
@@ -268,7 +268,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
var/list/valid_hairstyles = list()
for(var/hairstyle in hair_styles_list)
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
- if(!(pref.species in S.species_allowed))
+ if(!(mob_species.get_bodytype() in S.species_allowed))
continue
valid_hairstyles[hairstyle] = hair_styles_list[hairstyle]
@@ -324,7 +324,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
continue
if(pref.gender == FEMALE && S.gender == MALE)
continue
- if(!(pref.species in S.species_allowed))
+ if(!(mob_species.get_bodytype() in S.species_allowed))
continue
valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle]
diff --git a/code/modules/client/preferences_gear.dm b/code/modules/client/preferences_gear.dm
index 40cd37094dd..dfc26cb7c6a 100644
--- a/code/modules/client/preferences_gear.dm
+++ b/code/modules/client/preferences_gear.dm
@@ -1233,6 +1233,12 @@ var/global/list/gear_datums = list()
sort_category = "misc"
cost = 1
+/datum/gear/mirror
+ display_name = "handheld mirror"
+ path = /obj/item/weapon/mirror
+ sort_category = "misc"
+ cost = 1
+
/datum/gear/zippo
display_name = "zippo"
path = /obj/item/weapon/flame/lighter/zippo
diff --git a/code/modules/games/boardgame.dm b/code/modules/games/boardgame.dm
index cb25dabdb24..54a9866ea4d 100644
--- a/code/modules/games/boardgame.dm
+++ b/code/modules/games/boardgame.dm
@@ -1,8 +1,3 @@
-/*TODO:
- implement icon loading that is efficient using browse_rsc
- implement being able to move pieces
-*/
-
/obj/item/weapon/board
name = "board"
desc = "A standard 12' checkerboard. Well used."
@@ -14,6 +9,13 @@
var/board = list()
var/selected = -1
+/obj/item/weapon/board/New()
+ ..()
+ var i
+ for(i = 0; i < 12; i++)
+ new /obj/item/weapon/checker(src.loc)
+ new /obj/item/weapon/checker/red(src.loc)
+
/obj/item/weapon/board/examine(mob/user, var/distance = -1)
if(in_range(user,src))
user.set_machine(src)
@@ -21,29 +23,56 @@
return
..()
+/obj/item/weapon/board/attack_hand(mob/living/carbon/human/M as mob)
+ if(M.machine == src)
+ ..()
+ else
+ src.examine(M)
+
obj/item/weapon/board/attackby(obj/item/I as obj, mob/user as mob)
+ if(!addPiece(I,user))
+ ..()
+
+/obj/item/weapon/board/proc/addPiece(obj/item/I as obj, mob/user as mob, var/tile = 0)
if(I.w_class != 1) //only small stuff
user.show_message("\The [I] is too big to be used as a board piece.")
- return
+ return 0
if(num == 64)
user.show_message("\The [src] is already full!")
- return
+ return 0
+ if(tile > 0 && board["[tile]"])
+ user.show_message("That space is already filled!")
+ return 0
+ if(!user.Adjacent(src))
+ return 0
+
user.drop_from_inventory(I)
I.forceMove(src)
num++
+
if(!board_icons["[I.icon] [I.icon_state]"])
board_icons["[I.icon] [I.icon_state]"] = new /icon(I.icon,I.icon_state)
- var i;
- for(i=0;i<64;i++)
- if(!board["[i]"])
- board["[i]"] = I
- break
+ if(tile == 0)
+ var i;
+ for(i=0;i<64;i++)
+ if(!board["[i]"])
+ board["[i]"] = I
+ break
+ else
+ board["[tile]"] = I
src.updateDialog()
+ return 1
+
+
/obj/item/weapon/board/interact(mob/user as mob)
+ if(user.incapacitated(INCAPACITATION_DISABLED) || (!isAI(user) && !user.Adjacent(src))) //can't see if you arent conscious. If you are not an AI you can't see it unless you are next to it, either.
+ user << browse(null, "window=boardgame")
+ user.unset_machine()
+ return
var/dat = ""
dat += "
"
@@ -81,42 +110,61 @@ obj/item/weapon/board/attackby(obj/item/I as obj, mob/user as mob)
onclose(usr, "boardgame")
/obj/item/weapon/board/Topic(href, href_list)
- if(href_list["select"])
- var/s = href_list["select"]
- var/obj/item/I = board["[s]"]
- if(selected >= 0)
- if(I) //cant put items on other items.
- return
+ if(!usr.Adjacent(src))
+ usr.unset_machine()
+ usr << browse(null, "window=boardgame")
+ return
+
+ if(!usr.incapacitated()) //you can't move pieces if you can't move
+ if(href_list["select"])
+ var/s = href_list["select"]
+ var/obj/item/I = board["[s]"]
+ if(selected >= 0)
+ //check to see if clicked on tile is currently selected one
+ if(text2num(s) == selected)
+ selected = 0 //deselect it
+ return
+
+ if(I) //cant put items on other items.
+ return
//put item in new spot.
- I = board["[selected]"]
+ I = board["[selected]"]
+ board["[selected]"] = null
+ board -= "[selected]"
+ board -= null
+ board["[s]"] = I
+ selected = -1
+ else
+ if(I)
+ selected = text2num(s)
+ else
+ var/mob/living/carbon/human/H = locate(href_list["person"])
+ if(!istype(H))
+ return
+ var/obj/item/O = H.get_active_hand()
+ if(!O)
+ return
+ addPiece(O,H,text2num(s))
+ if(href_list["remove"])
+ var/obj/item/I = board["[selected]"]
board["[selected]"] = null
board -= "[selected]"
board -= null
- board["[s]"] = I
+ I.forceMove(src.loc)
+ num--
selected = -1
- else
- if(I)
- selected = text2num(s)
- if(href_list["remove"])
- var/obj/item/I = board["[selected]"]
- board["[selected]"] = null
- board -= "[selected]"
- board -= null
- I.forceMove(src.loc)
- num--
- selected = -1
- var j
- for(j=0;j<64;j++)
- if(board["[j]"])
- var/obj/item/K = board["[j]"]
- if(K.icon == I.icon && cmptext(K.icon_state,I.icon_state))
- src.updateDialog()
- return
- //Didn't find it in use, remove it and allow GC to delete it.
- board_icons["[I.icon] [I.icon_state]"] = null
- board_icons -= "[I.icon] [I.icon_state]"
- board_icons -= null
+ var j
+ for(j=0;j<64;j++)
+ if(board["[j]"])
+ var/obj/item/K = board["[j]"]
+ if(K.icon == I.icon && cmptext(K.icon_state,I.icon_state))
+ src.updateDialog()
+ return
+ //Didn't find it in use, remove it and allow GC to delete it.
+ board_icons["[I.icon] [I.icon_state]"] = null
+ board_icons -= "[I.icon] [I.icon_state]"
+ board_icons -= null
src.updateDialog()
/obj/item/weapon/checker/
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index e1061b09958..2655878aa6d 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -1,7 +1,13 @@
//This proc is called whenever someone clicks an inventory ui slot.
/mob/proc/attack_ui(slot)
var/obj/item/W = get_active_hand()
- if(istype(W))
+ var/obj/item/E = get_equipped_item(slot)
+ if (istype(E))
+ if(istype(W))
+ E.attackby(W,src)
+ else
+ E.attack_hand(src)
+ else
equip_to_slot_if_possible(W, slot)
/mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1, redraw_mob = 1)
@@ -77,13 +83,13 @@ var/list/slot_equipment_priority = list( \
// Try put it in their backpack
if(istype(src.back,/obj/item/weapon/storage))
var/obj/item/weapon/storage/backpack = src.back
- if(backpack.contents.len < backpack.storage_slots)
+ if(backpack.can_be_inserted(newitem, 1))
newitem.forceMove(src.back)
return 1
// Try to place it in any item that can store stuff, on the mob.
for(var/obj/item/weapon/storage/S in src.contents)
- if (S.contents.len < S.storage_slots)
+ if(S.can_be_inserted(newitem, 1))
newitem.forceMove(S)
return 1
return 0
@@ -186,7 +192,7 @@ var/list/slot_equipment_priority = list( \
wear_mask = null
update_inv_wear_mask(0)
return
-
+
/mob/proc/isEquipped(obj/item/I)
if(!I)
return 0
diff --git a/code/modules/mob/living/bot/cleanbot.dm b/code/modules/mob/living/bot/cleanbot.dm
index fe5f7317240..7ce6f684191 100644
--- a/code/modules/mob/living/bot/cleanbot.dm
+++ b/code/modules/mob/living/bot/cleanbot.dm
@@ -26,6 +26,8 @@
var/blood = 1
var/list/target_types = list()
+ var/maximum_search_range = 7
+
/mob/living/bot/cleanbot/New()
..()
get_targets()
@@ -36,6 +38,25 @@
if(radio_controller)
radio_controller.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
+/mob/living/bot/cleanbot/proc/handle_target()
+ if(loc == target.loc)
+ if(!cleaning)
+ UnarmedAttack(target)
+ return 1
+ if(!path.len)
+// spawn(0)
+ path = AStar(loc, target.loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard)
+ if(!path)
+ custom_emote(2, "[src] can't reach the target and is giving up.")
+ target = null
+ path = list()
+ return
+ if(path.len)
+ step_to(src, path[1])
+ path -= path[1]
+ return 1
+ return
+
/mob/living/bot/cleanbot/Life()
..()
@@ -46,7 +67,7 @@
return
if(cleaning)
return
-
+
if(!screwloose && !oddbutton && prob(5))
custom_emote(2, "makes an excited beeping booping sound!")
@@ -74,65 +95,64 @@
spawn(600)
ignorelist -= gib
- if(!target) // Find a target
- for(var/obj/effect/decal/cleanable/D in view(7, src))
- if(D in ignorelist)
- continue
- for(var/T in target_types)
- if(istype(D, T))
- target = D
- patrol_path = list()
+ // Find a target
+
+ if(pulledby) // Don't wiggle if someone pulls you
+ patrol_path = list()
+ return
- if(!target) // No targets in range
- if(!should_patrol)
- return
+ var/found_spot
+ search_loop:
+ for(var/i=0, i <= maximum_search_range, i++)
+ for(var/obj/effect/decal/cleanable/D in view(i, src))
+ if(D in ignorelist)
+ continue
+ for(var/T in target_types)
+ if(istype(D, T))
+ patrol_path = list()
+ target = D
+ found_spot = handle_target()
+ if (found_spot)
+ break search_loop
+ else
+ target = null
+ continue // no need to check the other types
- if(!patrol_path || !patrol_path.len)
- if(!signal_sent || signal_sent > world.time + 200) // Waited enough or didn't send yet
- var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq)
- if(!frequency)
- return
- closest_dist = 9999
- next_dest = null
- next_dest_loc = null
-
- var/datum/signal/signal = new()
- signal.source = src
- signal.transmission_method = 1
- signal.data = list("findbeakon" = "patrol")
- frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS)
- signal_sent = world.time
- else
- if(next_dest)
- next_dest_loc = listener.memorized[next_dest]
- if(next_dest_loc)
- patrol_path = AStar(loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id = botcard, exclude = null)
- signal_sent = 0
- else
- if(pulledby) // Don't wiggle if someone pulls you
- patrol_path = list()
+ if(!found_spot && !target) // No targets in range
+ if(!patrol_path || !patrol_path.len)
+ if(!signal_sent || signal_sent > world.time + 200) // Waited enough or didn't send yet
+ var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq)
+ if(!frequency)
return
- if(patrol_path[1] == loc)
- patrol_path -= patrol_path[1]
- var/moved = step_towards(src, patrol_path[1])
- if(moved)
- patrol_path -= patrol_path[1]
- if(target)
- if(loc == target.loc)
- if(!cleaning)
- UnarmedAttack(target)
+
+ closest_dist = 9999
+ next_dest = null
+ next_dest_loc = null
+
+ var/datum/signal/signal = new()
+ signal.source = src
+ signal.transmission_method = 1
+ signal.data = list("findbeakon" = "patrol")
+ frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS)
+ signal_sent = world.time
+ else
+ if(next_dest)
+ next_dest_loc = listener.memorized[next_dest]
+ if(next_dest_loc)
+ patrol_path = AStar(loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id = botcard, exclude = null)
+ signal_sent = 0
+ else
+ if(pulledby) // Don't wiggle if someone pulls you
+ patrol_path = list()
return
- if(!path.len)
- spawn(0)
- path = AStar(loc, target.loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id = botcard)
- if(!path)
- path = list()
- return
- if(path.len)
- step_to(src, path[1])
- path -= path[1]
- return
+ if(patrol_path[1] == loc)
+ patrol_path -= patrol_path[1]
+ var/moved = step_towards(src, patrol_path[1])
+ if(moved)
+ patrol_path -= patrol_path[1]
+
+
/mob/living/bot/cleanbot/UnarmedAttack(var/obj/effect/decal/cleanable/D, var/proximity)
if(!..())
@@ -145,7 +165,7 @@
return
cleaning = 1
- custom_emote(2, "begins to clean up the [D]")
+ custom_emote(2, "begins to clean up \the [D]")
update_icons()
var/cleantime = istype(D, /obj/effect/decal/cleanable/dirt) ? 10 : 50
if(do_after(src, cleantime))
@@ -155,6 +175,8 @@
if(!D)
return
qdel(D)
+ if(D == target)
+ target = null
cleaning = 0
update_icons()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 9e929fb88ff..58dd22d2223 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1385,7 +1385,7 @@
/mob/living/carbon/human/MouseDrop(var/atom/over_object)
var/mob/living/carbon/human/H = over_object
- if(holder_type && istype(H) && !H.lying && !issmall(H) && Adjacent(H))
+ if(H.a_intent == I_HELP && holder_type && istype(H) && !H.lying && !issmall(H) && Adjacent(H))
get_scooped(H, (usr == src))
return
return ..()
diff --git a/code/modules/mob/living/carbon/human/species/station/monkey.dm b/code/modules/mob/living/carbon/human/species/station/monkey.dm
index d9d8347550c..c4ccc620649 100644
--- a/code/modules/mob/living/carbon/human/species/station/monkey.dm
+++ b/code/modules/mob/living/carbon/human/species/station/monkey.dm
@@ -39,7 +39,7 @@
push_flags = MONKEY|SLIME|SIMPLE_ANIMAL|ALIEN
pass_flags = PASSTABLE
-
+ holder_type = /obj/item/weapon/holder
/datum/species/monkey/handle_npc(var/mob/living/carbon/human/H)
if(H.stat != CONSCIOUS)
return
diff --git a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm
index 3162c94221a..81f2025aea2 100644
--- a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm
+++ b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm
@@ -1,4 +1,7 @@
+var/global/ntnrc_uid = 0
+
/datum/ntnet_conversation/
+ var/id = null
var/title = "Untitled Conversation"
var/datum/computer_file/program/chatclient/operator // "Administrator" of this channel. Creator starts as channel's operator,
var/list/messages = list()
@@ -6,6 +9,8 @@
var/password
/datum/ntnet_conversation/New()
+ id = ntnrc_uid
+ ntnrc_uid++
if(ntnet_global)
ntnet_global.chat_channels.Add(src)
..()
diff --git a/code/modules/modular_computers/computers/item/modular_computer.dm b/code/modules/modular_computers/computers/item/modular_computer.dm
index dd53adcdc80..847fc99b52e 100644
--- a/code/modules/modular_computers/computers/item/modular_computer.dm
+++ b/code/modules/modular_computers/computers/item/modular_computer.dm
@@ -28,6 +28,7 @@
// Important hardware (must be installed for computer to work)
+ var/obj/item/weapon/computer_hardware/processor_unit/processor_unit // CPU. Without it the computer won't run. Better CPUs can run more programs at once.
var/obj/item/weapon/computer_hardware/network_card/network_card // Network Card component of this computer. Allows connection to NTNet
var/obj/item/weapon/computer_hardware/hard_drive/hard_drive // Hard Drive component of this computer. Stores programs and files.
var/obj/item/weapon/computer_hardware/battery_module/battery_module // An internal power source for this computer. Can be recharged.
@@ -36,6 +37,8 @@
var/obj/item/weapon/computer_hardware/nano_printer/nano_printer // Nano Printer component of this computer, for your everyday paperwork needs.
var/obj/item/weapon/computer_hardware/hard_drive/portable/portable_drive // Portable data storage
+ var/list/idle_threads = list() // Idle programs on background. They still receive process calls but can't be interacted with.
+
// Eject ID card from computer, if it has ID slot with card inside.
/obj/item/modular_computer/verb/eject_id()
@@ -164,7 +167,7 @@
/obj/item/modular_computer/proc/turn_on(var/mob/user)
var/issynth = issilicon(user) // Robots and AIs get different activation messages.
- if((battery_module && battery_module.battery.charge) || check_power_override()) // Battery-run and charged or non-battery but powered by APC.
+ if(processor_unit && ((battery_module && battery_module.battery.charge) || check_power_override())) // Battery-run and charged or non-battery but powered by APC.
if(issynth)
user << "You send an activation signal to \the [src], turning it on"
else
@@ -188,11 +191,22 @@
kill_program(1)
visible_message("\The [src]'s screen briefly freezes and then shows \"NETWORK ERROR - NTNet connection lost. Please retry. If problem persists contact your system administrator.\" error.")
+ for(var/datum/computer_file/program/P in idle_threads)
+ if(P.requires_ntnet && !get_ntnet_status(P.requires_ntnet_feature))
+ P.kill_program(1)
+ idle_threads.Remove(P)
+ visible_message("\The [src] screen displays an \"Process [P.filename].[P.filetype] (PID [rand(100,999)]) terminated - Network Error\" error")
+
if(active_program)
active_program.process_tick()
active_program.ntnet_status = get_ntnet_status()
active_program.computer_emagged = computer_emagged
+ for(var/datum/computer_file/program/P in idle_threads)
+ P.process_tick()
+ P.ntnet_status = get_ntnet_status()
+ P.computer_emagged = computer_emagged
+
handle_power() // Handles all computer power interaction
// Function used by NanoUI's to obtain data for header. All relevant entries begin with "PC_"
@@ -230,6 +244,17 @@
if(3)
data["PC_ntneticon"] = "sig_lan.gif"
+ if(idle_threads.len)
+ var/list/program_headers = list()
+ for(var/datum/computer_file/program/P in idle_threads)
+ if(!P.ui_header)
+ continue
+ program_headers.Add(list(list(
+ "icon" = P.ui_header
+ )))
+
+ data["PC_programheaders"] = program_headers
+
data["PC_stationtime"] = worldtime2text()
data["PC_hasheader"] = 1
data["PC_showexitprogram"] = active_program ? 1 : 0 // Hides "Exit Program" button on mainscreen
@@ -257,9 +282,13 @@
return 0
return ntnet_global.add_log(text, network_card)
-/obj/item/modular_computer/proc/shutdown_computer()
+/obj/item/modular_computer/proc/shutdown_computer(var/loud = 1)
kill_program(1)
- visible_message("\The [src] shuts down.")
+ for(var/datum/computer_file/program/P in idle_threads)
+ P.kill_program(1)
+ idle_threads.Remove(P)
+ if(loud)
+ visible_message("\The [src] shuts down.")
enabled = 0
update_icon()
return
@@ -284,6 +313,23 @@
if( href_list["PC_shutdown"] )
shutdown_computer()
return
+ if( href_list["PC_minimize"] )
+ var/mob/user = usr
+ if(!active_program || !processor_unit)
+ return
+
+ if(idle_threads.len >= processor_unit.max_idle_programs)
+ user << "\The [src] displays a \"Maximal CPU load reached. Unable to minimize another program.\" error"
+ return
+
+ idle_threads.Add(active_program)
+ active_program.running = 0 // Should close any existing UIs
+ nanomanager.close_uis(active_program.NM ? active_program.NM : active_program)
+ active_program = null
+ update_icon()
+ if(user && istype(user))
+ ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
+
if( href_list["PC_runprogram"] )
var/prog = href_list["PC_runprogram"]
var/datum/computer_file/program/P = null
@@ -299,6 +345,14 @@
if(!P.is_supported_by_hardware(hardware_flag, 1, user))
return
+ // The program is already running. Resume it.
+ if(P in idle_threads)
+ P.running = 1
+ active_program = P
+ idle_threads.Remove(P)
+ update_icon()
+ return
+
if(P.requires_ntnet && !get_ntnet_status(P.requires_ntnet_feature)) // The program requires NTNet connection, but we are not connected to NTNet.
user << "\The [src]'s screen shows \"NETWORK ERROR - Unable to connect to NTNet. Please retry. If problem persists contact your system administrator.\" warning."
return
@@ -311,9 +365,7 @@
/obj/item/modular_computer/proc/power_failure()
if(enabled) // Shut down the computer
visible_message("\The [src]'s screen flickers \"BATTERY CRITICAL\" warning as it shuts down unexpectedly.")
- kill_program(1)
- enabled = 0
- update_icon()
+ shutdown_computer(0)
// Handles power-related things, such as battery interaction, recharging, shutdown when it's discharged
/obj/item/modular_computer/proc/handle_power()
@@ -322,11 +374,10 @@
return 0
var/power_usage = screen_on ? base_active_power_usage : base_idle_power_usage
- if(network_card && network_card.enabled)
- power_usage += network_card.power_usage
- if(hard_drive && hard_drive.enabled)
- power_usage += hard_drive.power_usage
+ for(var/obj/item/weapon/computer_hardware/H in get_all_components())
+ if(H.enabled)
+ power_usage += H.power_usage
if(battery_module)
battery_module.battery.use(power_usage * CELLRATE)
@@ -440,6 +491,12 @@
return
found = 1
battery_module = H
+ else if(istype(H, /obj/item/weapon/computer_hardware/processor_unit))
+ if(processor_unit)
+ user << "This computer's processor slot is already occupied by \the [processor_unit]."
+ return
+ found = 1
+ processor_unit = H
if(found)
user << "You install \the [H] into \the [src]"
H.holder2 = src
@@ -467,11 +524,15 @@
if(battery_module == H)
battery_module = null
found = 1
+ if(processor_unit == H)
+ processor_unit = null
+ found = 1
+ critical = 1
if(found)
user << "You remove \the [H] from \the [src]."
H.forceMove(get_turf(src))
H.holder2 = null
- if(critical)
+ if(critical && enabled)
user << "\The [src]'s screen freezes for few seconds and then displays an \"HARDWARE ERROR: Critical component disconnected. Please verify component connection and reboot the device. If the problem persists contact technical support for assistance.\" warning."
kill_program(1)
enabled = 0
@@ -492,6 +553,8 @@
return card_slot
if(battery_module && (battery_module.name == name))
return battery_module
+ if(processor_unit && (processor_unit.name == name))
+ return processor_unit
return null
// Returns list of all components
@@ -509,4 +572,6 @@
all_components.Add(card_slot)
if(battery_module)
all_components.Add(battery_module)
+ if(processor_unit)
+ all_components.Add(processor_unit)
return all_components
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm
index 0e44e6ac99c..21818d06b15 100644
--- a/code/modules/modular_computers/computers/item/processor.dm
+++ b/code/modules/modular_computers/computers/item/processor.dm
@@ -78,9 +78,7 @@
/obj/item/modular_computer/processor/shutdown_computer()
if(!machinery_computer)
return
- kill_program(1)
- visible_message("\The [machinery_computer] shuts down.")
- enabled = 0
+ ..()
machinery_computer.update_icon()
return
diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm
index a423fba92e7..9dafd2405c9 100644
--- a/code/modules/modular_computers/computers/machinery/console_presets.dm
+++ b/code/modules/modular_computers/computers/machinery/console_presets.dm
@@ -8,6 +8,7 @@
. = ..()
if(!cpu)
return
+ cpu.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit(cpu)
if(_has_id_slot)
cpu.card_slot = new/obj/item/weapon/computer_hardware/card_slot(cpu)
if(_has_printer)
diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm
index 8941e1c4c10..213a45d13c6 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -84,8 +84,7 @@
if(cpu && cpu.enabled) // Shut down the computer
visible_message("\The [src]'s screen flickers [cpu.battery_module ? "\"BATTERY CRITICAL\"" : "\"EXTERNAL POWER LOSS\""] warning as it shuts down unexpectedly.")
if(cpu)
- cpu.kill_program(1)
- cpu.enabled = 0
+ cpu.shutdown_computer(0)
battery_powered = 0
update_icon()
stat |= NOPOWER
diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm
index b21a136b4e8..805f4258852 100644
--- a/code/modules/modular_computers/file_system/program.dm
+++ b/code/modules/modular_computers/file_system/program.dm
@@ -18,6 +18,8 @@
var/available_on_ntnet = 1 // Whether the program can be downloaded from NTNet. Set to 0 to disable.
var/available_on_syndinet = 0 // Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable.
var/computer_emagged = 0 // Set to 1 if computer that's running us was emagged. Computer updates this every Process() tick
+ var/ui_header = null // Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /nano/images/status_icons. Be careful not to use too large images!
+
/datum/computer_file/program/New(var/obj/item/modular_computer/comp = null)
..()
@@ -35,6 +37,11 @@
temp.usage_flags = usage_flags
return temp
+// Relays icon update to the computer.
+/datum/computer_file/program/proc/update_computer_icon()
+ if(computer)
+ computer.update_icon()
+
// Attempts to create a log in global ntnet datum. Returns 1 on success, 0 on fail.
/datum/computer_file/program/proc/generate_network_log(var/text)
if(computer)
diff --git a/code/modules/modular_computers/file_system/programs/_engineering.dm b/code/modules/modular_computers/file_system/programs/_engineering.dm
index c038efdbb0b..db00a52d90f 100644
--- a/code/modules/modular_computers/file_system/programs/_engineering.dm
+++ b/code/modules/modular_computers/file_system/programs/_engineering.dm
@@ -15,18 +15,37 @@
filename = "alarmmonitor"
filedesc = "Alarm Monitoring"
nanomodule_path = /datum/nano_module/alarm_monitor/engineering
- program_icon_state = "alarm_monitor"
+ ui_header = "alarm_green.gif"
+ program_icon_state = "alert-green"
extended_desc = "This program provides visual interface for station's alarm system."
requires_ntnet = 1
network_destination = "alarm monitoring network"
size = 5
+ var/has_alert = 0
+
+/datum/computer_file/program/alarm_monitor/process_tick()
+ ..()
+ var/datum/nano_module/alarm_monitor/NMA = NM
+ if(istype(NMA) && NMA.has_major_alarms())
+ if(!has_alert)
+ program_icon_state = "alert-red"
+ ui_header = "alarm_red.gif"
+ update_computer_icon()
+ has_alert = 1
+ else
+ if(has_alert)
+ program_icon_state = "alert-green"
+ ui_header = "alarm_green.gif"
+ update_computer_icon()
+ has_alert = 0
+ return 1
/datum/computer_file/program/atmos_control
filename = "atmoscontrol"
filedesc = "Atmosphere Control"
nanomodule_path = /datum/nano_module/atmos_control
program_icon_state = "atmos_control"
- extended_desc = "This program allows remote control of air alarms around the station"
+ extended_desc = "This program allows remote control of air alarms around the station. This program can not be run on tablet computers."
required_access = access_atmospherics
requires_ntnet = 1
network_destination = "atmospheric control system"
@@ -39,7 +58,7 @@
filedesc = "RCON Remote Control"
nanomodule_path = /datum/nano_module/rcon
program_icon_state = "generic"
- extended_desc = "This program allows remote control of power distribution systems around the station."
+ extended_desc = "This program allows remote control of power distribution systems around the station. This program can not be run on tablet computers."
required_access = access_engine
requires_ntnet = 1
network_destination = "RCON remote control system"
diff --git a/code/modules/modular_computers/file_system/programs/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/ntdownloader.dm
index 1e22a703344..a6339cb637f 100644
--- a/code/modules/modular_computers/file_system/programs/ntdownloader.dm
+++ b/code/modules/modular_computers/file_system/programs/ntdownloader.dm
@@ -10,6 +10,7 @@
requires_ntnet_feature = NTNET_SOFTWAREDOWNLOAD
available_on_ntnet = 0
nanomodule_path = /datum/nano_module/computer_ntnetdownload/
+ ui_header = "downloader_finished.gif"
var/datum/computer_file/program/downloaded_file = null
var/hacked_download = 0
var/download_completion = 0 //GQ of downloaded data.
@@ -32,6 +33,8 @@
if(!computer || !computer.hard_drive || !computer.hard_drive.try_store_file(PRG))
return 0
+ ui_header = "downloader_running.gif"
+
if(PRG in ntnet_global.available_station_software)
generate_network_log("Began downloading file [PRG.filename].[PRG.filetype] from NTNet Software Repository.")
hacked_download = 0
@@ -50,6 +53,7 @@
generate_network_log("Aborted download of file [hacked_download ? "**ENCRYPTED**" : downloaded_file.filename].[downloaded_file.filetype].")
downloaded_file = null
download_completion = 0
+ ui_header = "downloader_finished.gif"
/datum/computer_file/program/ntnetdownload/proc/complete_file_download()
if(!downloaded_file)
@@ -60,6 +64,7 @@
downloaderror = "I/O ERROR - Unable to save file. Check whether you have enough free space on your hard drive and whether your hard drive is properly connected. If the issue persists contact your system administrator for assistance."
downloaded_file = null
download_completion = 0
+ ui_header = "downloader_finished.gif"
/datum/computer_file/program/ntnetdownload/process_tick()
if(!downloaded_file)
diff --git a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
index ab9a95aac55..431b08c10b5 100644
--- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
+++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
@@ -7,8 +7,10 @@
requires_ntnet = 1
requires_ntnet_feature = NTNET_COMMUNICATION
network_destination = "NTNRC server"
+ ui_header = "ntnrc_idle.gif"
available_on_ntnet = 1
nanomodule_path = /datum/nano_module/computer_chatclient/
+ var/last_message = null // Used to generate the toolbar icon
var/username
var/datum/ntnet_conversation/channel = null
var/operator_mode = 0 // Channel operator mode
@@ -30,7 +32,7 @@
if(href_list["PRG_joinchannel"])
var/datum/ntnet_conversation/C
for(var/datum/ntnet_conversation/chan in ntnet_global.chat_channels)
- if(chan.title == href_list["PRG_joinchannel"])
+ if(chan.id == text2num(href_list["PRG_joinchannel"]))
C = chan
break
@@ -143,6 +145,20 @@
..(href, href_list)
+/datum/computer_file/program/chatclient/process_tick()
+ ..()
+ if(running)
+ ui_header = "ntnrc_idle.gif"
+ if(channel)
+ // Remember the last message. If there is no message in the channel remember null.
+ last_message = channel.messages.len ? channel.messages[channel.messages.len - 1] : null
+ else
+ last_message = null
+ return 1
+ if(channel && channel.messages && channel.messages.len)
+ ui_header = last_message == channel.messages[channel.messages.len - 1] ? "ntnrc_idle.gif" : "ntnrc_new.gif"
+ else
+ ui_header = "ntnrc_idle.gif"
/datum/computer_file/program/chatclient/kill_program(var/forced = 0)
if(channel)
@@ -188,7 +204,8 @@
for(var/datum/ntnet_conversation/conv in ntnet_global.chat_channels)
if(conv && conv.title)
all_channels.Add(list(list(
- "chan" = conv.title
+ "chan" = conv.title,
+ "id" = conv.id
)))
data["all_channels"] = all_channels
diff --git a/code/modules/modular_computers/hardware/processor_unit.dm b/code/modules/modular_computers/hardware/processor_unit.dm
new file mode 100644
index 00000000000..b013a39cd9d
--- /dev/null
+++ b/code/modules/modular_computers/hardware/processor_unit.dm
@@ -0,0 +1,36 @@
+// CPU that allows the computer to run programs.
+// Better CPUs are obtainable via research and can run more programs on background.
+
+/obj/item/weapon/computer_hardware/processor_unit
+ name = "standard processor"
+ desc = "A standard CPU used in most computers. It can run up to three programs simultaneously."
+ icon_state = "cpu_normal"
+ hardware_size = 2
+ power_usage = 50
+ critical = 1
+
+ var/max_idle_programs = 2 // 2 idle, + 1 active = 3 as said in description.
+
+/obj/item/weapon/computer_hardware/processor_unit/small
+ name = "standard microprocessor"
+ desc = "A standard miniaturised CPU used in portable devices. It can run up to two programs simultaneously."
+ icon_state = "cpu_small"
+ hardware_size = 1
+ power_usage = 25
+ max_idle_programs = 1
+
+/obj/item/weapon/computer_hardware/processor_unit/photonic
+ name = "photonic processor"
+ desc = "An advanced experimental CPU that uses photonic core instead of regular circuitry. It can run up to five programs simultaneously, but uses a lot of power."
+ icon_state = "cpu_normal_photonic"
+ hardware_size = 2
+ power_usage = 250
+ max_idle_programs = 4
+
+/obj/item/weapon/computer_hardware/processor_unit/photonic/small
+ name = "photonic microprocessor"
+ desc = "An advanced miniaturised CPU for use in portable devices. It uses photonic core instead of regular circuitry. It can run up to three programs simultaneously."
+ icon_state = "cpu_small_photonic"
+ hardware_size = 1
+ power_usage = 75
+ max_idle_programs = 2
\ No newline at end of file
diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm
index dce72afcb77..31e7fc8381d 100644
--- a/code/modules/modular_computers/laptop_vendor.dm
+++ b/code/modules/modular_computers/laptop_vendor.dm
@@ -19,6 +19,7 @@
var/total_price = 0 // Price of currently vended device.
// Device loadout
+ var/dev_cpu = 1 // 1: Default, 2: Upgraded
var/dev_battery = 1 // 1: Default, 2: Upgraded, 3: Advanced
var/dev_disk = 1 // 1: Default, 2: Upgraded, 3: Advanced
var/dev_netcard = 0 // 0: None, 1: Basic, 2: Long-Range
@@ -36,6 +37,7 @@
if(fabricated_tablet)
qdel(fabricated_tablet)
fabricated_tablet = null
+ dev_cpu = 1
dev_battery = 1
dev_disk = 1
dev_netcard = 0
@@ -50,17 +52,25 @@
if(fabricate)
fabricated_laptop = new(src)
total_price = 99
+ switch(dev_cpu)
+ if(1)
+ if(fabricate)
+ fabricated_laptop.cpu.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit/small(fabricated_laptop.cpu)
+ if(2)
+ if(fabricate)
+ fabricated_laptop.cpu.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit(fabricated_laptop.cpu)
+ total_price += 299
switch(dev_battery)
if(1) // Basic(750C)
if(fabricate)
- fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module(fabricated_tablet)
+ fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module(fabricated_laptop.cpu)
if(2) // Upgraded(1100C)
if(fabricate)
- fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/advanced(fabricated_tablet)
+ fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/advanced(fabricated_laptop.cpu)
total_price += 199
if(3) // Advanced(1500C)
if(fabricate)
- fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/super(fabricated_tablet)
+ fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/super(fabricated_laptop.cpu)
total_price += 499
switch(dev_disk)
if(1) // Basic(128GQ)
@@ -100,6 +110,7 @@
else if(devtype == 2) // Tablet, more expensive, not everyone could probably afford this.
if(fabricate)
fabricated_tablet = new(src)
+ fabricated_tablet.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit/small(fabricated_tablet)
total_price = 199
switch(dev_battery)
if(1) // Basic(300C)
@@ -169,6 +180,10 @@
state = 2 // Wait for ID swipe for payment processing
fabricate_and_recalc_price(0)
return 1
+ if(href_list["hw_cpu"])
+ dev_cpu = text2num(href_list["hw_cpu"])
+ fabricate_and_recalc_price(0)
+ return 1
if(href_list["hw_battery"])
dev_battery = text2num(href_list["hw_battery"])
fabricate_and_recalc_price(0)
@@ -213,6 +228,7 @@
data["hw_tesla"] = dev_tesla
data["hw_nanoprint"] = dev_nanoprint
data["hw_card"] = dev_card
+ data["hw_cpu"] = dev_cpu
data["totalprice"] = "[total_price]$"
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
diff --git a/code/modules/nano/modules/alarm_monitor.dm b/code/modules/nano/modules/alarm_monitor.dm
index 839b099d76f..41435c05342 100644
--- a/code/modules/nano/modules/alarm_monitor.dm
+++ b/code/modules/nano/modules/alarm_monitor.dm
@@ -41,6 +41,14 @@
return all_alarms
+// Modified version of above proc that uses slightly less resources, returns 1 if there is a major alarm, 0 otherwise.
+/datum/nano_module/alarm_monitor/proc/has_major_alarms()
+ for(var/datum/alarm_handler/AH in alarm_handlers)
+ if(AH.has_major_alarms())
+ return 1
+
+ return 0
+
/datum/nano_module/alarm_monitor/proc/minor_alarms()
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 79cddcf10cb..f2c11b3704d 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -43,6 +43,16 @@
/obj/machinery/power/apc/high
cell_type = /obj/item/weapon/cell/high
+// Construction site APC, starts turned off
+/obj/machinery/power/apc/high/inactive
+ cell_type = /obj/item/weapon/cell/high
+ lighting = 0
+ equipment = 0
+ environ = 0
+ locked = 0
+ coverlocked = 0
+ start_charge = 100
+
/obj/machinery/power/apc/super
cell_type = /obj/item/weapon/cell/super
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 54415a4990e..9d83c9898bb 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -595,7 +595,7 @@
icon = 'icons/obj/lighting.dmi'
force = 2
throwforce = 5
- w_class = 2
+ w_class = 1
var/status = 0 // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN
var/base_state
var/switchcount = 0 // number of times switched
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index ffb8fc310f4..cf55081eaa9 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -916,6 +916,45 @@ other types of metals and chemistry for reagents).
build_path = /obj/item/weapon/computer_hardware/battery_module/micro
sort_string = "VBAAU"
+/datum/design/item/modularcomponent/cpu/
+ name = "computer processor unit"
+ id = "cpu_normal"
+ req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 2)
+ build_type = IMPRINTER
+ materials = list(DEFAULT_WALL_MATERIAL = 8000)
+ chemicals = list("sacid" = 20)
+ build_path = /obj/item/weapon/computer_hardware/processor_unit
+ sort_string = "VBAAV"
+
+/datum/design/item/modularcomponent/cpu/small
+ name = "computer microprocessor unit"
+ id = "cpu_small"
+ req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+ build_type = IMPRINTER
+ materials = list(DEFAULT_WALL_MATERIAL = 4000)
+ chemicals = list("sacid" = 20)
+ build_path = /obj/item/weapon/computer_hardware/processor_unit/small
+ sort_string = "VBAAW"
+
+/datum/design/item/modularcomponent/cpu/photonic
+ name = "computer photonic processor unit"
+ id = "pcpu_normal"
+ req_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 4)
+ build_type = IMPRINTER
+ materials = list(DEFAULT_WALL_MATERIAL = 32000, glass = 8000)
+ chemicals = list("sacid" = 40)
+ build_path = /obj/item/weapon/computer_hardware/processor_unit/photonic
+ sort_string = "VBAAX"
+
+/datum/design/item/modularcomponent/cpu/photonic/small
+ name = "computer photonic microprocessor unit"
+ id = "pcpu_small"
+ req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3)
+ build_type = IMPRINTER
+ materials = list(DEFAULT_WALL_MATERIAL = 16000, glass = 4000)
+ chemicals = list("sacid" = 20)
+ build_path = /obj/item/weapon/computer_hardware/processor_unit/photonic/small
+ sort_string = "VBAAY"
/*
CIRCUITS BELOW
*/
diff --git a/code/modules/research/xenoarchaeology/tools/tools.dm b/code/modules/research/xenoarchaeology/tools/tools.dm
index e16db119c55..bc9d0ca21f5 100644
--- a/code/modules/research/xenoarchaeology/tools/tools.dm
+++ b/code/modules/research/xenoarchaeology/tools/tools.dm
@@ -30,7 +30,6 @@
icon_state = "satchel"
slot_flags = SLOT_BELT | SLOT_POCKET
w_class = 3
- storage_slots = 50
- max_storage_space = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class
+ max_storage_space = 100
max_w_class = 3
can_hold = list(/obj/item/weapon/fossil)
diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm
index aee13ede832..ed4c7f3b061 100644
--- a/code/modules/surgery/limb_reattach.dm
+++ b/code/modules/surgery/limb_reattach.dm
@@ -28,7 +28,7 @@
end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/E = tool
- user.visible_message("[user] has attached [target]'s [E.name] to the [E.amputation_point].>", \
+ user.visible_message("[user] has attached [target]'s [E.name] to the [E.amputation_point].", \
"You have attached [target]'s [E.name] to the [E.amputation_point].")
user.drop_from_inventory(E)
E.replaced(target)
diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm
index ba9334d933a..7006d4ce069 100644
--- a/code/modules/surgery/other.dm
+++ b/code/modules/surgery/other.dm
@@ -88,7 +88,7 @@
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("\blue [user] has cut away necrotic tissue in [target]'s [affected.name] with \the [tool].", \
"\blue You have cut away necrotic tissue in [target]'s [affected.name] with \the [tool].")
- affected.open = 3
+ affected.status &= ~ORGAN_DEAD
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
diff --git a/code/unit_tests/unit_test.dm b/code/unit_tests/unit_test.dm
index e8a413f07f9..dac62a552eb 100644
--- a/code/unit_tests/unit_test.dm
+++ b/code/unit_tests/unit_test.dm
@@ -67,10 +67,12 @@ datum/unit_test/proc/check_result()
proc/load_unit_test_changes()
-
+/*
+ //This takes about 60 seconds to run on Travis and is only used for the ZAS vacume check on The Asteroid.
if(config.generate_asteroid != 1)
log_unit_test("Overiding Configuration option for Asteroid Generation to ENABLED")
config.generate_asteroid = 1 // The default map requires it, the example config doesn't have this enabled.
+ */
diff --git a/code/unit_tests/zas_tests.dm b/code/unit_tests/zas_tests.dm
index e39ead59a0e..8d1d04f64ee 100644
--- a/code/unit_tests/zas_tests.dm
+++ b/code/unit_tests/zas_tests.dm
@@ -133,7 +133,7 @@ datum/unit_test/zas_area_test/incinerator
name = "ZAS: Incinerator"
area_path = /area/maintenance/incinerator
disabled = 1
- why_disabled = "Failing currently for existing bug: #11846"
+ why_disabled = "Incernator blast doors not blocking air flow. See bug #11846"
datum/unit_test/zas_area_test/virology
name = "ZAS: Virology"
@@ -151,11 +151,14 @@ datum/unit_test/zas_area_test/west_hall_mining_outpost
name = "ZAS: Mining outpost West Hallway"
area_path = /area/outpost/mining_main/west_hall
+/*
datum/unit_test/zas_area_test/mining_area
name = "ZAS: Mining Area (Vacuum)"
area_path = /area/mine/explored
expectation = UT_VACUUM
-
+ disabled = 1
+ why_disabled = "Asteroid Generation disabled"
+ */
datum/unit_test/zas_area_test/
name = "ZAS: Cargo Bay"
area_path = /area/quartermaster/storage
diff --git a/html/changelogs/RavingManiac-PR-10095.yml b/html/changelogs/RavingManiac-PR-10095.yml
new file mode 100644
index 00000000000..05c9267af93
--- /dev/null
+++ b/html/changelogs/RavingManiac-PR-10095.yml
@@ -0,0 +1,6 @@
+author: RavingManiac
+
+delete-after: True
+
+changes:
+ - rscadd: "Storage in backpacks, boxes and other containers is now capacity-based. Some containers like belts remain slot-based."
diff --git a/html/changelogs/chinsky - stuff.yml b/html/changelogs/chinsky - stuff.yml
new file mode 100644
index 00000000000..c9fa37ab16f
--- /dev/null
+++ b/html/changelogs/chinsky - stuff.yml
@@ -0,0 +1,5 @@
+author: Chinsky
+
+delete-after: True
+changes:
+ - bugfix: "Can pick up monkeys / undress resomi now properly. HELP intent for scooping, NON-HELP for undressing."
diff --git a/icons/mob/screen1.dmi b/icons/mob/screen1.dmi
index 8181013f7ee..d2220fffd14 100644
Binary files a/icons/mob/screen1.dmi and b/icons/mob/screen1.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 6631ebe296d..bd6bdba6635 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/modular_components.dmi b/icons/obj/modular_components.dmi
index e2aca17340a..3594a12c17f 100644
Binary files a/icons/obj/modular_components.dmi and b/icons/obj/modular_components.dmi differ
diff --git a/icons/obj/modular_console.dmi b/icons/obj/modular_console.dmi
index fb9f7ba9082..a157462f57a 100644
Binary files a/icons/obj/modular_console.dmi and b/icons/obj/modular_console.dmi differ
diff --git a/icons/obj/modular_laptop.dmi b/icons/obj/modular_laptop.dmi
index 587cd9de2c2..b3e0cb53648 100644
Binary files a/icons/obj/modular_laptop.dmi and b/icons/obj/modular_laptop.dmi differ
diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_tablet.dmi
index fb0e1fd9c92..1872315f49f 100644
Binary files a/icons/obj/modular_tablet.dmi and b/icons/obj/modular_tablet.dmi differ
diff --git a/icons/policetape.dmi b/icons/policetape.dmi
index 0422ecb22f3..42095beef70 100644
Binary files a/icons/policetape.dmi and b/icons/policetape.dmi differ
diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm
index 94b3eee8057..a63e8658a69 100644
--- a/maps/exodus-1.dmm
+++ b/maps/exodus-1.dmm
@@ -1743,7 +1743,7 @@
"aHA" = (/turf/simulated/floor/tiled/dark,/area/chapel/main)
"aHB" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/door/airlock/hatch{name = "Command Substation"; req_one_access = list(11,24)},/obj/machinery/door/firedoor/border_only,/turf/simulated/floor/plating,/area/maintenance/substation/command)
"aHC" = (/obj/structure/closet/coffin,/obj/machinery/door/window/eastleft{name = "Coffin Storage"; req_access = list(22)},/turf/simulated/floor/tiled/dark,/area/chapel/main)
-"aHD" = (/obj/machinery/light/small{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 4},/turf/simulated/floor/tiled/dark,/area/chapel/main)
+"aHD" = (/obj/machinery/light/small{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 4},/obj/machinery/button/remote/driver{id = "chapelgun"; pixel_x = 24; pixel_y = -24},/turf/simulated/floor/tiled/dark,/area/chapel/main)
"aHE" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8},/turf/simulated/floor/tiled/dark,/area/chapel/main)
"aHF" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'EXTERNAL AIRLOCK'"; icon_state = "space"; layer = 4; name = "EXTERNAL AIRLOCK"; pixel_x = 0; pixel_y = 32},/obj/effect/floor_decal/industrial/warning{dir = 4},/turf/simulated/floor/plating,/area/chapel/main)
"aHG" = (/obj/machinery/door/window{dir = 8; name = "Mass Driver"; req_access = list(22)},/obj/machinery/mass_driver{dir = 4; id = "chapelgun"},/obj/machinery/atmospherics/unary/vent_pump/on{dir = 8},/obj/machinery/airlock_sensor{pixel_y = 25},/obj/effect/floor_decal/industrial/warning{dir = 8},/turf/simulated/floor/plating,/area/chapel/main)
@@ -7434,7 +7434,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaT
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaTDaaaaaaaaabhObhObhObhObhObhObhObhObhObhOaaaaaaboJbnubntbnvbgrbnxboWbpmbnTaWMaVrbjpbpsblabnYbnZbmWbbZbbZbbZbbZbbZbbZboabobbocaXebdObdPbdPbdPbdPbdPbdPbdPbnybdPbdPbdPbogbdPbfmbnzblCbgabgabgabnAblpbkEaRYbnBbmGbombnCbncbnDbvGbotbnEbotaafbebbylbtAbowboxboybzibFKbebaafbedbkLboCbFMbpGbiCbiGboFaJibnHbnGaLYbXHbnLbnKbnObnNbnQaYebnSbnRbnUbnUbnWbnVbnXbnXbojbofboXbokbonbolboobnnboqbopbosbmPbnabovbmPbnabYfaVJbpjbozboGboBbplboEbppboHboKboIboMboLboOboNblOaZzboPbpxblOboQboSboRboUboTboVbnIbqUbpLbpJbnMaaaaaaaaaaacaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaaaaTDaTDaTDaTDaTDaaaaTDaTDaTDaTDaTDaaaaaaaaaaaaaaabgnbgobgpbgqbdWbpObpObpObrsbpObrCboZboYbpabgrbpbbjpbauaYPbnFbpRbqHbqGbqKbqKbqKbqMbkWbpUbkWbkWbkWbkWbpVbpWbpWbpWbbxbdPbpebpdbpcbpfbpibphbpnbpkbqhbpqbptbqkbqkcKDbpubgabgabpwbfmaMbbpzbpybpAaJubqqbpBbpDbpCborbrobpIbotaafbebbebbpKbebbrubebbpMbebbebaafbedbqzboCbqAbrvbqCbqDbpNaJibpPaQSaLYaJibpSbpQbpZbpTbpgbqLbnSbqbbnXbnXbnXbnXbnXbnXbqdbqcbqebokbqgbqfbqibnnbqmbqjbqobqnbnabovbmPbqpbYfaVJbpjbqrboEbqtbqZbqsbqvbqubqubqubqEbqxbqIbqFbrhbqJbqObqNbnIbqPbqRbqQbqSboTbqTbnIbqXbqVbrrbnMaaaaaaaaaaaaaaaaaaaaaaIuaIuaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaaaaTDaTDaTDaTDaTDaaaaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaaaaaaaaaaaabsybsibrqbeMbdybgwbgwbhtbhobrcbgrbtkbsqcrMbhvbjpbjpbjpbajbrEbrFbrGbrHbrGbrGbrGbrHbrGbajbajbdPbdPbdPbsxbdPbgNbrdbrdbrdbrdbrdbpnbrfbrLbribrkbqabrmbrlbrpbrnbrtbrtbrxbrwbrzbrybrAaHBbsbbrBbsabrDbsAbotbrIbotaafbtDbsEbsBbrjbsmbsHbsBbsIbtDaafbedbspbhFbspbedbedbedbtbaJibrKaQSaLYbXHbnLbnKbrNbrMbrObqLbrJbqbbrRbrQbrTbrSbrPbrUbqdbrVbnibrXbrZbrYbscbnnbsdbqjbosbmPbnabovbmPbnabYfaVJbpjboEboEboEbseboEbsNbsgbsjbshbslbskbsobsnbrhbssbsubstbnIbswbsCbszbsFbsDbrWbnIbsMbhwbtebnMaaaaaaaaaaaaaaaaaaaaaaaaaIuaIuaIuaIuaIuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaaaaacaaaaaaaaaaaaaaaaaaaaabsybtFbtEbuvbsLbsPbsPbsQbsPbsPbgrbsSbsRboAaYPbjpaaaaaaaaaaafaafbtnbtnbtnbtnbtnbtnbtnaaaaaabtJbhIbsTbsWbiYbsYbsXbsXbsXbsXbsXbtabsZbtdbtcbtgbtfbtzbupbfmbfmbhxbfmbfmbtCbtibthbtjbmGbtHbmGbmGbmGbmGbmGbtlbmGaafbvbbuGbtLbtmbtNbtmbtLbuNbvcaafbspbtQbtRbtSbtobtpbspbhyaJlbtqbbabtraJibtsblUbtubttbtvbucbtxbtwbFNbtybtIbtBbtMbtKbtPbtObnibokbtUbtTbsGbnnbovbtXbtZbtWbuabuabubbnabYfaXqbpjbsfboEbqtbsebuebuzbufbuhbugbujbuibulbudbrhbumbuqbunbnIburbutbusbsFboTbuubnIbuwbpFbvFbnMaaaaaaaaaaaacHOaafaafaafaafaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaaaaaaaaaaaaaaaaaaaaaaTDaTDaTDaTDaTDaaaaacaaaaaaaaaaaaaaaaaaaaabsybtFbtEbuvbsLbsPbsPbsQbsPbsPbgrbsSbsRboAaYPbjpaaaaaaaaaaafaafbtnbtnbtnbtnbtnbtnbtnaaaaaabtJbhIbsTbsWbiYbsYbsXbsXbsXbsXbsXbtabsZbtdbtcbtgbtfbtzbupbfmbfmbhxbfmbfmbtCbtibthbtjbmGbtHbmGbmGbmGbmGbmGbtlbmGaafbvbbuGbtLbtmbtNbtmbtLbuNbvcaafbspbtQbtRbtSbtobtpbspbhyaJlbtqbbabtraJibtsblUbtubttbtvbucbtxbtwbFNbtybtIbtBbtMbtKbtPbtObnibnnbtUbtTbsGbnnbovbtXbtZbtWbuabuabubbnabYfaXqbpjbsfboEbqtbsebuebuzbufbuhbugbujbuibulbudbrhbumbuqbunbnIburbutbusbsFboTbuubnIbuwbpFbvFbnMaaaaaaaaaaaacHOaafaafaafaafaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabeObyebvYbvZbpObwEbgnbgobwMbwEbgrbuybjpbwObwNbjpaaaaaaaaaaaaaaabtnbtnbtnbtnbtnbtnbtnaaaaaabxIbkwbrdbuCbuBbuEbuDbuDbuDbuHbuFbuDbuIbuKbuJbuMbuLbuPbuObfmbuQbgabuSbuTbvsbuVbuUbukbmGbmGbmGbuYbuXbvabuZbvdbvwaafbydbwnbvHbvfbvebvgbvNbwxbydaafbspbwCbvQbxnbedbvhbspbhPaJlbuWbcvbvjaJibvVbvWbvXbwDbvkbucbvmbvlbvobvnbvpbvpbvrbvqbvubvtbvvbwkbvxbwmbwkbwkbwkbwkbvybwkbwkaXKaXKaXKaXKaVJbpjboEboEboEbtYbvzbwqbvBbsjbsjbsjbskbvDbvCbwvbwwbvEbwybnIbvIbvKbvJbvLboTbvMbnIbzDbwFbnMbnMaaaaaaaaaaaaaafbvObvRbuRbvRbuRbvRbvTaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabtnbtnbtnbtnbtnbtnbtnbyAbyPbyFbvUbvUbwdbwcbwfbwebwebwebwgbrfbrdbrdbrLbwhbwjbwibwobwlbwrbwpbgabgabwsbxcbuVbuUbwzbwtbwBbwAbwGbxibxjbxkbwKbvwaafbxrbwPbtLbtmbwQbvibxobwSbxraafbspbqwbwRbwUbedbwVbspbhyaJlbwWbcvaLYaJibwYbwXbxabwZbxbbxCbxebxdbxCbxFbxGbxfbxFbwkbxhbxgbwkbwkbxmbkzbxqbxpbwTbxsbxvblubxwaXKbaybxxaXKbxybpjbvAboEbqtbxzbxAbppbxDbsjbsjbsjbskbvDbxEbrhbxHbxKbxJbnIbxLbxNbxMbxOboTbxPbnIbAVbykbnMaaaaaaaaaaaaaaaaafbxQbwHbrgbzNbwJbzObxQaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLbwLaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabtnbtnbtnbtnbtnbtnbtnbzKbxRbzKbxSbxSbxTbwcbwfbrdbrdbxUbxWbrfbxXbdPbdPbxYbgabrkbwobxZbywbyabybbybbyfbycbyhbygbyibvsbyjbvPbHJbxkbyHbyIbymbvwaafbxrbxrbxrbxrbyobxrbxrbxrbxraafbyNbyNbyNbyNbyNbyNbyNbypaJibyqbeTbeVaJibxtbyrbyrbytbyubxCbyxbyvbyWbyybyBbyzbyCbwmbyEbyDbyJbyGbyLbyKbyKbyMbyObyKbyRbyQbySbaAbwubyTbAsbyUbyXbxBbyYbyVbyZbzabppbzcboIboIbzdbskbvDbzebppbzfbzhbzgbHmbHlbHobHnbHqbHpbnIbnIbBdbnMbnMbBobBpbBpbBpbBrbCJbzjbzkbrgbwJbrgbynbuRaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/maps/exodus-3.dmm b/maps/exodus-3.dmm
index f041d5a290f..b3c38512501 100644
--- a/maps/exodus-3.dmm
+++ b/maps/exodus-3.dmm
@@ -212,7 +212,7 @@
"ed" = (/obj/machinery/door/airlock/hatch{name = "Telecoms Lounge"; req_access = list(61)},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled,/area/tcommsat/computer)
"ee" = (/obj/structure/window/reinforced{dir = 8},/obj/structure/lattice,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/turf/space,/area/turret_protected/tcomsat)
"ef" = (/turf/simulated/floor/bluegrid{name = "Mainframe Base"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/chamber)
-"eg" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/turf/simulated/floor/bluegrid{name = "Mainframe Base"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/chamber)
+"eg" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/power/apc/super/critical{name = "north bump"; pixel_y = 24},/turf/simulated/floor/bluegrid{name = "Mainframe Base"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/chamber)
"eh" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/atmospherics/pipe/simple/hidden/black{dir = 6},/turf/simulated/floor/plating,/area/tcommsat/chamber)
"ei" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/turf/simulated/floor/bluegrid{name = "Mainframe Base"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcommsat/chamber)
"ej" = (/obj/structure/window/reinforced{dir = 8},/obj/machinery/camera/network/telecom{c_tag = "Telecoms West Wing Central"; dir = 8},/turf/space,/area/turret_protected/tcomsat)
diff --git a/maps/exodus-4.dmm b/maps/exodus-4.dmm
index fbf2d3c7ce3..a16652b6190 100644
--- a/maps/exodus-4.dmm
+++ b/maps/exodus-4.dmm
@@ -70,7 +70,7 @@
"br" = (/obj/structure/cable/blue{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable/blue{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/machinery/autolathe,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/constructionsite/teleporter)
"bs" = (/obj/machinery/atmospherics/pipe/simple/hidden/blue{tag = "icon-intact (NORTHWEST)"; icon_state = "intact"; dir = 9},/turf/simulated/floor/tiled/dark,/area/constructionsite/teleporter)
"bt" = (/obj/structure/window/basic,/obj/machinery/portable_atmospherics/canister/air/airlock,/obj/machinery/atmospherics/portables_connector{tag = "icon-map_connector (EAST)"; icon_state = "map_connector"; dir = 4},/turf/simulated/floor/tiled/dark,/area/constructionsite/teleporter)
-"bu" = (/obj/structure/cable/blue,/obj/machinery/power/apc/high{dir = 2; environ = 0; equipment = 0; lighting = 0; locked = 0; name = "south bump"; pixel_y = -24},/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/turf/simulated/floor/tiled/dark,/area/constructionsite/teleporter)
+"bu" = (/obj/structure/cable/blue,/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 24},/obj/machinery/power/apc/high/inactive{dir = 2; name = "south bump"; pixel_y = -24},/turf/simulated/floor/tiled/dark,/area/constructionsite/teleporter)
"bv" = (/obj/machinery/pipedispenser/disposal,/turf/simulated/floor/tiled/dark,/area/constructionsite/teleporter)
"bw" = (/obj/machinery/pipedispenser,/turf/simulated/floor/tiled/dark,/area/constructionsite/teleporter)
"bx" = (/obj/structure/reagent_dispensers/fueltank,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled/dark,/area/constructionsite/teleporter)
@@ -87,7 +87,7 @@
"bI" = (/obj/machinery/door/airlock/highsecurity{icon_state = "door_closed"; locked = 0; name = "AI Upload"; req_access = list(16)},/turf/simulated/floor/bluegrid/airless,/area/constructionsite/ai)
"bJ" = (/obj/machinery/drone_fabricator/derelict,/turf/simulated/floor/airless,/area/constructionsite/ai)
"bK" = (/obj/machinery/computer/drone_control,/turf/simulated/floor/airless,/area/constructionsite/ai)
-"bL" = (/obj/machinery/power/apc/high{dir = 1; name = "north bump"; pixel_y = 24},/obj/structure/cable/blue{d2 = 2; icon_state = "0-2"},/turf/simulated/floor/airless,/area/constructionsite/ai)
+"bL" = (/obj/structure/cable/blue{d2 = 2; icon_state = "0-2"},/obj/machinery/power/apc/high/inactive{name = "north bump"; pixel_y = 24},/turf/simulated/floor/airless,/area/constructionsite/ai)
"bM" = (/obj/machinery/door/airlock/highsecurity{name = "Messaging Server"; req_access = list(30)},/turf/simulated/floor/airless,/area/constructionsite/hallway/fore)
"bN" = (/obj/machinery/door/airlock/highsecurity{name = "Messaging Server"; req_access = list(30)},/turf/simulated/floor/airless,/area/constructionsite/ai)
"bO" = (/obj/machinery/door/airlock/highsecurity{name = "Cyborg Station"; req_access = list(16)},/turf/simulated/floor/bluegrid/airless,/area/constructionsite/ai)
@@ -101,7 +101,7 @@
"bW" = (/obj/machinery/door/airlock/maintenance_hatch,/turf/simulated/floor/airless,/area/constructionsite/hallway/aft)
"bX" = (/obj/structure/cable/blue{d2 = 2; icon_state = "0-2"},/turf/simulated/floor/airless,/area/constructionsite/atmospherics)
"bY" = (/obj/structure/cable/blue{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/airless,/area/constructionsite/atmospherics)
-"bZ" = (/obj/machinery/power/apc/high{dir = 2; environ = 0; equipment = 0; lighting = 0; locked = 0; name = "south bump"; pixel_y = -24},/obj/structure/cable/blue,/turf/simulated/floor/airless,/area/constructionsite/atmospherics)
+"bZ" = (/obj/structure/cable/blue,/obj/machinery/power/apc/high/inactive{dir = 2; name = "south bump"; pixel_y = -24},/turf/simulated/floor/airless,/area/constructionsite/atmospherics)
"ca" = (/turf/simulated/floor/tiled/white/airless,/area/constructionsite/medical)
"cb" = (/obj/structure/grille,/turf/simulated/floor/airless,/area/constructionsite/medical)
"cc" = (/obj/machinery/sleeper,/turf/simulated/floor/tiled/white/airless,/area/constructionsite/medical)
@@ -146,7 +146,7 @@
"cP" = (/obj/structure/cable/blue,/turf/simulated/floor/airless,/area/constructionsite/engineering)
"cQ" = (/obj/machinery/power/emitter{anchored = 1; dir = 4; state = 2},/turf/simulated/floor/airless,/area/space)
"cR" = (/obj/machinery/field_generator,/turf/simulated/floor/airless,/area/space)
-"cS" = (/obj/machinery/power/emitter{anchored = 1; dir = 8; id = "EngineEmitter"; state = 2},/turf/simulated/floor/airless,/area/space)
+"cS" = (/obj/machinery/power/emitter{anchored = 1; dir = 8; state = 2},/turf/simulated/floor/airless,/area/space)
"cV" = (/turf/simulated/wall,/area/constructionsite/hallway/aft)
"cW" = (/turf/simulated/floor/airless,/area/constructionsite/hallway/aft)
"dm" = (/obj/structure/lattice,/turf/space,/area/constructionsite/hallway/aft)
diff --git a/maps/exodus-5.dmm b/maps/exodus-5.dmm
index aadec2bad53..6bc897bab06 100644
--- a/maps/exodus-5.dmm
+++ b/maps/exodus-5.dmm
@@ -1053,7 +1053,7 @@
"um" = (/obj/machinery/atmospherics/pipe/simple/visible/red{tag = "icon-intact (SOUTHWEST)"; icon_state = "intact"; dir = 10},/obj/machinery/meter,/turf/simulated/floor/tiled,/area/outpost/engineering/atmospherics)
"un" = (/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/manifold/hidden/cyan{dir = 8; icon_state = "map"; tag = "icon-manifold-f (WEST)"},/obj/effect/floor_decal/industrial/warning{dir = 9},/turf/simulated/floor,/area/outpost/engineering/hallway)
"uo" = (/obj/machinery/light/small{dir = 4},/obj/machinery/airlock_sensor{frequency = 1380; id_tag = "edock_sensor"; pixel_x = 25; pixel_y = 0},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 8; frequency = 1380; id_tag = "edock_pump"},/obj/effect/floor_decal/industrial/warning{dir = 5},/turf/simulated/floor/plating,/area/outpost/engineering/hallway)
-"up" = (/obj/machinery/power/emitter{anchored = 1; dir = 4; state = 2},/turf/simulated/floor/airless{icon_state = "asteroidplating"},/area/mine/explored)
+"up" = (/obj/machinery/power/emitter{anchored = 0; dir = 4; state = 0},/turf/simulated/floor/airless{icon_state = "asteroidplating"},/area/mine/explored)
"uq" = (/turf/simulated/wall,/area/outpost/engineering/hallway)
"ur" = (/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/grille,/obj/machinery/door/firedoor/border_only,/turf/simulated/floor/plating,/area/outpost/engineering/hallway)
"us" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/door/airlock/external{frequency = 1379; icon_state = "door_locked"; id_tag = "eoutpost_main_inner"; locked = 1; name = "Engineering Outpost"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/door/firedoor/border_only,/turf/simulated/floor,/area/outpost/engineering/hallway)
diff --git a/nano/images/status_icons/alarm_green.gif b/nano/images/status_icons/alarm_green.gif
new file mode 100644
index 00000000000..7c2570c8ce3
Binary files /dev/null and b/nano/images/status_icons/alarm_green.gif differ
diff --git a/nano/images/status_icons/alarm_red.gif b/nano/images/status_icons/alarm_red.gif
new file mode 100644
index 00000000000..327d58e4db8
Binary files /dev/null and b/nano/images/status_icons/alarm_red.gif differ
diff --git a/nano/images/status_icons/downloader_finished.gif b/nano/images/status_icons/downloader_finished.gif
new file mode 100644
index 00000000000..f01b7c42af8
Binary files /dev/null and b/nano/images/status_icons/downloader_finished.gif differ
diff --git a/nano/images/status_icons/downloader_running.gif b/nano/images/status_icons/downloader_running.gif
new file mode 100644
index 00000000000..68fb977c86d
Binary files /dev/null and b/nano/images/status_icons/downloader_running.gif differ
diff --git a/nano/images/status_icons/ntnrc_idle.gif b/nano/images/status_icons/ntnrc_idle.gif
new file mode 100644
index 00000000000..d47c01d5800
Binary files /dev/null and b/nano/images/status_icons/ntnrc_idle.gif differ
diff --git a/nano/images/status_icons/ntnrc_new.gif b/nano/images/status_icons/ntnrc_new.gif
new file mode 100644
index 00000000000..af72a8b332f
Binary files /dev/null and b/nano/images/status_icons/ntnrc_new.gif differ
diff --git a/nano/templates/computer_fabricator.tmpl b/nano/templates/computer_fabricator.tmpl
index b8afd1a1b3e..fcc5cef147c 100644
--- a/nano/templates/computer_fabricator.tmpl
+++ b/nano/templates/computer_fabricator.tmpl
@@ -29,6 +29,10 @@
| {{:helper.link('Standard', null, { "hw_netcard" : 1 }, data.hw_netcard == 1 ? 'selected' : null)}}
| {{:helper.link('Advanced', null, { "hw_netcard" : 2 }, data.hw_netcard == 2 ? 'selected' : null)}}
{{if data.devtype != 2}}
+ |
+ | Processor Unit:
+ | {{:helper.link('Standard', null, { "hw_cpu" : 1 }, data.hw_cpu == 1 ? 'selected' : null)}}
+ | {{:helper.link('Advanced', null, { "hw_cpu" : 2 }, data.hw_cpu == 2 ? 'selected' : null)}}
|
| Tesla Relay:
| {{:helper.link('None', null, { "hw_tesla" : 0 }, data.hw_tesla == 0 ? 'selected' : null)}}
@@ -50,6 +54,7 @@
Battery allows your device to operate without external utility power source. Advanced batteries increase battery life.
Hard Drive stores file on your device. Advanced drives can store more files, but use more power, shortening battery life.
Network Card allows your device to wirelessly connect to stationwide NTNet network. Basic cards are limited to on-station use, while advanced cards can operate anywhere near the station, which includes the asteroid outposts.
+ Processor Unit is critical for your device's functionality. It allows you to run programs from your hard drive. Advanced CPUs use more power, but allow you to run more programs on background at once.
Tesla Relay is an advanced wireless power relay that allows your device to connect to nearby area power controller to provide alternative power source. This component is currently unavailable on tablet computers due to size restrictions.
Nano Printer is device that allows for various paperwork manipulations, such as, scanning of documents or printing new ones. This device was certified EcoFriendlyPlus and is capable of recycling existing paper for printing purposes.
Card Reader adds a slot that allows you to manipulate RFID cards. Please note that this is not necessary to allow the device to read your identification, it is just necessary to manipulate other cards.
diff --git a/nano/templates/layout_default.tmpl b/nano/templates/layout_default.tmpl
index a5fd6f5804b..53701e30307 100644
--- a/nano/templates/layout_default.tmpl
+++ b/nano/templates/layout_default.tmpl
@@ -17,6 +17,9 @@
{{if data.PC_stationtime}}
| {{:data.PC_stationtime}}
{{/if}}
+ {{for data.PC_programheaders}}
+ |
+ {{/for}}
|
@@ -25,6 +28,7 @@
{{:helper.link('Shutdown', null, {'PC_shutdown' : 1})}}
{{if data.PC_showexitprogram}}
| {{:helper.link('Exit Program', null, {'PC_exit' : 1})}}
+ | {{:helper.link('Minimize Program', null, {'PC_minimize' : 1})}}
{{/if}}
diff --git a/nano/templates/ntnet_chat.tmpl b/nano/templates/ntnet_chat.tmpl
index 6424e073e25..592b6481770 100644
--- a/nano/templates/ntnet_chat.tmpl
+++ b/nano/templates/ntnet_chat.tmpl
@@ -60,7 +60,7 @@
Available channels:
{{for data.all_channels}}
- {{:helper.link(value.chan, null, {'PRG_joinchannel' : value.chan})}}
+ | {{:helper.link(value.chan, null, {'PRG_joinchannel' : value.id})}}
{{/for}}
|
{{/if}}
\ No newline at end of file
|