diff --git a/code/datums/outfits/jobs/civilian.dm b/code/datums/outfits/jobs/civilian.dm index ab102d2a8b..afbd7278e0 100644 --- a/code/datums/outfits/jobs/civilian.dm +++ b/code/datums/outfits/jobs/civilian.dm @@ -87,3 +87,18 @@ l_hand = /obj/item/weapon/storage/bible id_type = /obj/item/weapon/card/id/civilian/chaplain pda_type = /obj/item/device/pda/chaplain + +/decl/hierarchy/outfit/job/explorer + name = OUTFIT_JOB_NAME("Explorer") + shoes = /obj/item/clothing/shoes/boots/winter/explorer + uniform = /obj/item/clothing/under/explorer + mask = /obj/item/clothing/mask/gas/explorer + suit = /obj/item/clothing/suit/storage/hooded/explorer + gloves = /obj/item/clothing/gloves/black + l_ear = /obj/item/device/radio/headset + id_slot = slot_wear_id + id_type = /obj/item/weapon/card/id/civilian + pda_slot = slot_belt + pda_type = /obj/item/device/pda/cargo // Brown looks more rugged + r_pocket = /obj/item/device/gps/explorer + id_pda_assignment = "Explorer" diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm new file mode 100644 index 0000000000..b9c6952bc9 --- /dev/null +++ b/code/game/objects/items/devices/gps.dm @@ -0,0 +1,205 @@ +var/list/GPS_list = list() + +/obj/item/device/gps + name = "global positioning system" + desc = "Triangulates the approximate co-ordinates using a nearby satellite network. Alt+click to toggle power." + icon = 'icons/obj/gps.dmi' + icon_state = "gps-c" + w_class = ITEMSIZE_TINY + slot_flags = SLOT_BELT + origin_tech = list(TECH_MATERIALS = 2, TECH_BLUESPACE = 2, TECH_MAGNETS = 1) + matter = list(DEFAULT_WALL_MATERIAL = 500) + var/gps_tag = "COM0" + var/emped = FALSE + var/tracking = FALSE // Will not show other signals or emit its own signal if false. + var/long_range = FALSE // If true, can see farther, depending on get_map_levels(). + var/local_mode = FALSE // If true, only GPS signals of the same Z level are shown. + var/hide_signal = FALSE // If true, signal is not visible to other GPS devices. + var/can_hide_signal = FALSE // If it can toggle the above var. + +/obj/item/device/gps/initialize() + GPS_list += src + name = "global positioning system ([gps_tag])" + update_icon() + +/obj/item/device/gps/Destroy() + GPS_list -= src + return ..() + +/obj/item/device/gps/AltClick(mob/user) + toggletracking(user) + +/obj/item/device/gps/proc/toggletracking(mob/living/user) + if(!istype(user)) + return + if(emped) + to_chat(user, "It's busted!") + return + if(tracking) + to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.") + tracking = FALSE + update_icon() + else + to_chat(user, "[src] is now tracking, and visible to other GPS devices.") + tracking = TRUE + update_icon() + +/obj/item/device/gps/emp_act(severity) + if(emped) // Without a fancy callback system, this will have to do. + return + var/severity_modifier = severity ? severity : 4 // In case emp_act gets called without any arguments. + var/duration = 5 MINUTES / severity_modifier + emped = TRUE + update_icon() + + spawn(duration) + emped = FALSE + update_icon() + visible_message("\The [src] appears to be functional again.") + +/obj/item/device/gps/update_icon() + overlays.Cut() + if(emped) + overlays += image(icon, src, "emp") + else if(tracking) + overlays += image(icon, src, "working") + +/obj/item/device/gps/attack_self(mob/user) + display(user) + +/obj/item/device/gps/proc/display(mob/user) + if(!tracking) + to_chat(user, "The device is off. Alt-click it to turn it on.") + return + if(emped) + to_chat(user, "It's busted!") + return + + var/list/dat = list() + + var/turf/curr = get_turf(src) + var/area/my_area = get_area(src) + dat += "Current location: [my_area.name] ([curr.x], [curr.y], [curr.z])" + dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. \[Change Tag\] \ + \[Toggle Scan Range\] \ + [can_hide_signal ? "\[Toggle Signal Visibility\]":""]" + + var/list/signals = list() + + for(var/gps in GPS_list) + var/obj/item/device/gps/G = gps + if(G.emped || !G.tracking || G.hide_signal || G == src) // Their GPS isn't on or functional. + continue + var/turf/T = get_turf(G) + var/z_level_detection = using_map.get_map_levels(curr.z, long_range) + + if(local_mode && T.z != curr.z) // Only care about the current z-level. + continue + else if(!(T.z in z_level_detection)) // Too far away. + continue + + var/area/their_area = get_area(G) + var/area_name = their_area.name + var/coord = "[T.x], [T.y], [T.z]" + var/degrees = round(Get_Angle(curr, T)) + var/direction = uppertext(dir2text(get_dir(curr, T))) + var/distance = get_dist(curr, T) + var/local = curr.z == T.z ? TRUE : FALSE + if(!direction) + direction = "CENTER" + degrees = "N/A" + + signals += " [G.gps_tag]: [area_name] ([coord]) [local ? "Dist: [distance]m Dir: [degrees]° ([direction])":""]" + + if(signals.len) + dat += "Detected signals;" + for(var/line in signals) + dat += line + else + dat += "No other signals detected." + + var/result = dat.Join("
") + to_chat(user, result) + +/obj/item/device/gps/Topic(var/href, var/list/href_list) + if(..()) + return 1 + + if(href_list["tag"]) + var/a = input("Please enter desired tag.", name, gps_tag) as text + a = uppertext(copytext(sanitize(a), 1, 11)) + if(in_range(src, usr)) + gps_tag = a + name = "global positioning system ([gps_tag])" + to_chat(usr, "You set your GPS's tag to '[gps_tag]'.") + + if(href_list["range"]) + local_mode = !local_mode + to_chat(usr, "You set the signal receiver to [local_mode ? "'NARROW'" : "'BROAD'"].") + + if(href_list["hide"]) + if(!can_hide_signal) + return + hide_signal = !hide_signal + to_chat(usr, "You set the device to [hide_signal ? "not " : ""]broadcast a signal while scanning for other signals.") + +/obj/item/device/gps/on // Defaults to off to avoid polluting the signal list with a bunch of GPSes without owners. If you need to spawn active ones, use these. + tracking = TRUE + +/obj/item/device/gps/science + icon_state = "gps-s" + gps_tag = "SCI0" + +/obj/item/device/gps/science/on + tracking = TRUE + +/obj/item/device/gps/engineering + icon_state = "gps-e" + gps_tag = "ENG0" + +/obj/item/device/gps/engineering/on + tracking = TRUE + +/obj/item/device/gps/mining + icon_state = "gps-m" + gps_tag = "MINE0" + desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life. Alt+click to toggle power." + +/obj/item/device/gps/mining/on + tracking = TRUE + +/obj/item/device/gps/explorer + icon_state = "gps-ex" + gps_tag = "EX0" + desc = "A positioning system helpful for rescuing trapped or injured explorers, keeping one on you at all times while exploring might just save your life. Alt+click to toggle power." + +/obj/item/device/gps/explorer/on + tracking = TRUE + +/obj/item/device/gps/syndie + icon_state = "gps-syndie" + gps_tag = "NULL" + desc = "A positioning system that has extended range and can detect other GPS device signals without revealing its own. How that works is best left a mystery. Alt+click to toggle power." + origin_tech = list(TECH_MATERIALS = 2, TECH_BLUESPACE = 3, TECH_MAGNETS = 2, TECH_ILLEGAL = 2) + long_range = TRUE + hide_signal = TRUE + can_hide_signal = TRUE + +/obj/item/device/gps/robot + icon_state = "gps-b" + gps_tag = "SYNTH0" + desc = "A synthetic internal positioning system. Used as a recovery beacon for damaged synthetic assets, or a collaboration tool for mining or exploration teams. \ + Alt+click to toggle power." + tracking = TRUE // On by default. + +/obj/item/device/gps/internal // Base type for immobile/internal GPS units. + icon_state = null + gps_tag = "Eerie Signal" + desc = "Report to a coder immediately." + invisibility = INVISIBILITY_MAXIMUM + tracking = TRUE // Meant to point to a location, so it needs to be on. + anchored = TRUE + +/obj/item/device/gps/internal/base + gps_tag = "NT_BASE" + desc = "A homing signal from NanoTrasen's outpost." \ No newline at end of file diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm index 9545504f84..7b6e6184f1 100644 --- a/code/game/objects/items/weapons/material/knives.dm +++ b/code/game/objects/items/weapons/material/knives.dm @@ -92,3 +92,11 @@ desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." force_divisor = 0.25 // 15 when wielded with hardness 60 (steel) attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/weapon/material/hatchet/tacknife/survival + name = "survival knife" + desc = "A hunting grade survival knife." + icon = 'icons/obj/kitchen.dmi' + icon_state = "survivalknife" + item_state = "knife" + applies_material_colour = FALSE diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 4facc9fef7..299680b864 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -67,6 +67,15 @@ icon_state = "swat" siemens_coefficient = 0.7 +/obj/item/clothing/mask/gas/explorer + name = "explorer gas mask" + desc = "A military-grade gas mask that can be connected to an air supply." + icon_state = "explorer" + item_state_slots = list(slot_r_hand_str = "gas", slot_l_hand_str = "gas") + armor = list(melee = 10, bullet = 5, laser = 5,energy = 5, bomb = 0, bio = 50, rad = 0) + body_parts_covered = HEAD|FACE|EYES + siemens_coefficient = 0.9 + /obj/item/clothing/mask/gas/clown_hat name = "clown wig and mask" desc = "A true prankster's facial attire. A clown is incomplete without their wig and mask." diff --git a/code/modules/clothing/shoes/boots.dm b/code/modules/clothing/shoes/boots.dm index 88206f4132..40dd1c7242 100644 --- a/code/modules/clothing/shoes/boots.dm +++ b/code/modules/clothing/shoes/boots.dm @@ -96,6 +96,12 @@ desc = "A pair of winter boots. These ones are lined with brown fur, and their trim is ambrosia green" icon_state = "winterboots_hydro" +/obj/item/clothing/shoes/boots/winter/explorer + name = "explorer winter boots" + desc = "Steel-toed winter boots for mining or exploration in hazardous environments. Very good at keeping toes warm and uncrushed." + icon_state = "explorer" + armor = list(melee = 30, bullet = 10, laser = 10, energy = 15, bomb = 20, bio = 0, rad = 0) + /obj/item/clothing/shoes/boots/tactical name = "tactical boots" desc = "Tan boots with extra padding and armor." diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 006de8e99c..5819a5e065 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -770,6 +770,42 @@ obj/item/clothing/suit/storage/toggle/peacoat name = "mining winter hood" armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) +/obj/item/clothing/suit/storage/hooded/explorer + name = "explorer suit" + desc = "An armoured suit for exploring harsh environments." + icon_state = "explorer" + item_state = "explorer" + flags = THICKMATERIAL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + hooded = TRUE + hoodtype = /obj/item/clothing/head/explorer + siemens_coefficient = 0.9 + armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 50, bio = 100, rad = 50) // Inferior to sec vests in bullet/laser but better for environmental protection. + allowed = list( + /obj/item/device/flashlight, + /obj/item/weapon/gun, + /obj/item/ammo_magazine, + /obj/item/weapon/melee, + /obj/item/weapon/material/knife, + /obj/item/weapon/tank, + /obj/item/device/radio, + /obj/item/weapon/pickaxe + ) + +/obj/item/clothing/head/explorer + name = "explorer hood" + desc = "An armoured hood for exploring harsh environments." + icon_state = "explorer" + body_parts_covered = HEAD + cold_protection = HEAD + flags = THICKMATERIAL + flags_inv = HIDEEARS | BLOCKHAIR + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.9 + armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 50, bio = 100, rad = 50) + /obj/item/clothing/suit/varsity name = "black varsity jacket" desc = "A favorite of jocks everywhere from Sol to Nyx." diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index 1176b91089..b7b3b2b0b3 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -31,6 +31,7 @@ /obj/item/clothing/suit/storage/hooded/proc/RemoveHood() icon_state = "[initial(icon_state)]" suittoggled = 0 + hood.canremove = TRUE // This shouldn't matter anyways but just incase. if(ishuman(hood.loc)) var/mob/living/carbon/H = hood.loc H.unEquip(hood, 1) @@ -53,6 +54,7 @@ else H.equip_to_slot_if_possible(hood,slot_head,0,0,1) suittoggled = 1 + hood.canremove = FALSE icon_state = "[initial(icon_state)]_t" H.update_inv_wear_suit() else diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 77046dd89e..ddfb109ef6 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -812,3 +812,8 @@ desc = "A fluffy robe to keep you from showing off to the world." icon_state = "bathrobe" worn_state = "bathrobe" + +/obj/item/clothing/under/explorer + desc = "A green uniform for operating in hazardous environments." + name = "explorer's jumpsuit" + icon_state = "explorer" \ No newline at end of file diff --git a/code/modules/xenoarcheaology/tools/tools.dm b/code/modules/xenoarcheaology/tools/tools.dm index d3ab8d07d6..1d79a89449 100644 --- a/code/modules/xenoarcheaology/tools/tools.dm +++ b/code/modules/xenoarcheaology/tools/tools.dm @@ -1,17 +1,3 @@ -/obj/item/device/gps - name = "relay positioning device" - desc = "Triangulates the approximate co-ordinates using a nearby satellite network." - icon = 'icons/obj/device.dmi' - icon_state = "locator" - item_state = "locator" - origin_tech = list(TECH_MATERIAL = 2, TECH_DATA = 2, TECH_BLUESPACE = 2) - matter = list(DEFAULT_WALL_MATERIAL = 500) - w_class = ITEMSIZE_SMALL - -/obj/item/device/gps/attack_self(var/mob/user as mob) - var/turf/T = get_turf(src) - user << "\icon[src] \The [src] flashes [T.x]:[T.y]:[T.z]." - /obj/item/device/measuring_tape name = "measuring tape" desc = "A coiled metallic tape used to check dimensions and lengths." diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index 79b56e487c..e61f2d55ac 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 9947dec006..984f68f176 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index 02ffbf4e65..2d855bb804 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 0f88d8fd04..3029d8f3d6 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index 4dd885d30b..5261e549f8 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index 9cc38c1037..8abb265fde 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index fd3ff5ceca..090ba33aee 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index 557ed651ff..a87dcc3a81 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 424bc8894c..fa6ecad57a 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index 14feefefe6..eeb8183879 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/gps.dmi b/icons/obj/gps.dmi new file mode 100644 index 0000000000..b51087e9c7 Binary files /dev/null and b/icons/obj/gps.dmi differ diff --git a/icons/obj/kitchen.dmi b/icons/obj/kitchen.dmi index 4a269c4284..021d31d6e9 100644 Binary files a/icons/obj/kitchen.dmi and b/icons/obj/kitchen.dmi differ diff --git a/maps/southern_cross/southern_cross_defines.dm b/maps/southern_cross/southern_cross_defines.dm index fb70f74cbf..36063692e7 100644 --- a/maps/southern_cross/southern_cross_defines.dm +++ b/maps/southern_cross/southern_cross_defines.dm @@ -57,11 +57,16 @@ return map_levels else if (srcz == Z_LEVEL_TRANSIT) return list() // Nothing on transit! - else if (srcz >= Z_LEVEL_STATION_ONE && srcz <= Z_LEVEL_STATION_THREE) + else if (srcz >= Z_LEVEL_STATION_ONE && srcz <= Z_LEVEL_STATION_THREE) // Station can see other decks. return list( Z_LEVEL_STATION_ONE, Z_LEVEL_STATION_TWO, Z_LEVEL_STATION_THREE) + else if(srcz in list(Z_LEVEL_SURFACE, Z_LEVEL_SURFACE_MINE, Z_LEVEL_SURFACE_WILD)) // Being on the surface lets you see other surface Zs. + return list( + Z_LEVEL_SURFACE, + Z_LEVEL_SURFACE_MINE, + Z_LEVEL_SURFACE_WILD) else return ..() diff --git a/polaris.dme b/polaris.dme index f193f1328c..f8c678732d 100644 --- a/polaris.dme +++ b/polaris.dme @@ -824,6 +824,7 @@ #include "code\game\objects\items\devices\flashlight.dm" #include "code\game\objects\items\devices\floor_painter.dm" #include "code\game\objects\items\devices\geiger.dm" +#include "code\game\objects\items\devices\gps.dm" #include "code\game\objects\items\devices\hacktool.dm" #include "code\game\objects\items\devices\lightreplacer.dm" #include "code\game\objects\items\devices\locker_painter.dm"