Merge remote-tracking branch 'VOREStation/master' into upstream-merge-7919

This commit is contained in:
Unknown
2021-03-09 19:32:09 -05:00
417 changed files with 489763 additions and 92567 deletions
+1 -4
View File
@@ -40,10 +40,7 @@
return TRUE
/atom/movable/proc/has_buckled_mobs()
if(!buckled_mobs)
return FALSE
if(buckled_mobs.len)
return TRUE
return LAZYLEN(buckled_mobs)
/atom/movable/Destroy()
unbuckle_all_mobs()
+1 -1
View File
@@ -11,7 +11,7 @@
create_reagents(100)
/obj/effect/decal/cleanable/chemcoating/Initialize()
..()
. = ..()
var/turf/T = get_turf(src)
if(T)
for(var/obj/O in get_turf(src))
@@ -1,10 +1,10 @@
/obj/effect/decal/warning_stripes
icon = 'icons/effects/warning_stripes.dmi'
/obj/effect/decal/warning_stripes/New()
/obj/effect/decal/warning_stripes/Initialize()
. = ..()
var/turf/T=get_turf(src)
var/image/I=image(icon, icon_state = icon_state, dir = dir)
I.color=color
T.overlays += I
qdel(src)
return INITIALIZE_HINT_QDEL
+13 -8
View File
@@ -10,32 +10,37 @@
var/obj/item/weapon/mine/mineitemtype = /obj/item/weapon/mine
var/panel_open = 0
var/datum/wires/mines/wires = null
register_as_dangerous_object = TRUE
var/camo_net = FALSE // Will the mine 'cloak' on deployment?
// The trap item will be triggered in some manner when detonating. Default only checks for grenades.
var/obj/item/trap = null
/obj/effect/mine/New()
/obj/effect/mine/Initialize()
icon_state = "uglyminearmed"
wires = new(src)
. = ..()
if(ispath(trap))
trap = new trap(src)
/obj/effect/mine/Initialize()
..()
register_dangerous_to_step()
if(camo_net)
alpha = 50
/obj/effect/mine/Destroy()
unregister_dangerous_to_step()
if(trap)
QDEL_NULL(trap)
qdel_null(wires)
return ..()
/obj/effect/mine/Moved(atom/oldloc)
. = ..()
if(.)
var/turf/old_turf = get_turf(oldloc)
var/turf/new_turf = get_turf(src)
if(old_turf != new_turf)
old_turf.unregister_dangerous_object(src)
new_turf.register_dangerous_object(src)
/obj/effect/mine/proc/explode(var/mob/living/M)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
triggered = 1
@@ -17,7 +17,7 @@
..()
/obj/effect/temporary_effect/eruption/Initialize()
..()
. = ..()
flick("[icon_state]_create",src)
/obj/effect/temporary_effect/eruption/Destroy()
@@ -159,7 +159,6 @@
/obj/effect/spawner/newbomb/Initialize(newloc)
..(newloc)
var/obj/item/device/transfer_valve/V = new(src.loc)
var/obj/item/weapon/tank/phoron/PT = new(V)
var/obj/item/weapon/tank/oxygen/OT = new(V)
@@ -183,19 +182,14 @@
OT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE+1
OT.air_contents.update_values()
var/obj/item/device/assembly/S = new assembly_type(V)
V.attached_device = S
S.holder = V
S.toggle_secure()
V.update_icon()
qdel(src)
return INITIALIZE_HINT_QDEL
///////////////////////
@@ -26,7 +26,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
show_messages = 1
origin_tech = list(TECH_ENGINEERING = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2, TECH_DATA = 2)
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10, MAT_COPPER = 10)
var/video_range = 3
var/obj/machinery/camera/communicator/video_source // Their camera
@@ -131,7 +131,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
for(var/mob/living/voice/voice in contents)
. += "<span class='notice'>On the screen, you can see a image feed of [voice].</span>"
if(voice && voice.key)
switch(voice.stat)
if(CONSCIOUS)
+1 -1
View File
@@ -33,7 +33,7 @@
var/cell_type = /obj/item/weapon/cell/device
/obj/item/device/flash/Initialize()
..()
. = ..()
power_supply = new cell_type(src)
/obj/item/device/flash/attackby(var/obj/item/W, var/mob/user)
+237 -132
View File
@@ -9,24 +9,119 @@ var/list/GPS_list = list()
slot_flags = SLOT_BELT
origin_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 2, TECH_MAGNET = 1)
matter = list(DEFAULT_WALL_MATERIAL = 500)
var/gps_tag = "GEN0"
var/emped = FALSE
var/updating = TRUE // Lets users lock the UI so they don't have to deal with constantly shifting signals
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.
var/mob/holder
var/is_in_processing_list = FALSE
var/list/tracking_devices
var/list/showing_tracked_names
var/obj/compass_holder/compass
/obj/item/device/gps/Initialize()
. = ..()
compass = new(src)
GPS_list += src
name = "global positioning system ([gps_tag])"
update_holder()
update_icon()
/obj/item/device/gps/proc/check_visible_to_holder()
. = (holder && (holder.get_active_hand() == src || holder.get_inactive_hand() == src))
/obj/item/device/gps/proc/update_holder()
if(holder && loc != holder)
GLOB.moved_event.unregister(holder, src)
GLOB.dir_set_event.unregister(holder, src)
holder.client?.screen -= compass
holder = null
if(istype(loc, /mob))
holder = loc
GLOB.moved_event.register(holder, src, .proc/update_compass)
GLOB.dir_set_event.register(holder, src, .proc/update_compass)
if(holder && tracking)
if(!is_in_processing_list)
START_PROCESSING(SSobj, src)
is_in_processing_list = TRUE
if(holder.client)
if(check_visible_to_holder())
holder.client.screen |= compass
else
holder.client.screen -= compass
else
STOP_PROCESSING(SSobj, src)
is_in_processing_list = FALSE
if(holder?.client)
holder.client.screen -= compass
/obj/item/device/gps/pickup()
. = ..()
update_holder()
/obj/item/device/gps/equipped()
. = ..()
update_holder()
/obj/item/device/gps/dropped()
. = ..()
update_holder()
/obj/item/device/gps/process()
if(!tracking)
is_in_processing_list = FALSE
return PROCESS_KILL
update_holder()
if(holder)
update_compass(TRUE)
/obj/item/device/gps/Destroy()
STOP_PROCESSING(SSobj, src)
is_in_processing_list = FALSE
GPS_list -= src
return ..()
. = ..()
update_holder()
QDEL_NULL(compass)
/obj/item/device/gps/proc/can_track(var/obj/item/device/gps/other, var/reachable_z_levels)
if(!other.tracking || other.emped || other.hide_signal)
return FALSE
var/turf/origin = get_turf(src)
var/turf/target = get_turf(other)
if(!istype(origin) || !istype(target))
return FALSE
if(origin.z == target.z)
return TRUE
if(local_mode)
return FALSE
reachable_z_levels = reachable_z_levels || using_map.get_map_levels(origin.z, long_range)
return (target.z in reachable_z_levels)
/obj/item/device/gps/proc/update_compass(var/update_compass_icon)
compass.hide_waypoints(FALSE)
for(var/thing in tracking_devices)
var/obj/item/device/gps/gps = locate(thing)
if(!istype(gps) || QDELETED(gps))
LAZYREMOVE(tracking_devices, thing)
LAZYREMOVE(showing_tracked_names, thing)
continue
var/turf/gps_turf = get_turf(gps)
var/gps_tag = LAZYACCESS(showing_tracked_names, thing) ? gps.gps_tag : null
if(istype(gps_turf))
compass.set_waypoint("\ref[gps]", gps_tag, gps_turf.x, gps_turf.y, gps_turf.z, LAZYACCESS(tracking_devices, "\ref[gps]"))
else
compass.set_waypoint("\ref[gps]", gps_tag, 0, 0, 0, LAZYACCESS(tracking_devices, "\ref[gps]"))
if(can_track(gps))
compass.show_waypoint("\ref[gps]")
compass.rebuild_overlay_lists(update_compass_icon)
/obj/item/device/gps/AltClick(mob/user)
toggletracking(user)
@@ -37,14 +132,25 @@ var/list/GPS_list = list()
if(emped)
to_chat(user, "It's busted!")
return
toggle_tracking()
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/proc/toggle_tracking()
tracking = !tracking
if(tracking)
if(!is_in_processing_list)
is_in_processing_list = TRUE
START_PROCESSING(SSobj, src)
else
is_in_processing_list = FALSE
STOP_PROCESSING(SSobj, src)
update_compass()
update_holder()
update_icon()
/obj/item/device/gps/emp_act(severity)
if(emped) // Without a fancy callback system, this will have to do.
@@ -67,11 +173,7 @@ var/list/GPS_list = list()
add_overlay("working")
/obj/item/device/gps/attack_self(mob/user)
tgui_interact(user)
/obj/item/device/gps/examine(mob/user)
. = ..()
. += display()
display(user)
// Compiles all the data not available directly from the GPS
// Like the positions and directions to all other GPS units
@@ -90,15 +192,8 @@ var/list/GPS_list = list()
dat["z_level_detection"] = using_map.get_map_levels(curr.z, long_range)
for(var/obj/item/device/gps/G in GPS_list - src)
if(!G.tracking || G.emped || G.hide_signal)
continue
var/turf/T = get_turf(G)
if(!T)
continue
if(local_mode && curr.z != T.z)
continue
if(!(T.z in dat["z_level_detection"]))
if(!can_track(G, dat["z_level_detection"]))
continue
var/gps_data[0]
@@ -108,6 +203,7 @@ var/list/GPS_list = list()
var/area/A = get_area(G)
gps_data["area_name"] = A.get_name()
var/turf/T = get_turf(G)
gps_data["z_name"] = using_map.get_zlevel_name(T.z)
gps_data["direction"] = get_adir(curr, T)
gps_data["degrees"] = round(Get_Angle(curr,T))
@@ -122,37 +218,102 @@ var/list/GPS_list = list()
return dat
/obj/item/device/gps/proc/display()
if(!tracking)
. = "The device is off. Alt-click it to turn it on."
return
/obj/item/device/gps/proc/display(mob/user)
if(emped)
. = "It's busted!"
to_chat(user, "It's busted!")
return
var/list/dat = list()
var/list/gps_data = display_list()
dat += "Current location: [gps_data["my_area_name"]] <b>([gps_data["curr_x"]], [gps_data["curr_y"]], [gps_data["curr_z_name"]])</b>"
dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. <a href='?src=\ref[src];tag=1'>\[Change Tag\]</a> \
<a href='?src=\ref[src];range=1'>\[Toggle Scan Range\]</a> \
[can_hide_signal ? "<a href='?src=\ref[src];hide=1'>\[Toggle Signal Visibility\]</a>":""]"
if(gps_data["gps_list"].len)
dat += "Detected signals;"
for(var/gps in gps_data["gps_list"])
if(istype(gps_data["ref"], /obj/item/device/gps/internal/poi))
dat += " [gps["gps_tag"]]: [gps["area_name"]] - [gps["local"] ? "[gps["direction"]] Dist: [round(gps["distance"], 10)]m" : "in \the [gps["z_name"]]"]"
else
dat += " [gps["gps_tag"]]: [gps["area_name"]], ([gps["x"]], [gps["y"]]) - [gps["local"] ? "[gps["direction"]] Dist: [gps["distX"] ? "[abs(round(gps["distX"], 1))]m [(gps["distX"] > 0) ? "E" : "W"], " : ""][gps["distY"] ? "[abs(round(gps["distY"], 1))]m [(gps["distY"] > 0) ? "N" : "S"]" : ""]" : "in \the [gps["z_name"]]"]"
dat += "<table width = '100%'>"
if(!tracking)
dat += "<tr><td colspan = 6></td><a href='?src=\ref[src];toggle_power=1'>\[Switch On]\]</a></tr>"
else
dat += "No other signals detected."
dat += "<tr><td colspan = 6></td><a href='?src=\ref[src];toggle_power=1'>\[Switch Off]\]</a></tr>"
dat += "<tr><td colspan = 2><b>Current location</b></td><td colspan = 2>[gps_data["my_area_name"]]</td><td colspan = 2><b>([gps_data["curr_x"]], [gps_data["curr_y"]], [gps_data["curr_z_name"]])</b></td></tr>"
dat += "<tr><td colspan = 4>[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'.</td>"
dat += "<td><a href='?src=\ref[src];tag=1'>\[Change Tag\]</a><a href='?src=\ref[src];range=1'>\[Toggle Scan Range\]</a>[can_hide_signal ? "<a href='?src=\ref[src];hide=1'>\[Toggle Signal Visibility\]</a>":""]</td></tr>"
. = dat
if(gps_data["gps_list"].len)
dat += "<tr><td colspan = 6><b>Detected signals</b></td></tr>"
for(var/gps in gps_data["gps_list"])
dat += "<tr>"
var/gps_ref = "\ref[gps["ref"]]"
dat += "<td>[gps["gps_tag"]]</td><td>[gps["area_name"]]</td>"
if(istype(gps_data["ref"], /obj/item/device/gps/internal/poi))
dat += "<td>[gps["local"] ? "[gps["direction"]] Dist: [round(gps["distance"], 10)]m" : "in \the [gps["z_name"]]"]</td>"
else
dat += "<td>([gps["x"]], [gps["y"]], [gps["z_name"]])</td>"
if(gps["local"])
dat += "<td>[gps["distance"]]m</td>"
dat += "<td>[gps["degrees"]]° ([gps["direction"]])</td>"
else
dat += "<td colspan = 2>Non-local signal.</td>"
if(LAZYACCESS(tracking_devices, gps_ref))
dat += "<td><a href='?src=\ref[src];stop_track=[gps_ref]'>\[Stop Tracking\]</a> <a href='?src=\ref[src];track_color=[gps_ref]'>\[Colour [color_square(hex = LAZYACCESS(tracking_devices, gps_ref))]\]</a> <a href='?src=\ref[src];track_label=[gps_ref]'>Show/Hide Label</a></td>"
else
dat += "<td><a href='?src=\ref[src];start_track=[gps_ref]'>\[Start Tracking\]</a></td>"
dat += "</tr>"
else
dat += "<tr><td colspan = 5>No other signals detected.</td></tr>"
dat += "</table>"
var/datum/browser/popup = new(user, "gps_\ref[src]", "Global Positioning System", 700, 1000)
popup.set_content(dat.Join(null))
popup.open()
/obj/item/device/gps/Topic(var/href, var/list/href_list)
if(..())
return 1
return TRUE
if(href_list["toggle_power"])
toggle_tracking()
. = TRUE
if(href_list["track_label"])
var/gps_ref = href_list["track_label"]
var/obj/item/device/gps/gps = locate(gps_ref)
if(istype(gps) && !QDELETED(gps) && !LAZYACCESS(showing_tracked_names, gps_ref))
LAZYSET(showing_tracked_names, gps_ref, TRUE)
else
LAZYREMOVE(showing_tracked_names, gps_ref)
to_chat(usr, SPAN_NOTICE("\The [src] is [LAZYACCESS(showing_tracked_names, gps_ref) ? "now showing" : "no longer showing"] labels for [gps.gps_tag]."))
if(href_list["stop_track"])
var/gps_ref = href_list["stop_track"]
var/obj/item/device/gps/gps = locate(gps_ref)
compass.clear_waypoint(gps_ref)
LAZYREMOVE(tracking_devices, gps_ref)
LAZYREMOVE(showing_tracked_names, gps_ref)
if(istype(gps) && !QDELETED(gps))
to_chat(usr, SPAN_NOTICE("\The [src] is no longer tracking [gps.gps_tag]."))
update_compass()
. = TRUE
if(href_list["start_track"])
var/gps_ref = href_list["start_track"]
var/obj/item/device/gps/gps = locate(gps_ref)
if(istype(gps) && !QDELETED(gps))
LAZYSET(tracking_devices, gps_ref, "#00ffff")
LAZYSET(showing_tracked_names, gps_ref, TRUE)
to_chat(usr, SPAN_NOTICE("\The [src] is now tracking [gps.gps_tag]."))
update_compass()
. = TRUE
if(href_list["track_color"])
var/obj/item/device/gps/gps = locate(href_list["track_color"])
if(istype(gps) && !QDELETED(gps))
var/new_colour = input("Enter a new tracking color.", "GPS Waypoint Color") as color|null
if(new_colour && istype(gps) && !QDELETED(gps) && holder == usr && !usr.incapacitated())
to_chat(usr, SPAN_NOTICE("You adjust the colour \the [src] is using to highlight [gps.gps_tag]."))
LAZYSET(tracking_devices, href_list["track_color"], new_colour)
update_compass()
. = TRUE
if(href_list["tag"])
var/a = input("Please enter desired tag.", name, gps_tag) as text
@@ -161,95 +322,22 @@ var/list/GPS_list = list()
gps_tag = a
name = "global positioning system ([gps_tag])"
to_chat(usr, "You set your GPS's tag to '[gps_tag]'.")
. = TRUE
if(href_list["range"])
local_mode = !local_mode
to_chat(usr, "You set the signal receiver to [local_mode ? "'NARROW'" : "'BROAD'"].")
. = TRUE
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.")
. = TRUE
/obj/item/device/gps/tgui_interact(mob/user, datum/tgui/ui)
if(emped)
to_chat(user, "<span class='hear'>[src] fizzles weakly.</span>")
return
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Gps", name)
ui.open()
ui.set_autoupdate(updating)
/obj/item/device/gps/tgui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gps_tag
data["updating"] = updating
data["globalmode"] = !local_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(src)
data["currentArea"] = "[get_area_name(curr, TRUE)]"
data["currentCoords"] = list(curr.x, curr.y, curr.z)
data["currentCoordsText"] = "[curr.x], [curr.y], [using_map.get_zlevel_name(curr.z)]"
data["zLevelDetection"] = using_map.get_map_levels(curr.z, long_range)
var/list/signals = list()
data["signals"] = list()
for(var/obj/item/device/gps/G in GPS_list - src)
if(!G.tracking || G.emped || G.hide_signal)
continue
var/turf/T = get_turf(G)
if(!T)
continue
if(local_mode && curr.z != T.z)
continue
if(!(T.z in data["zLevelDetection"]))
continue
var/list/signal = list()
signal["entrytag"] = G.gps_tag //Name or 'tag' of the GPS
signal["coords"] = list(T.x, T.y, T.z)
signal["coordsText"] = "[T.x], [T.y], [using_map.get_zlevel_name(T.z)]"
if(T.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, T), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, T)) //0-360 degree directional bearing, for more precision.
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/obj/item/device/gps/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("rename")
var/a = stripped_input(usr, "Please enter desired tag.", name, gps_tag, 20)
if(!a)
return
gps_tag = a
name = "global positioning system ([gps_tag])"
. = TRUE
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
local_mode = !local_mode
. = TRUE
if(. && loc == usr)
display(usr)
/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
@@ -373,26 +461,43 @@ var/list/GPS_list = list()
can_hide_signal = TRUE
/obj/item/device/gps/syndie/display(mob/user)
if(!tracking)
. = "The device is off. Alt-click it to turn it on."
return
if(emped)
. = "It's busted!"
to_chat(user, "It's busted!")
return
var/list/dat = list()
var/list/gps_data = display_list()
dat += "Current location: [gps_data["my_area_name"]] <b>([gps_data["curr_x"]], [gps_data["curr_y"]], [gps_data["curr_z_name"]])</b>"
dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. <a href='?src=\ref[src];tag=1'>\[Change Tag\]</a> \
<a href='?src=\ref[src];range=1'>\[Toggle Scan Range\]</a> \
[can_hide_signal ? "<a href='?src=\ref[src];hide=1'>\[Toggle Signal Visibility\]</a>":""]"
if(gps_data["gps_list"].len)
dat += "Detected signals;"
for(var/gps in gps_data["gps_list"])
dat += " [gps["gps_tag"]]: [gps["area_name"]] ([gps["x"]], [gps["y"]], [gps["z_name"]]) [gps["local"] ? "Dist: [gps["distance"]]m Dir: [gps["degrees"]]° ([gps["direction"]])" :""]"
dat += "<table width = '100%'>"
if(!tracking)
dat += "<tr><td colspan = 6></td><a href='?src=\ref[src];toggle_power=1'>\[Switch On]\]</a></tr>"
else
dat += "No other signals detected."
dat += "<tr><td colspan = 6></td><a href='?src=\ref[src];toggle_power=1'>\[Switch Off]\]</a></tr>"
dat += "<tr><td colspan = 2><b>Current location</b></td><td colspan = 2>[gps_data["my_area_name"]]</td><td colspan = 2><b>([gps_data["curr_x"]], [gps_data["curr_y"]], [gps_data["curr_z_name"]])</b></td></tr>"
dat += "<tr><td colspan = 4>[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'.</td>"
dat += "<td><a href='?src=\ref[src];tag=1'>\[Change Tag\]</a><a href='?src=\ref[src];range=1'>\[Toggle Scan Range\]</a>[can_hide_signal ? "<a href='?src=\ref[src];hide=1'>\[Toggle Signal Visibility\]</a>":""]</td></tr>"
. = dat
if(gps_data["gps_list"].len)
dat += "<tr><td colspan = 6><b>Detected signals</b></td></tr>"
for(var/gps in gps_data["gps_list"])
dat += "<tr>"
var/gps_ref = "\ref[gps["ref"]]"
dat += "<td>[gps["gps_tag"]]</td><td>[gps["area_name"]] ([gps["x"]], [gps["y"]], [gps["z_name"]])</td>"
if(gps["local"])
dat += "<td>[gps["distance"]]m</td>"
dat += "<td>[gps["degrees"]]° ([gps["direction"]])</td>"
else
dat += "<td colspan = 2>Non-local signal.</td>"
if(LAZYACCESS(tracking_devices, gps_ref))
dat += "<td><a href='?src=\ref[src];stop_track=[gps_ref]'>\[Stop Tracking\]</a> <a href='?src=\ref[src];track_color=[gps_ref]'>\[Colour [color_square(hex = LAZYACCESS(tracking_devices, gps_ref))]\]</a> <a href='?src=\ref[src];track_label=[gps_ref]'>Show/Hide Label</a></td>"
else
dat += "<td><a href='?src=\ref[src];start_track=[gps_ref]'>\[Start Tracking\]</a></td>"
dat += "</tr>"
else
dat += "<tr><td colspan = 6>No other signals detected.</td></tr>"
dat += "</table>"
var/datum/browser/popup = new(user, "gps_\ref[src]", "Global Positioning System", 700, 1000)
popup.set_content(dat.Join(null))
popup.open()
@@ -6,7 +6,7 @@
item_state = "pen"
var/pointer_icon_state
slot_flags = SLOT_BELT
matter = list("glass" = 500,"metal" = 500)
matter = list("glass" = 500,"metal" = 500, MAT_COPPER = 10)
w_class = 2 //Increased to 2, because diodes are w_class 2. Conservation of matter.
origin_tech = list(TECH_MAGNET = 2, TECH_COMBAT = 1)
var/turf/pointer_loc
+1 -1
View File
@@ -17,7 +17,7 @@
drop_sound = 'sound/items/drop/multitool.ogg'
pickup_sound = 'sound/items/pickup/multitool.ogg'
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20, MAT_COPPER = 10)
var/mode_index = 1
var/toolmode = MULTITOOL_MODE_STANDARD
@@ -11,7 +11,7 @@
slot_flags = SLOT_BACK
w_class = ITEMSIZE_HUGE
matter = list(DEFAULT_WALL_MATERIAL = 10000,"glass" = 2500)
matter = list(DEFAULT_WALL_MATERIAL = 10000,"glass" = 2500, MAT_COPPER = 1550)
var/code = 2
@@ -84,7 +84,6 @@
desc = "A headset used by pilots, has access to the explorer channel."
icon_state = "pilot_headset"
adhoc_fallback = TRUE
ks2type = /obj/item/device/encryptionkey/pilot
/obj/item/device/radio/headset/pilot/alt
name = "pilot's bowman headset"
@@ -120,7 +119,7 @@
desc = "A headset used by volunteers to expedition teams, has access to the exploration channel."
icon_state = "pilot_headset"
adhoc_fallback = TRUE
ks2type = /obj/item/device/encryptionkey/pilot
ks2type = /obj/item/device/encryptionkey/explorer
/obj/item/device/radio/headset/talon
name = "talon headset"
@@ -61,7 +61,7 @@ var/global/list/default_medbay_channels = list(
var/bs_tx_preload_id
var/bs_rx_preload_id
matter = list("glass" = 25,DEFAULT_WALL_MATERIAL = 75)
matter = list("glass" = 25, DEFAULT_WALL_MATERIAL = 75, MAT_COPPER = 15)
var/const/FREQ_LISTENING = 1
var/list/internal_channels
+1 -1
View File
@@ -21,7 +21,7 @@ HALOGEN COUNTER - Radcount on mobs
w_class = ITEMSIZE_SMALL
throw_speed = 5
throw_range = 10
matter = list(DEFAULT_WALL_MATERIAL = 200)
matter = list(DEFAULT_WALL_MATERIAL = 200, MAT_COPPER = 25)
origin_tech = list(TECH_MAGNET = 1, TECH_BIO = 1)
var/mode = 1;
var/advscan = 0
@@ -7,15 +7,12 @@
var/obj/item/stack/type_to_spawn = null
/obj/fiftyspawner/Initialize()
..() //We're not returning . because we're going to ask to be deleted.
..()
var/turf/T = get_turf(src)
var/obj/item/stack/M = new type_to_spawn(T)
var/obj/structure/closet/C = locate() in T
var/obj/item/stack/M = new type_to_spawn(C || T)
M.amount = M.max_amount //some stuff spawns with 60, we're still calling it fifty
M.update_icon() // Some stacks have different sprites depending on how full they are.
var/obj/structure/closet/C = locate() in T
if(C)
C.contents += M
return INITIALIZE_HINT_QDEL //Bye!
/obj/fiftyspawner/rods
+4 -2
View File
@@ -14,6 +14,8 @@
max_amount = 60
attack_verb = list("hit", "bludgeoned", "whacked")
color = "#666666"
/obj/item/stack/rods/cyborg
name = "metal rod synthesizer"
desc = "A device that makes metal rods."
@@ -24,8 +26,8 @@
stacktype = /obj/item/stack/rods
no_variants = TRUE
/obj/item/stack/rods/New()
..()
/obj/item/stack/rods/Initialize()
. = ..()
recipes = rods_recipes
update_icon()
+6 -14
View File
@@ -32,19 +32,15 @@
bag_material = MAT_SYNCLOTH
/obj/item/stack/sandbags/New(var/newloc, var/amt, var/bag_mat)
..()
/obj/item/stack/sandbags/Initialize(var/ml, var/amt, var/bag_mat)
. = ..(ml, amt)
recipes = sandbag_recipes
update_icon()
if(bag_mat)
bag_material = bag_mat
var/datum/material/M = get_material_by_name("[bag_material]")
if(!M)
qdel(src)
return
return INITIALIZE_HINT_QDEL
color = M.icon_colour
/obj/item/stack/sandbags/update_icon()
@@ -136,17 +132,13 @@ var/global/list/datum/stack_recipe/sandbag_recipes = list( \
var/bag_material = "cloth"
/obj/item/stack/emptysandbag/New(var/newloc, var/amt, var/bag_mat)
..(newloc, amt)
/obj/item/stack/emptysandbag/Initialize(var/ml, var/amt, var/bag_mat)
. = ..(ml, amt)
if(bag_mat)
bag_material = bag_mat
var/datum/material/M = get_material_by_name("[bag_material]")
if(!M)
qdel(src)
return
return INITIALIZE_HINT_QDEL
color = M.icon_colour
/obj/item/stack/emptysandbag/attack_self(var/mob/user)
+41 -6
View File
@@ -29,14 +29,13 @@
var/pass_color = FALSE // Will the item pass its own color var to the created item? Dyed cloth, wood, etc.
var/strict_color_stacking = FALSE // Will the stack merge with other stacks that are different colors? (Dyed cloth, wood, etc)
/obj/item/stack/New(var/loc, var/amount=null)
..()
if (!stacktype)
/obj/item/stack/Initialize(var/ml, var/amount)
. = ..()
if(!stacktype)
stacktype = type
if (amount)
if(amount)
src.amount = amount
update_icon()
return
/obj/item/stack/Destroy()
if(uses_charge)
@@ -170,8 +169,37 @@
var/atom/O
if(recipe.use_material)
O = new recipe.result_type(user.loc, recipe.use_material)
if(istype(O, /obj))
var/obj/Ob = O
if(LAZYLEN(Ob.matter)) // Law of equivalent exchange.
Ob.matter.Cut()
else
Ob.matter = list()
var/mattermult = istype(Ob, /obj/item) ? min(2000, 400 * Ob.w_class) : 2000
Ob.matter[recipe.use_material] = mattermult / produced * required
else
O = new recipe.result_type(user.loc)
if(recipe.matter_material)
if(istype(O, /obj))
var/obj/Ob = O
if(LAZYLEN(Ob.matter)) // Law of equivalent exchange.
Ob.matter.Cut()
else
Ob.matter = list()
var/mattermult = istype(Ob, /obj/item) ? min(2000, 400 * Ob.w_class) : 2000
Ob.matter[recipe.use_material] = mattermult / produced * required
O.set_dir(user.dir)
O.add_fingerprint(user)
@@ -379,8 +407,9 @@
var/on_floor = 0
var/use_material
var/pass_color
var/matter_material // Material type used for recycling. Default, uses use_material. For non-material-based objects however, matter_material is needed.
/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, supplied_material = null, pass_stack_color)
/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, supplied_material = null, pass_stack_color, recycle_material = null)
src.title = title
src.result_type = result_type
src.req_amount = req_amount
@@ -392,6 +421,12 @@
src.use_material = supplied_material
src.pass_color = pass_stack_color
if(!recycle_material && src.use_material)
src.matter_material = src.use_material
else if(recycle_material)
src.matter_material = recycle_material
/*
* Recipe list datum
*/
+1 -1
View File
@@ -7,7 +7,7 @@
w_class = ITEMSIZE_TINY
max_amount = 30
/obj/item/stack/arcadeticket/New(loc, amount = null)
/obj/item/stack/arcadeticket/Initialize()
. = ..()
update_icon()
@@ -20,8 +20,8 @@
drop_sound = 'sound/items/drop/axe.ogg'
pickup_sound = 'sound/items/pickup/axe.ogg'
/obj/item/stack/tile/New()
..()
/obj/item/stack/tile/Initialize()
. = ..()
randpixel_xy()
/*
@@ -23,6 +23,8 @@
drop_sound = 'sound/items/drop/device.ogg'
pickup_sound = 'sound/items/pickup/device.ogg'
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
//Called when the circuitboard is used to contruct a new machine.
/obj/item/weapon/circuitboard/proc/construct(var/obj/machinery/M)
if(istype(M, build_path))
@@ -10,37 +10,37 @@
name = T_BOARD("guestpass console")
build_path = /obj/machinery/computer/guestpass
board_type = new /datum/frame/frame_types/guest_pass_console
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/status_display
name = T_BOARD("status display")
build_path = /obj/machinery/status_display
board_type = new /datum/frame/frame_types/display
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/ai_status_display
name = T_BOARD("ai status display")
build_path = /obj/machinery/ai_status_display
board_type = new /datum/frame/frame_types/display
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/newscaster
name = T_BOARD("newscaster")
build_path = /obj/machinery/newscaster
board_type = new /datum/frame/frame_types/newscaster
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/atm
name = T_BOARD("atm")
build_path = /obj/machinery/atm
board_type = new /datum/frame/frame_types/atm
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/request
name = T_BOARD("request console")
build_path = /obj/machinery/requests_console
board_type = new /datum/frame/frame_types/supply_request_console
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
//Alarm
@@ -48,25 +48,25 @@
name = T_BOARD("fire alarm")
build_path = /obj/machinery/firealarm
board_type = new /datum/frame/frame_types/fire_alarm
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/airalarm
name = T_BOARD("air alarm")
build_path = /obj/machinery/alarm
board_type = new /datum/frame/frame_types/air_alarm
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/intercom
name = T_BOARD("intercom")
build_path = /obj/item/device/radio/intercom
board_type = new /datum/frame/frame_types/intercom
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/keycard_auth
name = T_BOARD("keycard authenticator")
build_path = /obj/machinery/keycard_auth
board_type = new /datum/frame/frame_types/keycard_authenticator
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
//Computer
@@ -74,7 +74,7 @@
name = T_BOARD("holopad")
build_path = /obj/machinery/hologram/holopad
board_type = new /datum/frame/frame_types/holopad
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/scanner_console
name = T_BOARD("body scanner console")
@@ -94,7 +94,7 @@
name = T_BOARD("photocopier")
build_path = /obj/machinery/photocopier
board_type = new /datum/frame/frame_types/photocopier
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
req_components = list(
/obj/item/weapon/stock_parts/scanning_module = 1,
/obj/item/weapon/stock_parts/motor = 1,
@@ -105,7 +105,7 @@
name = T_BOARD("fax")
build_path = /obj/machinery/photocopier/faxmachine
board_type = new /datum/frame/frame_types/fax
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
req_components = list(
/obj/item/weapon/stock_parts/scanning_module = 1,
/obj/item/weapon/stock_parts/motor = 1,
@@ -116,6 +116,7 @@
name = T_BOARD("conveyor")
build_path = /obj/machinery/conveyor
board_type = new /datum/frame/frame_types/conveyor
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
req_components = list(
/obj/item/weapon/stock_parts/gear = 2,
/obj/item/weapon/stock_parts/motor = 2,
@@ -125,6 +126,7 @@
name = T_BOARD("recharger")
build_path = /obj/machinery/recharger
board_type = new /datum/frame/frame_types/recharger
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
req_components = list(
/obj/item/weapon/stock_parts/capacitor = 1,
/obj/item/stack/cable_coil = 5)
@@ -138,6 +140,7 @@
name = T_BOARD("heavy-duty cell charger")
build_path = /obj/machinery/cell_charger
board_type = new /datum/frame/frame_types/cell_charger
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
req_components = list(
/obj/item/weapon/stock_parts/capacitor = 1,
/obj/item/stack/cable_coil = 5)
@@ -146,7 +149,7 @@
name = T_BOARD("washing machine")
build_path = /obj/machinery/washing_machine
board_type = new /datum/frame/frame_types/washing_machine
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
req_components = list(
/obj/item/weapon/stock_parts/motor = 1,
/obj/item/weapon/stock_parts/gear = 2)
@@ -155,6 +158,7 @@
name = T_BOARD("reagent grinder")
build_path = /obj/machinery/reagentgrinder
board_type = new /datum/frame/frame_types/grinder
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
req_components = list(
/obj/item/weapon/stock_parts/motor = 1,
/obj/item/weapon/stock_parts/gear = 1,
@@ -163,6 +167,7 @@
/obj/item/weapon/circuitboard/distiller
build_path = /obj/machinery/portable_atmospherics/powered/reagent_distillery
board_type = new /datum/frame/frame_types/reagent_distillery
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
req_components = list(
/obj/item/weapon/stock_parts/capacitor = 1,
/obj/item/weapon/stock_parts/micro_laser = 1,
@@ -173,6 +178,7 @@
name = T_BOARD("teleporter hub")
build_path = /obj/machinery/teleport/hub
board_type = "teleporter_hub"
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_GOLD = 100)
// origin_tech = list(TECH_DATA = 2, TECH_BLUESPACE = 4)
req_components = list(
/obj/item/weapon/stock_parts/scanning_module = 4,
@@ -183,6 +189,7 @@
name = T_BOARD("teleporter station")
build_path = /obj/machinery/teleport/station
board_type = "teleporter_station"
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_GOLD = 100)
// origin_tech = list(TECH_DATA = 2, TECH_BLUESPACE = 3)
req_components = list(
/obj/item/weapon/stock_parts/console_screen = 1,
@@ -194,6 +201,7 @@
build_path = /obj/machinery/bodyscanner
board_type = new /datum/frame/frame_types/medical_pod
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2)
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
req_components = list(
/obj/item/weapon/stock_parts/scanning_module = 3,
/obj/item/stack/material/glass/reinforced = 2)
@@ -202,6 +210,7 @@
name = T_BOARD("sleeper")
build_path = /obj/machinery/sleeper
board_type = new /datum/frame/frame_types/medical_pod
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2)
req_components = list(
/obj/item/weapon/stock_parts/manipulator = 1,
@@ -214,6 +223,7 @@
name = T_BOARD("VR sleeper")
build_path = /obj/machinery/vr_sleeper
board_type = new /datum/frame/frame_types/medical_pod
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_GOLD = 100)
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2)
req_components = list(
/obj/item/weapon/stock_parts/scanning_module = 1,
@@ -223,6 +233,7 @@
name = T_BOARD("dna analyzer")
build_path = /obj/machinery/dnaforensics
board_type = new /datum/frame/frame_types/dna_analyzer
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_GOLD = 100)
origin_tech = list(TECH_MAGNET = 4, TECH_BIO = 2, TECH_DATA = 2)
req_components = list(
/obj/item/weapon/stock_parts/scanning_module = 2,
@@ -233,6 +244,7 @@
name = T_BOARD("mass driver")
build_path = /obj/machinery/mass_driver
board_type = new /datum/frame/frame_types/mass_driver
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_GOLD = 100)
req_components = list(
/obj/item/weapon/stock_parts/gear = 2,
/obj/item/weapon/stock_parts/motor = 2,
@@ -8,6 +8,7 @@
icon = 'icons/obj/module.dmi'
icon_state = "std_mod"
board_type = "other"
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, MAT_COPPER = 100)
/obj/item/weapon/circuitboard/mecha/ripley
origin_tech = list(TECH_DATA = 3)
@@ -299,3 +299,13 @@
src.imp = new /obj/item/weapon/implant/organ/limbaugment/wrist/blade( src )
..()
return
/obj/item/weapon/implantcase/restrainingbolt
name = "glass case - 'Restraining Bolt'"
desc = "A case containing a restraining bolt."
icon_state = "implantcase-b"
/obj/item/weapon/implantcase/restrainingbolt/New()
src.imp = new /obj/item/weapon/implant/restrainingbolt( src )
..()
return
@@ -4,18 +4,6 @@
icon = 'icons/obj/device.dmi'
icon_state = "implant"
initialize_loc = BP_HEAD
var/roundstart = TRUE
/obj/item/weapon/implant/dud/torso
name = "unknown implant"
desc = "A small device with small connector wires."
icon = 'icons/obj/device.dmi'
icon_state = "implant"
initialize_loc = BP_TORSO
/obj/item/weapon/implant/dud/old
name = "old implant"
desc = "A small device with small connector wires."
icon = 'icons/obj/device.dmi'
icon_state = "implant"
roundstart = FALSE
@@ -150,3 +150,12 @@
S.remove_from_storage(A)
A.loc.contents.Remove(A)
update()
/obj/item/weapon/implanter/restrainingbolt
name = "implanter (bolt)"
/obj/item/weapon/implanter/restrainingbolt/New()
src.imp = new /obj/item/weapon/implant/restrainingbolt( src )
..()
update()
return
@@ -0,0 +1,5 @@
/obj/item/weapon/implant/restrainingbolt
name = "\improper restraining bolt"
icon = 'icons/obj/device.dmi'
icon_state = "implant"
@@ -31,7 +31,9 @@ Protectiveness | Armor %
var/applies_material_color = TRUE
var/unbreakable = FALSE
var/default_material = null // Set this to something else if you want material attributes on init.
var/material_armor_modifer = 1 // Adjust if you want seperate types of armor made from the same material to have different protectiveness (e.g. makeshift vs real armor)
var/material_armor_modifier = 1 // Adjust if you want seperate types of armor made from the same material to have different protectiveness (e.g. makeshift vs real armor)
var/material_slowdown_modifier = 0
var/material_slowdown_multiplier = 1
/obj/item/clothing/New(var/newloc, var/material_key)
..(newloc)
@@ -138,7 +140,7 @@ Protectiveness | Armor %
return ..()
var/reflectchance = (40 * material.reflectivity) - round(damage/3)
reflectchance *= material_armor_modifer
reflectchance *= material_armor_modifier
if(!(def_zone in list(BP_TORSO, BP_GROIN)))
reflectchance /= 2
if(P.starting && prob(reflectchance))
@@ -166,17 +168,17 @@ Protectiveness | Armor %
if(material)
var/melee_armor = 0, bullet_armor = 0, laser_armor = 0, energy_armor = 0, bomb_armor = 0
melee_armor = calculate_material_armor(material.protectiveness * material_armor_modifer)
melee_armor = calculate_material_armor(material.protectiveness * material_armor_modifier)
bullet_armor = calculate_material_armor((material.protectiveness * (material.hardness / 100) * material_armor_modifer) * 0.7)
bullet_armor = calculate_material_armor((material.protectiveness * (material.hardness / 100) * material_armor_modifier) * 0.7)
laser_armor = calculate_material_armor((material.protectiveness * (material.reflectivity + 1) * material_armor_modifer) * 0.7)
laser_armor = calculate_material_armor((material.protectiveness * (material.reflectivity + 1) * material_armor_modifier) * 0.7)
if(material.opacity != 1)
laser_armor *= max(material.opacity - 0.3, 0) // Glass and such has an opacity of 0.3, but lasers should go through glass armor entirely.
energy_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.4)
energy_armor = calculate_material_armor((material.protectiveness * material_armor_modifier) * 0.4)
bomb_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.5)
bomb_armor = calculate_material_armor((material.protectiveness * material_armor_modifier) * 0.5)
// Makes sure the numbers stay capped.
for(var/number in list(melee_armor, bullet_armor, laser_armor, energy_armor, bomb_armor))
@@ -190,7 +192,12 @@ Protectiveness | Armor %
if(!isnull(material.conductivity))
siemens_coefficient = between(0, material.conductivity / 10, 10)
slowdown = between(0, round(material.weight / 10, 0.1), 6)
var/slowdownModified = between(0, round(material.weight / 10, 0.1), 6)
var/slowdownUncapped = (material_slowdown_multiplier * slowdownModified) - material_slowdown_modifier
slowdown = max(slowdownUncapped, 0)
/obj/item/clothing/suit/armor/material
name = "armor"
@@ -201,6 +208,67 @@ Protectiveness | Armor %
desc = "This appears to be two 'sheets' of a material held together by cable. If the sheets are strong, this could be rather protective."
icon_state = "material_armor_makeshift"
/obj/item/clothing/accessory/material/makeshift/light //Craftable with 4 material sheets, less slowdown, less armour
name = "light armor plate"
desc = "A thin plate of padded material, designed to fit into a plate carrier. Attaches to a plate carrier."
icon = 'icons/obj/clothing/modular_armor.dmi'
icon_state = "armor_light"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
slot = ACCESSORY_SLOT_ARMOR_C
material_armor_modifier = 0.8
material_slowdown_modifier = 0.5 //Subtracted from total slowdown
material_slowdown_multiplier = 0.8 //Multiplied by total slowdown
/obj/item/clothing/accessory/material/makeshift/heavy //Craftable with 8 material sheets, more slowdown, more armour
name = "heavy armor plate"
desc = "A thick plate of padded material, designed to fit into a plate carrier. Attaches to a plate carrier."
icon = 'icons/obj/clothing/modular_armor.dmi'
icon_state = "armor_medium"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
slot = ACCESSORY_SLOT_ARMOR_C
material_armor_modifier = 1.2
material_slowdown_modifier = 0
material_slowdown_multiplier = 1
/obj/item/clothing/accessory/material/custom //Not yet craftable, advanced version made with science!
name = "custom armor plate"
desc = "A composite plate of custom machined material, designed to fit into a plate carrier. Attaches to a plate carrier."
icon = 'icons/obj/clothing/modular_armor.dmi'
icon_state = "armor_tactical"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
slot = ACCESSORY_SLOT_ARMOR_C
material_armor_modifier = 1.2
material_slowdown_modifier = 0.5
material_slowdown_multiplier = 0.8
/obj/item/clothing/accessory/material/makeshift/armguards
name = "arm guards"
desc = "A pair of arm pads reinforced with material. Attaches to a plate carrier."
// accessory_icons = list(slot_tie_str = 'icons/mob/modular_armor.dmi', slot_wear_suit_str = 'icons/mob/modular_armor.dmi')
icon = 'icons/obj/clothing/modular_armor.dmi'
icon_override = 'icons/mob/modular_armor.dmi'
icon_state = "armguards_material"
gender = PLURAL
body_parts_covered = ARMS
slot = ACCESSORY_SLOT_ARMOR_A
material_armor_modifier = 0.8
material_slowdown_modifier = 0.8
material_slowdown_multiplier = 0.8
/obj/item/clothing/accessory/material/makeshift/legguards
name = "leg guards"
desc = "A pair of leg guards reinforced with material. Attaches to a plate carrier."
// accessory_icons = list(slot_tie_str = 'icons/mob/modular_armor.dmi', slot_wear_suit_str = 'icons/mob/modular_armor.dmi')
icon = 'icons/obj/clothing/modular_armor.dmi'
icon_override = 'icons/mob/modular_armor.dmi'
icon_state = "legguards_material"
gender = PLURAL
body_parts_covered = LEGS
slot = ACCESSORY_SLOT_ARMOR_L
material_armor_modifier = 0.8
material_slowdown_modifier = 0.8
material_slowdown_multiplier = 0.8
/obj/item/clothing/suit/armor/material/makeshift/durasteel
default_material = "durasteel"
@@ -218,6 +286,9 @@ Protectiveness | Armor %
thrown_force_divisor = 0.2
var/wired = FALSE
/obj/item/weapon/material/armor_plating/insert
unbreakable = FALSE
/obj/item/weapon/material/armor_plating/attackby(var/obj/O, mob/user)
if(istype(O, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/S = O
@@ -249,6 +320,54 @@ Protectiveness | Armor %
else
..()
//Make plating inserts for modular armour.
/obj/item/weapon/material/armor_plating/insert/attackby(var/obj/O, mob/user)
. = ..()
if(istype(O, /obj/item/weapon/weldingtool))
var /obj/item/weapon/weldingtool/S = O
if(S.remove_fuel(0,user))
if(!src || !S.isOn()) return
to_chat(user, "<span class='notice'>You trim down the edges to size.</span>")
user.drop_from_inventory(src)
var/obj/item/clothing/accessory/material/makeshift/light/new_armor = new(null, src.material.name)
user.put_in_hands(new_armor)
qdel(src)
return
if(istype(O, /obj/item/weapon/material/armor_plating/insert))
var/obj/item/weapon/material/armor_plating/insert/second_plate = O
if(second_plate.material != src.material)
to_chat(user, "<span class='warning'>Both plates need to be the same type of material.</span>")
return
to_chat(user, "<span class='notice'>You bond the two plates together.</span>")
user.drop_from_inventory(src)
user.drop_from_inventory(second_plate)
var/obj/item/clothing/accessory/material/makeshift/heavy/new_armor = new(null, src.material.name)
user.put_in_hands(new_armor)
qdel(second_plate)
qdel(src)
return
if(istype(O, /obj/item/weapon/tool/wirecutters))
to_chat(user, "<span class='notice'>You split the plate down the middle, and joint it at the elbow.</span>")
user.drop_from_inventory(src)
var/obj/item/clothing/accessory/material/makeshift/armguards/new_armor = new(null, src.material.name)
user.put_in_hands(new_armor)
qdel(src)
return
if(istype(O, /obj/item/stack/material))
var/obj/item/stack/material/S = O
if(S.material == get_material_by_name("leather"))
if(S.use(2))
to_chat(user, "<span class='notice'>You curve the plate inwards, and add a strap for adjustment.</span>")
user.drop_from_inventory(src)
var/obj/item/clothing/accessory/material/makeshift/legguards/new_armor = new(null, src.material.name)
user.put_in_hands(new_armor)
qdel(src)
return
// Used to craft the makeshift helmet
/obj/item/clothing/head/helmet/bucket
@@ -77,14 +77,14 @@
//visible_message("[user] has smashed the snowball in their hand!", "You smash the snowball in your hand.")
to_chat(user, "<span class='notice'>You smash the snowball in your hand.</span>")
var/atom/S = new /obj/item/stack/material/snow(user.loc)
del(src)
qdel(src)
user.put_in_hands(S)
else
//visible_message("[user] starts compacting the snowball.", "You start compacting the snowball.")
to_chat(user, "<span class='notice'>You start compacting the snowball.</span>")
if(do_after(user, 2 SECONDS))
var/atom/S = new /obj/item/weapon/material/snow/snowball/reinforced(user.loc)
del(src)
qdel(src)
user.put_in_hands(S)
/obj/item/weapon/material/snow/snowball/reinforced
@@ -6,7 +6,7 @@
item_state = "saddlebag"
icon_state = "saddlebag"
max_storage_space = INVENTORY_DUFFLEBAG_SPACE //Saddlebags can hold more, like dufflebags
slowdown = 1 //And are slower, too...Unless you're a macro, that is.
slowdown = 1 //And are slower, too...
var/taurtype = /datum/sprite_accessory/tail/taur/horse //Acceptable taur type to be wearing this
var/no_message = "You aren't the appropriate taur type to wear this!"
@@ -35,7 +35,7 @@
icon_state = "saddlebag"
var/icon_base = "saddlebag"
max_storage_space = INVENTORY_DUFFLEBAG_SPACE //Saddlebags can hold more, like dufflebags
slowdown = 1 //And are slower, too...Unless you're a macro, that is.
slowdown = 1 //And are slower, too...
var/no_message = "You aren't the appropriate taur type to wear this!"
mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = 0)
@@ -44,11 +44,6 @@
log_runtime("[H] was not a valid human!")
return
if(H.size_multiplier >= RESIZE_BIG) //Are they a macro? If yes, they get no slowdown.
slowdown = 0
else
slowdown = initial(slowdown)
var/datum/sprite_accessory/tail/taur/TT = H.tail_style
item_state = "[icon_base]_[TT.icon_sprite_tag]" //icon_sprite_tag is something like "deer"
return 1
@@ -174,7 +174,7 @@
gauge_icon = "indicator_emergency"
/obj/item/weapon/tank/emergency/nitrogen/Initialize()
..()
. = ..()
src.air_contents.adjust_gas("nitrogen", (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/weapon/tank/emergency/nitrogen/double
@@ -671,7 +671,7 @@
always_process = TRUE
/obj/item/weapon/weldingtool/electric/mounted/exosuit/Initialize()
..()
. = ..()
if(istype(loc, /obj/item/mecha_parts/mecha_equipment))
equip_mount = loc
-18
View File
@@ -19,29 +19,11 @@
var/can_speak = 0 //For MMIs and admin trickery. If an object has a brainmob in its contents, set this to 1 to allow it to speak.
var/show_examine = TRUE // Does this pop up on a mob when the mob is examined?
var/register_as_dangerous_object = FALSE // Should this tell its turf that it is dangerous automatically?
/obj/Initialize()
if(register_as_dangerous_object)
register_dangerous_to_step()
return ..()
/obj/Destroy()
STOP_PROCESSING(SSobj, src)
if(register_as_dangerous_object)
unregister_dangerous_to_step()
return ..()
/obj/Moved(atom/oldloc)
. = ..()
if(register_as_dangerous_object)
var/turf/old_turf = get_turf(oldloc)
var/turf/new_turf = get_turf(src)
if(old_turf != new_turf)
old_turf.unregister_dangerous_object(src)
new_turf.register_dangerous_object(src)
/obj/Topic(href, href_list, var/datum/tgui_state/state = GLOB.tgui_default_state)
if(usr && ..())
return 1
+1 -1
View File
@@ -8,7 +8,7 @@
// creates a new object and deletes itself
/obj/random/Initialize()
. = ..()
..()
if (!prob(spawn_nothing_percentage))
spawn_item()
return INITIALIZE_HINT_QDEL
+252 -236
View File
@@ -1,236 +1,252 @@
GLOBAL_LIST_EMPTY(cliff_icon_cache)
/*
Cliffs give a visual illusion of depth by seperating two places while presenting a 'top' and 'bottom' side.
Mobs moving into a cliff from the bottom side will simply bump into it and be denied moving into the tile,
where as mobs moving into a cliff from the top side will 'fall' off the cliff, forcing them to the bottom, causing significant damage and stunning them.
Mobs can climb this while wearing climbing equipment by clickdragging themselves onto a cliff, as if it were a table.
Flying mobs can pass over all cliffs with no risk of falling.
Projectiles and thrown objects can pass, however if moving upwards, there is a chance for it to be stopped by the cliff.
This makes fighting something that is on top of a cliff more challenging.
As a note, dir points upwards, e.g. pointing WEST means the left side is 'up', and the right side is 'down'.
When mapping these in, be sure to give at least a one tile clearance, as NORTH facing cliffs expand to
two tiles on initialization, and which way a cliff is facing may change during maploading.
*/
/obj/structure/cliff
name = "cliff"
desc = "A steep rock ledge. You might be able to climb it if you feel bold enough."
description_info = "Walking off the edge of a cliff while on top will cause you to fall off, causing severe injury.<br>\
You can climb this cliff if wearing special climbing equipment, by click-dragging yourself onto the cliff.<br>\
Projectiles traveling up a cliff may hit the cliff instead, making it more difficult to fight something \
on top."
icon = 'icons/obj/flora/rocks.dmi'
anchored = TRUE
density = TRUE
opacity = FALSE
climbable = TRUE
climb_delay = 10 SECONDS
block_turf_edges = TRUE // Don't want turf edges popping up from the cliff edge.
register_as_dangerous_object = TRUE
var/icon_variant = null // Used to make cliffs less repeative by having a selection of sprites to display.
var/corner = FALSE // Used for icon things.
var/ramp = FALSE // Ditto.
var/bottom = FALSE // Used for 'bottom' typed cliffs, to avoid infinite cliffs, and for icons.
var/is_double_cliff = FALSE // Set to true when making the two-tile cliffs, used for projectile checks.
var/uphill_penalty = 30 // Odds of a projectile not making it up the cliff.
// These arrange their sprites at runtime, as opposed to being statically placed in the map file.
/obj/structure/cliff/automatic
icon_state = "cliffbuilder"
dir = NORTH
/obj/structure/cliff/automatic/corner
icon_state = "cliffbuilder-corner"
dir = NORTHEAST
corner = TRUE
// Tiny part that doesn't block, used for making 'ramps'.
/obj/structure/cliff/automatic/ramp
icon_state = "cliffbuilder-ramp"
dir = NORTHEAST
density = FALSE
ramp = TRUE
// Made automatically as needed by automatic cliffs.
/obj/structure/cliff/bottom
bottom = TRUE
/obj/structure/cliff/automatic/Initialize()
..()
return INITIALIZE_HINT_LATELOAD
// Paranoid about the maploader, direction is very important to cliffs, since they may get bigger if initialized while facing NORTH.
/obj/structure/cliff/automatic/LateInitialize()
if(dir in GLOB.cardinal)
icon_variant = pick("a", "b", "c")
if(dir & NORTH && !bottom) // North-facing cliffs require more cliffs to be made.
make_bottom()
update_icon()
/obj/structure/cliff/proc/make_bottom()
// First, make sure there's room to put the bottom side.
var/turf/T = locate(x, y - 1, z)
if(!istype(T))
return FALSE
// Now make the bottom cliff have mostly the same variables.
var/obj/structure/cliff/bottom/bottom = new(T)
is_double_cliff = TRUE
climb_delay /= 2 // Since there are two cliffs to climb when going north, both take half the time.
bottom.dir = dir
bottom.is_double_cliff = TRUE
bottom.climb_delay = climb_delay
bottom.icon_variant = icon_variant
bottom.corner = corner
bottom.ramp = ramp
bottom.layer = layer - 0.1
bottom.density = density
bottom.update_icon()
/obj/structure/cliff/set_dir(new_dir)
..()
update_icon()
/obj/structure/cliff/update_icon()
icon_state = "cliff-[dir][icon_variant][bottom ? "-bottom" : ""][corner ? "-corner" : ""][ramp ? "-ramp" : ""]"
// Now for making the top-side look like a different turf.
var/turf/T = get_step(src, dir)
if(!istype(T))
return
var/subtraction_icon_state = "[icon_state]-subtract"
var/cache_string = "[icon_state]_[T.icon]_[T.icon_state]"
if(T && subtraction_icon_state in cached_icon_states(icon))
cut_overlays()
// If we've made the same icon before, just recycle it.
if(cache_string in GLOB.cliff_icon_cache)
add_overlay(GLOB.cliff_icon_cache[cache_string])
else // Otherwise make a new one, but only once.
var/icon/underlying_ground = icon(T.icon, T.icon_state, T.dir)
var/icon/subtract = icon(icon, subtraction_icon_state)
underlying_ground.Blend(subtract, ICON_SUBTRACT)
var/image/final = image(underlying_ground)
final.layer = src.layer - 0.2
GLOB.cliff_icon_cache[cache_string] = final
add_overlay(final)
// Movement-related code.
/obj/structure/cliff/CanPass(atom/movable/mover, turf/target)
if(isliving(mover))
var/mob/living/L = mover
if(L.hovering) // Flying mobs can always pass.
return TRUE
return ..()
// Projectiles and objects flying 'upward' have a chance to hit the cliff instead, wasting the shot.
else if(istype(mover, /obj))
var/obj/O = mover
if(check_shield_arc(src, dir, O)) // This is actually for mobs but it will work for our purposes as well.
if(prob(uphill_penalty / (1 + is_double_cliff) )) // Firing upwards facing NORTH means it will likely have to pass through two cliffs, so the chance is halved.
return FALSE
return TRUE
/obj/structure/cliff/Bumped(atom/A)
if(isliving(A))
var/mob/living/L = A
if(should_fall(L))
fall_off_cliff(L)
return
..()
/obj/structure/cliff/proc/should_fall(mob/living/L)
if(L.hovering)
return FALSE
var/turf/T = get_turf(L)
if(T && get_dir(T, loc) & reverse_dir[dir]) // dir points 'up' the cliff, e.g. cliff pointing NORTH will cause someone to fall if moving SOUTH into it.
return TRUE
return FALSE
/obj/structure/cliff/proc/fall_off_cliff(mob/living/L)
if(!istype(L))
return FALSE
var/turf/T = get_step(src, reverse_dir[dir])
var/displaced = FALSE
if(dir in list(EAST, WEST)) // Apply an offset if flying sideways, to help maintain the illusion of depth.
for(var/i = 1 to 2)
var/turf/new_T = locate(T.x, T.y - i, T.z)
if(!new_T || locate(/obj/structure/cliff) in new_T)
break
T = new_T
displaced = TRUE
if(istype(T))
visible_message(span("danger", "\The [L] falls off \the [src]!"))
L.forceMove(T)
// Do the actual hurting. Double cliffs do halved damage due to them most likely hitting twice.
var/harm = !is_double_cliff ? 1 : 0.5
if(istype(L.buckled, /obj/vehicle)) // People falling off in vehicles will take less damage, but will damage the vehicle severely.
var/obj/vehicle/vehicle = L.buckled
vehicle.adjust_health(40 * harm)
to_chat(L, span("warning", "\The [vehicle] absorbs some of the impact, damaging it."))
harm /= 2
playsound(L, 'sound/effects/break_stone.ogg', 70, 1)
L.Weaken(5 * harm)
var/fall_time = 3
if(displaced) // Make the fall look more natural when falling sideways.
L.pixel_z = 32 * 2
animate(L, pixel_z = 0, time = fall_time)
sleep(fall_time) // A brief delay inbetween the two sounds helps sell the 'ouch' effect.
playsound(L, "punch", 70, 1)
shake_camera(L, 1, 1)
visible_message(span("danger", "\The [L] hits the ground!"))
// The bigger they are, the harder they fall.
// They will take at least 20 damage at the minimum, and tries to scale up to 40% of their max health.
// This scaling is capped at 100 total damage, which occurs if the thing that fell has more than 250 health.
var/damage = between(20, L.getMaxHealth() * 0.4, 100)
var/target_zone = ran_zone()
var/blocked = L.run_armor_check(target_zone, "melee") * harm
var/soaked = L.get_armor_soak(target_zone, "melee") * harm
L.apply_damage(damage * harm, BRUTE, target_zone, blocked, soaked, used_weapon=src)
// Now fall off more cliffs below this one if they exist.
var/obj/structure/cliff/bottom_cliff = locate() in T
if(bottom_cliff)
visible_message(span("danger", "\The [L] rolls down towards \the [bottom_cliff]!"))
sleep(5)
bottom_cliff.fall_off_cliff(L)
/obj/structure/cliff/can_climb(mob/living/user, post_climb_check = FALSE)
// Cliff climbing requires climbing gear.
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/clothing/shoes/shoes = H.shoes
if(shoes && shoes.rock_climbing)
return ..() // Do the other checks too.
to_chat(user, span("warning", "\The [src] is too steep to climb unassisted."))
return FALSE
// This tells AI mobs to not be dumb and step off cliffs willingly.
/obj/structure/cliff/is_safe_to_step(mob/living/L)
if(should_fall(L))
return FALSE
return ..()
GLOBAL_LIST_EMPTY(cliff_icon_cache)
/*
Cliffs give a visual illusion of depth by seperating two places while presenting a 'top' and 'bottom' side.
Mobs moving into a cliff from the bottom side will simply bump into it and be denied moving into the tile,
where as mobs moving into a cliff from the top side will 'fall' off the cliff, forcing them to the bottom, causing significant damage and stunning them.
Mobs can climb this while wearing climbing equipment by clickdragging themselves onto a cliff, as if it were a table.
Flying mobs can pass over all cliffs with no risk of falling.
Projectiles and thrown objects can pass, however if moving upwards, there is a chance for it to be stopped by the cliff.
This makes fighting something that is on top of a cliff more challenging.
As a note, dir points upwards, e.g. pointing WEST means the left side is 'up', and the right side is 'down'.
When mapping these in, be sure to give at least a one tile clearance, as NORTH facing cliffs expand to
two tiles on initialization, and which way a cliff is facing may change during maploading.
*/
/obj/structure/cliff
name = "cliff"
desc = "A steep rock ledge. You might be able to climb it if you feel bold enough."
description_info = "Walking off the edge of a cliff while on top will cause you to fall off, causing severe injury.<br>\
You can climb this cliff if wearing special climbing equipment, by click-dragging yourself onto the cliff.<br>\
Projectiles traveling up a cliff may hit the cliff instead, making it more difficult to fight something \
on top."
icon = 'icons/obj/flora/rocks.dmi'
anchored = TRUE
density = TRUE
opacity = FALSE
climbable = TRUE
climb_delay = 10 SECONDS
block_turf_edges = TRUE // Don't want turf edges popping up from the cliff edge.
var/icon_variant = null // Used to make cliffs less repeative by having a selection of sprites to display.
var/corner = FALSE // Used for icon things.
var/ramp = FALSE // Ditto.
var/bottom = FALSE // Used for 'bottom' typed cliffs, to avoid infinite cliffs, and for icons.
var/is_double_cliff = FALSE // Set to true when making the two-tile cliffs, used for projectile checks.
var/uphill_penalty = 30 // Odds of a projectile not making it up the cliff.
/obj/structure/cliff/Initialize()
. = ..()
register_dangerous_to_step()
/obj/structure/cliff/Destroy()
unregister_dangerous_to_step()
. = ..()
/obj/structure/cliff/Moved(atom/oldloc)
. = ..()
if(.)
var/turf/old_turf = get_turf(oldloc)
var/turf/new_turf = get_turf(src)
if(old_turf != new_turf)
old_turf.unregister_dangerous_object(src)
new_turf.register_dangerous_object(src)
// These arrange their sprites at runtime, as opposed to being statically placed in the map file.
/obj/structure/cliff/automatic
icon_state = "cliffbuilder"
dir = NORTH
/obj/structure/cliff/automatic/corner
icon_state = "cliffbuilder-corner"
dir = NORTHEAST
corner = TRUE
// Tiny part that doesn't block, used for making 'ramps'.
/obj/structure/cliff/automatic/ramp
icon_state = "cliffbuilder-ramp"
dir = NORTHEAST
density = FALSE
ramp = TRUE
// Made automatically as needed by automatic cliffs.
/obj/structure/cliff/bottom
bottom = TRUE
/obj/structure/cliff/automatic/Initialize()
..()
return INITIALIZE_HINT_LATELOAD
// Paranoid about the maploader, direction is very important to cliffs, since they may get bigger if initialized while facing NORTH.
/obj/structure/cliff/automatic/LateInitialize()
if(dir in GLOB.cardinal)
icon_variant = pick("a", "b", "c")
if(dir & NORTH && !bottom) // North-facing cliffs require more cliffs to be made.
make_bottom()
update_icon()
/obj/structure/cliff/proc/make_bottom()
// First, make sure there's room to put the bottom side.
var/turf/T = locate(x, y - 1, z)
if(!istype(T))
return FALSE
// Now make the bottom cliff have mostly the same variables.
var/obj/structure/cliff/bottom/bottom = new(T)
is_double_cliff = TRUE
climb_delay /= 2 // Since there are two cliffs to climb when going north, both take half the time.
bottom.dir = dir
bottom.is_double_cliff = TRUE
bottom.climb_delay = climb_delay
bottom.icon_variant = icon_variant
bottom.corner = corner
bottom.ramp = ramp
bottom.layer = layer - 0.1
bottom.density = density
bottom.update_icon()
/obj/structure/cliff/set_dir(new_dir)
..()
update_icon()
/obj/structure/cliff/update_icon()
icon_state = "cliff-[dir][icon_variant][bottom ? "-bottom" : ""][corner ? "-corner" : ""][ramp ? "-ramp" : ""]"
// Now for making the top-side look like a different turf.
var/turf/T = get_step(src, dir)
if(!istype(T))
return
var/subtraction_icon_state = "[icon_state]-subtract"
var/cache_string = "[icon_state]_[T.icon]_[T.icon_state]"
if(T && subtraction_icon_state in cached_icon_states(icon))
cut_overlays()
// If we've made the same icon before, just recycle it.
if(cache_string in GLOB.cliff_icon_cache)
add_overlay(GLOB.cliff_icon_cache[cache_string])
else // Otherwise make a new one, but only once.
var/icon/underlying_ground = icon(T.icon, T.icon_state, T.dir)
var/icon/subtract = icon(icon, subtraction_icon_state)
underlying_ground.Blend(subtract, ICON_SUBTRACT)
var/image/final = image(underlying_ground)
final.layer = src.layer - 0.2
GLOB.cliff_icon_cache[cache_string] = final
add_overlay(final)
// Movement-related code.
/obj/structure/cliff/CanPass(atom/movable/mover, turf/target)
if(isliving(mover))
var/mob/living/L = mover
if(L.hovering) // Flying mobs can always pass.
return TRUE
return ..()
// Projectiles and objects flying 'upward' have a chance to hit the cliff instead, wasting the shot.
else if(istype(mover, /obj))
var/obj/O = mover
if(check_shield_arc(src, dir, O)) // This is actually for mobs but it will work for our purposes as well.
if(prob(uphill_penalty / (1 + is_double_cliff) )) // Firing upwards facing NORTH means it will likely have to pass through two cliffs, so the chance is halved.
return FALSE
return TRUE
/obj/structure/cliff/Bumped(atom/A)
if(isliving(A))
var/mob/living/L = A
if(should_fall(L))
fall_off_cliff(L)
return
..()
/obj/structure/cliff/proc/should_fall(mob/living/L)
if(L.hovering)
return FALSE
var/turf/T = get_turf(L)
if(T && get_dir(T, loc) & reverse_dir[dir]) // dir points 'up' the cliff, e.g. cliff pointing NORTH will cause someone to fall if moving SOUTH into it.
return TRUE
return FALSE
/obj/structure/cliff/proc/fall_off_cliff(mob/living/L)
if(!istype(L))
return FALSE
var/turf/T = get_step(src, reverse_dir[dir])
var/displaced = FALSE
if(dir in list(EAST, WEST)) // Apply an offset if flying sideways, to help maintain the illusion of depth.
for(var/i = 1 to 2)
var/turf/new_T = locate(T.x, T.y - i, T.z)
if(!new_T || locate(/obj/structure/cliff) in new_T)
break
T = new_T
displaced = TRUE
if(istype(T))
visible_message(span("danger", "\The [L] falls off \the [src]!"))
L.forceMove(T)
// Do the actual hurting. Double cliffs do halved damage due to them most likely hitting twice.
var/harm = !is_double_cliff ? 1 : 0.5
if(istype(L.buckled, /obj/vehicle)) // People falling off in vehicles will take less damage, but will damage the vehicle severely.
var/obj/vehicle/vehicle = L.buckled
vehicle.adjust_health(40 * harm)
to_chat(L, span("warning", "\The [vehicle] absorbs some of the impact, damaging it."))
harm /= 2
playsound(L, 'sound/effects/break_stone.ogg', 70, 1)
L.Weaken(5 * harm)
var/fall_time = 3
if(displaced) // Make the fall look more natural when falling sideways.
L.pixel_z = 32 * 2
animate(L, pixel_z = 0, time = fall_time)
sleep(fall_time) // A brief delay inbetween the two sounds helps sell the 'ouch' effect.
playsound(L, "punch", 70, 1)
shake_camera(L, 1, 1)
visible_message(span("danger", "\The [L] hits the ground!"))
// The bigger they are, the harder they fall.
// They will take at least 20 damage at the minimum, and tries to scale up to 40% of their max health.
// This scaling is capped at 100 total damage, which occurs if the thing that fell has more than 250 health.
var/damage = between(20, L.getMaxHealth() * 0.4, 100)
var/target_zone = ran_zone()
var/blocked = L.run_armor_check(target_zone, "melee") * harm
var/soaked = L.get_armor_soak(target_zone, "melee") * harm
L.apply_damage(damage * harm, BRUTE, target_zone, blocked, soaked, used_weapon=src)
// Now fall off more cliffs below this one if they exist.
var/obj/structure/cliff/bottom_cliff = locate() in T
if(bottom_cliff)
visible_message(span("danger", "\The [L] rolls down towards \the [bottom_cliff]!"))
sleep(5)
bottom_cliff.fall_off_cliff(L)
/obj/structure/cliff/can_climb(mob/living/user, post_climb_check = FALSE)
// Cliff climbing requires climbing gear.
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/clothing/shoes/shoes = H.shoes
if(shoes && shoes.rock_climbing)
return ..() // Do the other checks too.
to_chat(user, span("warning", "\The [src] is too steep to climb unassisted."))
return FALSE
// This tells AI mobs to not be dumb and step off cliffs willingly.
/obj/structure/cliff/is_safe_to_step(mob/living/L)
if(should_fall(L))
return FALSE
return ..()
@@ -37,7 +37,6 @@
/obj/structure/closet/Initialize()
..()
// Closets need to come later because of spawners potentially creating objects during init.
return INITIALIZE_HINT_LATELOAD
/obj/structure/closet/LateInitialize()
@@ -133,7 +133,6 @@
/obj/item/clothing/gloves/fingerless,
/obj/item/device/radio/headset/pilot,
/obj/item/device/radio/headset/pilot/alt,
/obj/item/weapon/cartridge/explorer,
/obj/item/device/flashlight,
/obj/item/weapon/reagent_containers/food/snacks/liquidfood,
/obj/item/weapon/reagent_containers/food/snacks/liquidprotein,
@@ -0,0 +1,25 @@
//Dance pole
/obj/structure/dancepole
name = "dance pole"
desc = "Engineered for your entertainment"
icon = 'icons/obj/objects_vr.dmi'
icon_state = "dancepole"
density = 0
anchored = 1
/obj/structure/dancepole/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(O.is_screwdriver())
anchored = !anchored
playsound(src, O.usesound, 50, 1)
if(anchored)
to_chat(user, "<font color='blue'>You secure \the [src].</font>")
else
to_chat(user, "<font color='blue'>You unsecure \the [src].</font>")
if(O.is_wrench())
playsound(src, O.usesound, 50, 1)
to_chat(user, "<span class='notice'>Now disassembling \the [src]...</span>")
if(do_after(user, 30 * O.toolspeed))
if(!src) return
to_chat(user, "<span class='notice'>You dissasembled \the [src]!</span>")
new /obj/item/stack/material/steel(src.loc, 1)
qdel(src)
+1 -1
View File
@@ -14,7 +14,7 @@
var/smashed = 0
/obj/structure/fireaxecabinet/Initialize()
..()
. = ..()
fireaxe = new /obj/item/weapon/material/twohanded/fireaxe()
/obj/structure/fireaxecabinet/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
+1 -1
View File
@@ -22,7 +22,7 @@
var/list/harvest_loot = null // Should be an associative list for things to spawn, and their weights. An example would be a branch from a tree.
/obj/structure/flora/Initialize()
..()
. = ..()
if(randomize_size)
icon_scale_x = rand(min_x_scale * 100, max_x_scale * 100) / 100
@@ -28,7 +28,7 @@
icon_state = icon_state_opened
if(needscharger)
new /obj/machinery/recharge_station/ghost_pod_recharger(src.loc)
del(src)
qdel(src)
return TRUE
else
return FALSE
@@ -25,7 +25,7 @@
var/list/clothing_possibilities
/obj/structure/ghost_pod/ghost_activated/human/Initialize()
..()
. = ..()
handle_clothing_setup()
@@ -153,7 +153,7 @@
var/list/clothing_possibilities
/obj/structure/ghost_pod/manual/human/Initialize()
..()
. = ..()
handle_clothing_setup()
@@ -89,7 +89,7 @@
qdel(src)
/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/Initialize()
..()
. = ..()
var/turf/T = get_turf(src)
say_dead_object("A <span class='notice'>[drone_class] swarm drone</span> shell is now available in \the [T.loc].", src)
+1 -1
View File
@@ -20,7 +20,7 @@
var/total_creature_max //If set, it can spawn this many creatures, total, ever.
/obj/structure/prop/nest/Initialize()
..()
. = ..()
den_mobs = list()
START_PROCESSING(SSobj, src)
last_spawn = world.time
+1 -1
View File
@@ -23,7 +23,7 @@
return ..()
/obj/structure/cult/pylon/swarm/Initialize()
..()
. = ..()
active_beams = list()
/obj/structure/cult/pylon/swarm/Destroy()
@@ -1,26 +1,59 @@
/obj/structure/bed/chair/wheelchair
name = "wheelchair"
desc = "You sit in this. Either by will or force."
icon = 'icons/obj/wheelchair.dmi'
icon_state = "wheelchair"
anchored = 0
buckle_movable = 1
var/folded_type = /obj/item/wheelchair
var/driving = 0
var/mob/living/pulling = null
var/bloodiness
var/min_mob_buckle_size = MOB_SMALL
var/max_mob_buckle_size = MOB_LARGE
/obj/structure/bed/chair/wheelchair/Initialize()
. = ..()
update_icon()
/obj/structure/bed/chair/wheelchair/motor
name = "electric wheelchair"
desc = "A motorized wheelchair controlled with a joystick on one armrest"
icon_state = "motorchair"
folded_type = /obj/item/wheelchair/motor
/obj/structure/bed/chair/wheelchair/smallmotor
name = "small electric wheelchair"
desc = "A small motorized wheelchair, it looks around the right size for a Teshari"
icon_state = "teshchair"
min_mob_buckle_size = MOB_SMALL
max_mob_buckle_size = MOB_MEDIUM
folded_type = /obj/item/wheelchair/motor/small
/obj/structure/bed/chair/wheelchair/can_buckle_check(mob/living/M, forced = FALSE)
. = ..()
if(.)
if(M.mob_size < min_mob_buckle_size)
to_chat(M, SPAN_WARNING("You are too small to use \the [src]."))
. = FALSE
else if(M.mob_size >= max_mob_buckle_size)
to_chat(M, SPAN_WARNING("You are too large to use \the [src]."))
. = FALSE
/obj/structure/bed/chair/wheelchair/update_icon()
return
cut_overlays()
var/image/O = image(icon = icon, icon_state = "[icon_state]_overlay", layer = ABOVE_MOB_LAYER)
O.plane = MOB_PLANE
add_overlay(O)
/obj/structure/bed/chair/wheelchair/set_dir()
..()
cut_overlays()
var/image/O = image(icon = 'icons/obj/furniture.dmi', icon_state = "w_overlay", layer = FLY_LAYER, dir = src.dir)
add_overlay(O)
if(has_buckled_mobs())
for(var/A in buckled_mobs)
var/mob/living/L = A
L.set_dir(dir)
. = ..()
if(.)
if(has_buckled_mobs())
for(var/A in buckled_mobs)
var/mob/living/L = A
L.set_dir(dir)
/obj/structure/bed/chair/wheelchair/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(W.is_wrench() || W.is_wirecutter() || istype(W,/obj/item/stack))
@@ -93,8 +126,6 @@
/obj/structure/bed/chair/wheelchair/Moved(atom/old_loc, direction, forced = FALSE)
. = ..()
cut_overlays()
playsound(src, 'sound/effects/roll.ogg', 75, 1)
if(has_buckled_mobs())
for(var/A in buckled_mobs)
@@ -203,28 +234,13 @@
usr.pulledby = null
..()
/obj/item/wheelchair
name = "wheelchair"
desc = "A folded wheelchair that can be carried around."
icon = 'icons/obj/furniture.dmi'
icon_state = "wheelchair_folded"
item_state = "wheelchair"
w_class = ITEMSIZE_HUGE // Can't be put in backpacks. Oh well.
/obj/item/wheelchair/attack_self(mob/user)
var/obj/structure/bed/chair/wheelchair/R = new /obj/structure/bed/chair/wheelchair(user.loc)
R.add_fingerprint(user)
R.name = src.name
R.color = src.color
qdel(src)
/obj/structure/bed/chair/wheelchair/MouseDrop(over_object, src_location, over_location)
..()
if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src))))
if(!ishuman(usr)) return
if(has_buckled_mobs()) return 0
visible_message("[usr] collapses \the [src.name].")
var/obj/item/wheelchair/R = new/obj/item/wheelchair(get_turf(src))
var/obj/item/wheelchair/R = new folded_type(get_turf(src))
R.name = src.name
R.color = src.color
spawn(0)
@@ -0,0 +1,29 @@
/obj/item/wheelchair
name = "wheelchair"
desc = "A folded wheelchair that can be carried around."
icon = 'icons/obj/wheelchair.dmi'
icon_state = "wheelchair_folded"
item_state = "wheelchair"
w_class = ITEMSIZE_HUGE // Can't be put in backpacks. Oh well.
var/unfolded_type = /obj/structure/bed/chair/wheelchair
/obj/item/wheelchair/attack_self(mob/user)
var/obj/structure/bed/chair/wheelchair/R = new unfolded_type(user.loc)
R.add_fingerprint(user)
R.name = src.name
R.color = src.color
qdel(src)
/obj/item/wheelchair/motor
name = "electric wheelchair"
desc = "A motorized wheelchair controlled with a joystick on one armrest"
icon_state = "motorchair_folded"
item_state = "motorchair"
unfolded_type = /obj/structure/bed/chair/wheelchair/motor
/obj/item/wheelchair/motor/small
name = "small electric wheelchair"
desc = "A small motorized wheelchair, it looks around the right size for a Teshari."
icon_state = "teshchair_folded"
item_state = "teshchair"
unfolded_type = /obj/structure/bed/chair/wheelchair/smallmotor
@@ -180,6 +180,7 @@
prob(2);/obj/item/clothing/shoes/galoshes,
prob(2);/obj/item/clothing/under/pants/camo,
prob(2);/obj/item/clothing/under/syndicate/tacticool,
prob(2);/obj/item/clothing/under/hyperfiber,
prob(2);/obj/item/device/camera,
prob(2);/obj/item/device/flashlight/flare,
prob(2);/obj/item/device/flashlight/glowstick,
@@ -240,6 +241,7 @@
prob(2);/obj/item/weapon/handcuffs/legcuffs/fuzzy,
prob(2);/obj/item/weapon/storage/box/syndie_kit/spy,
prob(2);/obj/item/weapon/grenade/anti_photon,
prob(2);/obj/item/clothing/under/hyperfiber/bluespace,
prob(1);/obj/item/clothing/suit/storage/vest/heavy/merc,
prob(1);/obj/item/device/nif/bad,
prob(1);/obj/item/device/radio_jammer,
@@ -27,11 +27,10 @@
return FALSE
/obj/effect/wingrille_spawn/Initialize()
. = ..()
if(!win_path)
return
if(ticker && ticker.current_state < GAME_STATE_PLAYING)
if(win_path && ticker && ticker.current_state < GAME_STATE_PLAYING)
activate()
..()
return INITIALIZE_HINT_QDEL
/obj/effect/wingrille_spawn/proc/activate()
if(activated) return
@@ -58,7 +57,8 @@
activated = 1
for(var/obj/effect/wingrille_spawn/other in neighbours)
if(!other.activated) other.activate()
qdel(src)
if(initialized && !QDELETED(src))
qdel(src)
/obj/effect/wingrille_spawn/proc/handle_window_spawn(var/obj/structure/window/W)
return