mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-18 02:25:06 +01:00
Merge remote-tracking branch 'upstream/dev-freeze' into dev
Conflicts: code/_helpers/unsorted.dm code/game/objects/items/weapons/RCD.dm code/game/objects/items/weapons/grenades/emgrenade.dm code/modules/clothing/spacesuits/rig/rig_attackby.dm
This commit is contained in:
@@ -115,6 +115,10 @@
|
||||
H << "<span class='warning'>You cannot teleport into solid walls.</span>"
|
||||
return 0
|
||||
|
||||
if(T.z in config.admin_levels)
|
||||
H << "<span class='warning'>You cannot use your teleporter on this Z-level.</span>"
|
||||
return 0
|
||||
|
||||
phase_out(H,get_turf(H))
|
||||
H.loc = T
|
||||
phase_in(H,get_turf(H))
|
||||
|
||||
@@ -64,8 +64,8 @@
|
||||
var/malfunction_delay = 0
|
||||
var/electrified = 0
|
||||
var/locked_down = 0
|
||||
var/locked_dna = null
|
||||
|
||||
var/seal_delay = SEAL_DELAY
|
||||
var/sealing // Keeps track of seal status independantly of canremove.
|
||||
var/offline = 1 // Should we be applying suit maluses?
|
||||
var/offline_slowdown = 3 // If the suit is deployed and unpowered, it sets slowdown to this.
|
||||
@@ -205,7 +205,7 @@
|
||||
|
||||
if(!instant)
|
||||
M.visible_message("<font color='blue'>[M]'s suit emits a quiet hum as it begins to adjust its seals.</font>","<font color='blue'>With a quiet hum, the suit begins running checks and adjusting components.</font>")
|
||||
if(!do_after(M,SEAL_DELAY))
|
||||
if(seal_delay && !do_after(M,seal_delay))
|
||||
if(M) M << "<span class='warning'>You must remain still while the suit is adjusting the components.</span>"
|
||||
failed_to_seal = 1
|
||||
|
||||
@@ -229,9 +229,8 @@
|
||||
|
||||
if(!failed_to_seal && M.back == src && piece == compare_piece)
|
||||
|
||||
if(!instant)
|
||||
if(!do_after(M,SEAL_DELAY,needhand=0))
|
||||
failed_to_seal = 1
|
||||
if(seal_delay && !instant && !do_after(M,seal_delay,needhand=0))
|
||||
failed_to_seal = 1
|
||||
|
||||
piece.icon_state = "[initial(icon_state)][!seal_target ? "_sealed" : ""]"
|
||||
switch(msg_type)
|
||||
@@ -500,10 +499,6 @@
|
||||
return 0
|
||||
if(user.back != src)
|
||||
return 0
|
||||
if(locked_dna)
|
||||
if(!user.dna || user.dna.unique_enzymes != locked_dna)
|
||||
user << "<span class='danger'>DNA scan mismatch. Access denied.</span>"
|
||||
return 0
|
||||
else if(!src.allowed(user))
|
||||
user << "<span class='danger'>Unauthorized user. Access denied.</span>"
|
||||
return 0
|
||||
@@ -563,10 +558,9 @@
|
||||
/obj/item/weapon/rig/equipped(mob/living/carbon/human/M)
|
||||
..()
|
||||
|
||||
if(istype(M) && M.back == src)
|
||||
if(seal_delay > 0 && istype(M) && M.back == src)
|
||||
M.visible_message("<font color='blue'>[M] starts putting on \the [src]...</font>", "<font color='blue'>You start putting on \the [src]...</font>")
|
||||
|
||||
if(!do_after(M,SEAL_DELAY))
|
||||
if(!do_after(M,seal_delay))
|
||||
if(M && M.back == src)
|
||||
M.back = null
|
||||
M.drop_from_inventory(src)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
/datum/custom_item
|
||||
var/assoc_key
|
||||
var/character_name
|
||||
var/inherit_inhands = 1 //if unset, and inhands are not provided, then the inhand overlays will be invisible.
|
||||
var/item_icon
|
||||
var/item_desc
|
||||
var/name
|
||||
@@ -44,9 +45,20 @@
|
||||
if(item_desc)
|
||||
item.desc = item_desc
|
||||
if(item_icon)
|
||||
item.icon = CUSTOM_ITEM_OBJ
|
||||
item.icon_state = item_icon
|
||||
if(istype(item, /obj/item))
|
||||
if(!istype(item))
|
||||
item.icon = CUSTOM_ITEM_OBJ
|
||||
item.icon_state = item_icon
|
||||
return
|
||||
else
|
||||
if(inherit_inhands)
|
||||
apply_inherit_inhands(item)
|
||||
else
|
||||
item.item_state_slots = null
|
||||
item.item_icons = null
|
||||
|
||||
item.icon = CUSTOM_ITEM_OBJ
|
||||
item.icon_state = item_icon
|
||||
item.item_state = null
|
||||
item.icon_override = CUSTOM_ITEM_MOB
|
||||
|
||||
// Kits are dumb so this is going to have to be hardcoded/snowflake.
|
||||
@@ -66,6 +78,48 @@
|
||||
|
||||
return item
|
||||
|
||||
/datum/custom_item/proc/apply_inherit_inhands(var/obj/item/item)
|
||||
var/list/new_item_icons = list()
|
||||
var/list/new_item_state_slots = list()
|
||||
|
||||
var/list/available_states = icon_states(CUSTOM_ITEM_MOB)
|
||||
|
||||
//If l_hand or r_hand are not present, preserve them using item_icons/item_state_slots
|
||||
//Then use icon_override to make every other slot use the custom sprites by default.
|
||||
//This has to be done before we touch any of item's vars
|
||||
if(!("[item_icon]_l" in available_states))
|
||||
new_item_state_slots[slot_l_hand_str] = get_state(item, slot_l_hand_str, "_l")
|
||||
new_item_icons[slot_l_hand_str] = get_icon(item, slot_l_hand_str, 'icons/mob/items/lefthand.dmi')
|
||||
if(!("[item_icon]_r" in available_states))
|
||||
new_item_state_slots[slot_r_hand_str] = get_state(item, slot_r_hand_str, "_r")
|
||||
new_item_icons[slot_r_hand_str] = get_icon(item, slot_r_hand_str, 'icons/mob/items/righthand.dmi')
|
||||
|
||||
item.item_state_slots = new_item_state_slots
|
||||
item.item_icons = new_item_icons
|
||||
|
||||
//this has to mirror the way update_inv_*_hand() selects the state
|
||||
/datum/custom_item/proc/get_state(var/obj/item/item, var/slot_str, var/hand_str)
|
||||
var/t_state
|
||||
if(item.item_state_slots && item.item_state_slots[slot_str])
|
||||
t_state = item.item_state_slots[slot_str]
|
||||
else if(item.item_state)
|
||||
t_state = item.item_state
|
||||
else
|
||||
t_state = item.icon_state
|
||||
if(item.icon_override)
|
||||
t_state += hand_str
|
||||
return t_state
|
||||
|
||||
//this has to mirror the way update_inv_*_hand() selects the icon
|
||||
/datum/custom_item/proc/get_icon(var/obj/item/item, var/slot_str, var/icon/hand_icon)
|
||||
var/icon/t_icon
|
||||
if(item.icon_override)
|
||||
t_icon = item.icon_override
|
||||
else if(item.item_icons && (slot_str in item.item_icons))
|
||||
t_icon = item.item_icons[slot_str]
|
||||
else
|
||||
t_icon = hand_icon
|
||||
return t_icon
|
||||
|
||||
// Parses the config file into the custom_items list.
|
||||
/hook/startup/proc/load_custom_items()
|
||||
@@ -107,6 +161,8 @@
|
||||
current_data.name = field_data
|
||||
if("item_icon")
|
||||
current_data.item_icon = field_data
|
||||
if("inherit_inhands")
|
||||
current_data.inherit_inhands = text2num(field_data)
|
||||
if("item_desc")
|
||||
current_data.item_desc = field_data
|
||||
if("req_access")
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define LIGHTING_LAMBERTIAN 1 // use lambertian shading for light sources
|
||||
#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
|
||||
#define LIGHTING_TRANSITIONS 1 // smooth, animated transitions, similar to /tg/station
|
||||
#define LIGHTING_ROUND_VALUE (1 / 128) //Value used to round lumcounts, values smaller than 1/255 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
|
||||
|
||||
#define LIGHTING_RESOLUTION 1 // resolution of the lighting overlays, powers of 2 only, max of 32
|
||||
#define LIGHTING_LAYER 10 // drawing layer for lighting overlays
|
||||
#define LIGHTING_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects
|
||||
|
||||
@@ -60,13 +60,16 @@
|
||||
if(top_atom != source_atom)
|
||||
if(!top_atom.light_sources) top_atom.light_sources = list()
|
||||
top_atom.light_sources += src
|
||||
lighting_update_lights += src
|
||||
needs_update = 1
|
||||
|
||||
if(!needs_update)
|
||||
lighting_update_lights += src
|
||||
needs_update = 1
|
||||
|
||||
/datum/light_source/proc/force_update()
|
||||
needs_update = 1
|
||||
force_update = 1
|
||||
lighting_update_lights += src
|
||||
if(!needs_update)
|
||||
lighting_update_lights += src
|
||||
needs_update = 1
|
||||
|
||||
/datum/light_source/proc/check()
|
||||
if(!source_atom || !light_range || !light_power)
|
||||
@@ -113,11 +116,7 @@
|
||||
|
||||
/datum/light_source/proc/falloff(atom/movable/lighting_overlay/O)
|
||||
#if LIGHTING_FALLOFF == 1 // circular
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
. = (O.x - source_turf.x)**2 + (O.y - source_turf.y)**2 + LIGHTING_HEIGHT
|
||||
#else
|
||||
. = (O.x - source_turf.x + O.xoffset)**2 + (O.y - source_turf.y + O.yoffset)**2 + LIGHTING_HEIGHT
|
||||
#endif
|
||||
|
||||
#if LIGHTING_LAMBERTIAN == 1
|
||||
. = CLAMP01((1 - CLAMP01(sqrt(.) / light_range)) * (1 / (sqrt(. + 1))))
|
||||
@@ -126,11 +125,7 @@
|
||||
#endif
|
||||
|
||||
#elif LIGHTING_FALLOFF == 2 // square
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
. = abs(O.x - source_turf.x) + abs(O.y - source_turf.y) + LIGHTING_HEIGHT
|
||||
#else
|
||||
. = abs(O.x - source_turf.x + O.xoffset) + abs(O.y - source_turf.y + O.yoffset) + LIGHTING_HEIGHT
|
||||
#endif
|
||||
|
||||
#if LIGHTING_LAMBERTIAN == 1
|
||||
. = CLAMP01((1 - CLAMP01(. / light_range)) * (1 / (sqrt(.)**2 + )))
|
||||
@@ -142,26 +137,36 @@
|
||||
/datum/light_source/proc/apply_lum()
|
||||
applied = 1
|
||||
if(istype(source_turf))
|
||||
for(var/atom/movable/lighting_overlay/O in view(light_range, source_turf))
|
||||
var/strength = light_power * falloff(O)
|
||||
for(var/turf/T in dview(light_range, source_turf, INVISIBILITY_LIGHTING))
|
||||
if(T.lighting_overlay)
|
||||
var/strength = light_power * falloff(T.lighting_overlay)
|
||||
if(!strength) //Don't add turfs that aren't affected to the affected turfs.
|
||||
continue
|
||||
|
||||
effect_r[O] = lum_r * strength
|
||||
effect_g[O] = lum_g * strength
|
||||
effect_b[O] = lum_b * strength
|
||||
effect_r[T.lighting_overlay] = round(lum_r * strength, LIGHTING_ROUND_VALUE)
|
||||
effect_g[T.lighting_overlay] = round(lum_g * strength, LIGHTING_ROUND_VALUE)
|
||||
effect_b[T.lighting_overlay] = round(lum_b * strength, LIGHTING_ROUND_VALUE)
|
||||
|
||||
T.lighting_overlay.update_lumcount(
|
||||
round(lum_r * strength, LIGHTING_ROUND_VALUE),
|
||||
round(lum_g * strength, LIGHTING_ROUND_VALUE),
|
||||
round(lum_b * strength, LIGHTING_ROUND_VALUE)
|
||||
)
|
||||
|
||||
if(!T.affecting_lights)
|
||||
T.affecting_lights = list()
|
||||
|
||||
O.update_lumcount(lum_r * strength, lum_g * strength, lum_b * strength)
|
||||
for(var/turf/T in view(light_range, source_turf))
|
||||
if(!T.affecting_lights) T.affecting_lights = list()
|
||||
T.affecting_lights += src
|
||||
effect_turf += T
|
||||
|
||||
/datum/light_source/proc/remove_lum()
|
||||
applied = 0
|
||||
for(var/atom/movable/lighting_overlay/O in effect_r)
|
||||
O.update_lumcount(-effect_r[O], -effect_g[O], -effect_b[O])
|
||||
|
||||
for(var/turf/T in effect_turf)
|
||||
if(T.affecting_lights) T.affecting_lights -= src
|
||||
if(T.affecting_lights)
|
||||
T.affecting_lights -= src
|
||||
|
||||
if(T.lighting_overlay)
|
||||
T.lighting_overlay.update_lumcount(-effect_r[T.lighting_overlay], -effect_g[T.lighting_overlay], -effect_b[T.lighting_overlay])
|
||||
|
||||
effect_r.Cut()
|
||||
effect_g.Cut()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
anchored = 1
|
||||
|
||||
icon = LIGHTING_ICON
|
||||
icon_state = "light1"
|
||||
layer = LIGHTING_LAYER
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
blend_mode = BLEND_MULTIPLY
|
||||
@@ -14,24 +15,42 @@
|
||||
var/lum_g
|
||||
var/lum_b
|
||||
|
||||
#if LIGHTING_RESOLUTION != 1
|
||||
var/xoffset
|
||||
var/yoffset
|
||||
#endif
|
||||
|
||||
var/needs_update
|
||||
|
||||
/atom/movable/lighting_overlay/New()
|
||||
. = ..()
|
||||
verbs.Cut()
|
||||
|
||||
var/turf/T = loc //If this runtimes atleast we'll know what's creating overlays in things that aren't turfs.
|
||||
T.luminosity = 0
|
||||
|
||||
/atom/movable/lighting_overlay/proc/update_lumcount(delta_r, delta_g, delta_b)
|
||||
if(!delta_r && !delta_g && !delta_b) //Nothing is being changed all together.
|
||||
return
|
||||
|
||||
var/should_update = 0
|
||||
|
||||
if(!needs_update) //If this isn't true, we're already updating anyways.
|
||||
if(max(lum_r, lum_g, lum_b) < 1) //Any change that could happen WILL change appearance.
|
||||
should_update = 1
|
||||
|
||||
else if(max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b) < 1) //The change would bring us under 1 max lum, again, guaranteed to change appearance.
|
||||
should_update = 1
|
||||
|
||||
else //We need to make sure that the colour ratios won't change in this code block.
|
||||
var/mx1 = max(lum_r, lum_g, lum_b)
|
||||
var/mx2 = max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b)
|
||||
|
||||
if(lum_r / mx1 != (lum_r + delta_r) / mx2 || lum_g / mx1 != (lum_g + delta_g) / mx2 || lum_b / mx1 != (lum_b + delta_b) / mx2) //Stuff would change.
|
||||
should_update = 1
|
||||
|
||||
lum_r += delta_r
|
||||
lum_g += delta_g
|
||||
lum_b += delta_b
|
||||
|
||||
needs_update = 1
|
||||
lighting_update_overlays += src
|
||||
if(!needs_update && should_update)
|
||||
needs_update = 1
|
||||
lighting_update_overlays += src
|
||||
|
||||
/atom/movable/lighting_overlay/proc/update_overlay()
|
||||
var/mx = max(lum_r, lum_g, lum_b)
|
||||
@@ -46,3 +65,43 @@
|
||||
#else
|
||||
color = rgb(lum_r * 255 * ., lum_g * 255 * ., lum_b * 255 * .)
|
||||
#endif
|
||||
|
||||
var/turf/T = loc
|
||||
|
||||
if(istype(T)) //Incase we're not on a turf, pool ourselves, something happened.
|
||||
if(color != "#000000")
|
||||
T.luminosity = 1
|
||||
else //No light, set the turf's luminosity to 0 to remove it from view()
|
||||
#if LIGHTING_TRANSITIONS == 1
|
||||
spawn(LIGHTING_INTERVAL - 1)
|
||||
T.luminosity = 0
|
||||
#else
|
||||
T.luminosity = 0
|
||||
#endif
|
||||
|
||||
else
|
||||
warning("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : ""]) in update_overlay() and got pooled!")
|
||||
qdel(src)
|
||||
|
||||
/atom/movable/lighting_overlay/ResetVars()
|
||||
loc = null
|
||||
|
||||
lum_r = 0
|
||||
lum_g = 0
|
||||
lum_b = 0
|
||||
|
||||
color = "#000000"
|
||||
|
||||
needs_update = 0
|
||||
|
||||
/atom/movable/lighting_overlay/Destroy()
|
||||
lighting_update_overlays -= src
|
||||
|
||||
var/turf/T = loc
|
||||
if(istype(T))
|
||||
T.lighting_overlay = null
|
||||
|
||||
for(var/datum/light_source/D in T.affecting_lights) //Remove references to us on the light sources affecting us.
|
||||
D.effect_r -= src
|
||||
D.effect_g -= src
|
||||
D.effect_b -= src
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
/datum/controller/process/lighting/setup()
|
||||
name = "lighting"
|
||||
schedule_interval = LIGHTING_INTERVAL
|
||||
|
||||
create_lighting_overlays()
|
||||
|
||||
/datum/controller/process/lighting/doWork()
|
||||
for(var/datum/light_source/L in lighting_update_lights)
|
||||
if(L.needs_update)
|
||||
if(L.destroyed || L.check() || L.force_update)
|
||||
L.remove_lum()
|
||||
if(!L.destroyed) L.apply_lum()
|
||||
L.force_update = 0
|
||||
L.needs_update = 0
|
||||
|
||||
scheck()
|
||||
|
||||
lighting_update_lights.Cut()
|
||||
|
||||
for(var/atom/movable/lighting_overlay/O in lighting_update_overlays)
|
||||
if(O.needs_update)
|
||||
O.update_overlay()
|
||||
O.needs_update = 0
|
||||
|
||||
scheck()
|
||||
|
||||
lighting_update_overlays.Cut()
|
||||
/datum/controller/process/lighting/setup()
|
||||
name = "lighting"
|
||||
schedule_interval = LIGHTING_INTERVAL
|
||||
|
||||
create_lighting_overlays()
|
||||
|
||||
/datum/controller/process/lighting/doWork()
|
||||
var/list/lighting_update_lights_old = lighting_update_lights //We use a different list so any additions to the update lists during a delay from scheck() don't cause things to be cut from the list without being updated.
|
||||
lighting_update_lights = null //Nulling it first because of http://www.byond.com/forum/?post=1854520
|
||||
lighting_update_lights = list()
|
||||
|
||||
for(var/datum/light_source/L in lighting_update_lights_old)
|
||||
if(L.needs_update)
|
||||
if(L.destroyed || L.check() || L.force_update)
|
||||
L.remove_lum()
|
||||
if(!L.destroyed) L.apply_lum()
|
||||
L.force_update = 0
|
||||
L.needs_update = 0
|
||||
|
||||
scheck()
|
||||
|
||||
var/list/lighting_update_overlays_old = lighting_update_overlays //Same as above.
|
||||
lighting_update_overlays = null //Same as above
|
||||
lighting_update_overlays = list()
|
||||
|
||||
for(var/atom/movable/lighting_overlay/O in lighting_update_overlays_old)
|
||||
if(O.needs_update)
|
||||
O.update_overlay()
|
||||
O.needs_update = 0
|
||||
|
||||
scheck()
|
||||
|
||||
@@ -5,26 +5,15 @@
|
||||
|
||||
// duplicates lots of code, but this proc needs to be as fast as possible.
|
||||
/proc/create_lighting_overlays(zlevel = 0)
|
||||
var/state = "light[LIGHTING_RESOLUTION]"
|
||||
var/area/A
|
||||
if(zlevel == 0) // populate all zlevels
|
||||
for(var/turf/T in world)
|
||||
if(T.dynamic_lighting)
|
||||
A = T.loc
|
||||
if(A.lighting_use_dynamic)
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
var/atom/movable/lighting_overlay/O = new(T)
|
||||
O.icon_state = state
|
||||
#else
|
||||
for(var/i = 0; i < LIGHTING_RESOLUTION; i++)
|
||||
for(var/j = 0; j < LIGHTING_RESOLUTION; j++)
|
||||
var/atom/movable/lighting_overlay/O = new(T)
|
||||
O.pixel_x = i * (32 / LIGHTING_RESOLUTION)
|
||||
O.pixel_y = j * (32 / LIGHTING_RESOLUTION)
|
||||
O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.icon_state = state
|
||||
#endif
|
||||
var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, T)
|
||||
T.lighting_overlay = O
|
||||
|
||||
else
|
||||
for(var/x = 1; x <= world.maxx; x++)
|
||||
for(var/y = 1; y <= world.maxy; y++)
|
||||
@@ -32,16 +21,5 @@
|
||||
if(T.dynamic_lighting)
|
||||
A = T.loc
|
||||
if(A.lighting_use_dynamic)
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
var/atom/movable/lighting_overlay/O = new(T)
|
||||
O.icon_state = state
|
||||
#else
|
||||
for(var/i = 0; i < LIGHTING_RESOLUTION; i++)
|
||||
for(var/j = 0; j < LIGHTING_RESOLUTION; j++)
|
||||
var/atom/movable/lighting_overlay/O = new(T)
|
||||
O.pixel_x = i * (32 / LIGHTING_RESOLUTION)
|
||||
O.pixel_y = j * (32 / LIGHTING_RESOLUTION)
|
||||
O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.icon_state = state
|
||||
#endif
|
||||
var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, T)
|
||||
T.lighting_overlay = O
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
/turf
|
||||
var/list/affecting_lights
|
||||
var/atom/movable/lighting_overlay/lighting_overlay
|
||||
|
||||
/turf/proc/reconsider_lights()
|
||||
for(var/datum/light_source/L in affecting_lights)
|
||||
L.force_update()
|
||||
|
||||
/turf/proc/lighting_clear_overlays()
|
||||
for(var/atom/movable/lighting_overlay/L in src)
|
||||
L.loc = null
|
||||
if(lighting_overlay)
|
||||
qdel(lighting_overlay)
|
||||
|
||||
/turf/proc/lighting_build_overlays()
|
||||
if(!locate(/atom/movable/lighting_overlay) in src)
|
||||
var/state = "light[LIGHTING_RESOLUTION]"
|
||||
if(!lighting_overlay)
|
||||
var/area/A = loc
|
||||
if(A.lighting_use_dynamic)
|
||||
#if LIGHTING_RESOLUTION == 1
|
||||
var/atom/movable/lighting_overlay/O = new(src)
|
||||
O.icon_state = state
|
||||
#else
|
||||
for(var/i = 0; i < LIGHTING_RESOLUTION; i++)
|
||||
for(var/j = 0; j < LIGHTING_RESOLUTION; j++)
|
||||
var/atom/movable/lighting_overlay/O = new(src)
|
||||
O.pixel_x = i * (32 / LIGHTING_RESOLUTION)
|
||||
O.pixel_y = j * (32 / LIGHTING_RESOLUTION)
|
||||
O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
|
||||
O.icon_state = state
|
||||
#endif
|
||||
var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, src)
|
||||
lighting_overlay = O
|
||||
|
||||
@@ -340,8 +340,8 @@
|
||||
R.amount = rand(5,25)
|
||||
|
||||
if(2)
|
||||
var/obj/item/stack/tile/R = new(src)
|
||||
R.amount = rand(1,5)
|
||||
var/obj/item/stack/material/plasteel/R = new(src)
|
||||
R.amount = rand(5,25)
|
||||
|
||||
if(3)
|
||||
var/obj/item/stack/material/steel/R = new(src)
|
||||
|
||||
@@ -852,11 +852,11 @@ var/global/list/damage_icon_parts = list()
|
||||
|
||||
//determine icon to use
|
||||
var/icon/t_icon
|
||||
if(r_hand.icon_override)
|
||||
if(r_hand.item_icons && (slot_r_hand_str in r_hand.item_icons))
|
||||
t_icon = r_hand.item_icons[slot_r_hand_str]
|
||||
else if(r_hand.icon_override)
|
||||
t_state += "_r"
|
||||
t_icon = r_hand.icon_override
|
||||
else if(r_hand.item_icons && (slot_r_hand_str in r_hand.item_icons))
|
||||
t_icon = r_hand.item_icons[slot_r_hand_str]
|
||||
else
|
||||
t_icon = INV_R_HAND_DEF_ICON
|
||||
|
||||
@@ -884,11 +884,11 @@ var/global/list/damage_icon_parts = list()
|
||||
|
||||
//determine icon to use
|
||||
var/icon/t_icon
|
||||
if(l_hand.icon_override)
|
||||
if(l_hand.item_icons && (slot_l_hand_str in l_hand.item_icons))
|
||||
t_icon = l_hand.item_icons[slot_l_hand_str]
|
||||
else if(l_hand.icon_override)
|
||||
t_state += "_l"
|
||||
t_icon = l_hand.icon_override
|
||||
else if(l_hand.item_icons && (slot_l_hand_str in l_hand.item_icons))
|
||||
t_icon = l_hand.item_icons[slot_l_hand_str]
|
||||
else
|
||||
t_icon = INV_L_HAND_DEF_ICON
|
||||
|
||||
|
||||
@@ -200,9 +200,12 @@
|
||||
if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
|
||||
if(Friends.len > 0 && prob(1))
|
||||
var/mob/nofriend = pick(Friends)
|
||||
--Friends[nofriend]
|
||||
if (Friends[nofriend] <= 0)
|
||||
Friends -= nofriend
|
||||
if(nofriend && Friends[nofriend])
|
||||
Friends[nofriend] -= 1
|
||||
if (Friends[nofriend] <= 0)
|
||||
Friends[nofriend] = null
|
||||
Friends -= nofriend
|
||||
Friends -= null
|
||||
|
||||
if(!Target)
|
||||
if(will_hunt(hungry) || attacked || rabid) // Only add to the list if we need to
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
return "I cannot feed on other slimes..."
|
||||
if (!Adjacent(M))
|
||||
return "This subject is too far away..."
|
||||
if (istype(M, /mob/living/carbon) && M.getCloneLoss() > 150 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
|
||||
if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.maxHealth * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
|
||||
return "This subject does not have an edible life energy..."
|
||||
for(var/mob/living/carbon/slime/met in view())
|
||||
if(met.Victim == M && met != src)
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
return
|
||||
|
||||
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
|
||||
fire_stacks = Clamp(fire_stacks + add_fire_stacks, min = FIRE_MIN_STACKS, max = FIRE_MAX_STACKS)
|
||||
fire_stacks = Clamp(fire_stacks + add_fire_stacks, FIRE_MIN_STACKS, FIRE_MAX_STACKS)
|
||||
|
||||
/mob/living/proc/handle_fire()
|
||||
if(fire_stacks < 0)
|
||||
|
||||
@@ -212,6 +212,7 @@
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/proc/check_horde()
|
||||
return 0
|
||||
if(emergency_shuttle.shuttle.location)
|
||||
if(!enroute && !target_mob) //The shuttle docked, all monsters rush for the escape hallway
|
||||
if(!shuttletarget && escape_list.len) //Make sure we didn't already assign it a target, and that there are targets to pick
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
/****************************************************
|
||||
EXTERNAL ORGANS
|
||||
****************************************************/
|
||||
|
||||
//These control the damage thresholds for the various ways of removing limbs
|
||||
#define DROPLIMB_THRESHOLD_EDGE 5
|
||||
#define DROPLIMB_THRESHOLD_TEAROFF 2
|
||||
#define DROPLIMB_THRESHOLD_DESTROY 1
|
||||
|
||||
/obj/item/organ/external
|
||||
name = "external"
|
||||
min_broken_damage = 30
|
||||
@@ -233,6 +239,7 @@
|
||||
//If we can't inflict the full amount of damage, spread the damage in other ways
|
||||
//How much damage can we actually cause?
|
||||
var/can_inflict = max_damage * config.organ_health_multiplier - (brute_dam + burn_dam)
|
||||
var/spillover = 0
|
||||
if(can_inflict)
|
||||
if (brute > 0)
|
||||
//Inflict all burte damage we can
|
||||
@@ -244,16 +251,17 @@
|
||||
//How much mroe damage can we inflict
|
||||
can_inflict = max(0, can_inflict - brute)
|
||||
//How much brute damage is left to inflict
|
||||
brute = max(0, brute - temp)
|
||||
spillover += max(0, brute - temp)
|
||||
|
||||
if (burn > 0 && can_inflict)
|
||||
//Inflict all burn damage we can
|
||||
createwound(BURN, min(burn,can_inflict))
|
||||
//How much burn damage is left to inflict
|
||||
burn = max(0, burn - can_inflict)
|
||||
spillover += max(0, burn - can_inflict)
|
||||
|
||||
//If there are still hurties to dispense
|
||||
if (burn || brute)
|
||||
owner.shock_stage += (brute+burn) * config.organ_damage_spillover_multiplier
|
||||
if (spillover)
|
||||
owner.shock_stage += spillover * config.organ_damage_spillover_multiplier
|
||||
|
||||
// sync the organ's damage with its wounds
|
||||
src.update_damages()
|
||||
@@ -262,26 +270,30 @@
|
||||
//If limb took enough damage, try to cut or tear it off
|
||||
if(owner && loc == owner)
|
||||
if(!cannot_amputate && config.limbs_can_break && (brute_dam + burn_dam) >= (max_damage * config.organ_health_multiplier))
|
||||
var/threshold = max_damage
|
||||
var/dropped
|
||||
if((burn >= threshold) && prob(burn/3))
|
||||
dropped = 1
|
||||
droplimb(0,DROPLIMB_BURN)
|
||||
if(!dropped && prob(brute))
|
||||
var/edge_eligible = 0
|
||||
if(edge)
|
||||
if(istype(used_weapon,/obj/item))
|
||||
var/obj/item/W = used_weapon
|
||||
if(W.w_class >= w_class)
|
||||
edge_eligible = 1
|
||||
else
|
||||
//organs can come off in three cases
|
||||
//1. If the damage source is edge_eligible and the brute damage dealt exceeds the edge threshold, then the organ is cut off.
|
||||
//2. If the damage amount dealt exceeds the disintegrate threshold, the organ is completely obliterated.
|
||||
//3. If the organ has already reached or would be put over it's max damage amount (currently redundant),
|
||||
// and the brute damage dealt exceeds the tearoff threshold, the organ is torn off.
|
||||
|
||||
//Check edge eligibility
|
||||
var/edge_eligible = 0
|
||||
if(edge)
|
||||
if(istype(used_weapon,/obj/item))
|
||||
var/obj/item/W = used_weapon
|
||||
if(W.w_class >= w_class)
|
||||
edge_eligible = 1
|
||||
else
|
||||
edge_eligible = 1
|
||||
|
||||
if(brute >= threshold || (edge_eligible && brute >= threshold/3))
|
||||
if(edge)
|
||||
droplimb(0,DROPLIMB_EDGE)
|
||||
else
|
||||
droplimb(0,DROPLIMB_BLUNT)
|
||||
if(edge_eligible && brute >= max_damage / DROPLIMB_THRESHOLD_EDGE && prob(brute))
|
||||
droplimb(0, DROPLIMB_EDGE)
|
||||
else if(burn >= max_damage / DROPLIMB_THRESHOLD_DESTROY && prob(burn/3))
|
||||
droplimb(0, DROPLIMB_BURN)
|
||||
else if(brute >= max_damage / DROPLIMB_THRESHOLD_DESTROY && prob(brute))
|
||||
droplimb(0, DROPLIMB_BLUNT)
|
||||
else if(brute >= max_damage / DROPLIMB_THRESHOLD_TEAROFF && prob(brute/3))
|
||||
droplimb(0, DROPLIMB_EDGE)
|
||||
|
||||
return update_icon()
|
||||
|
||||
@@ -709,11 +721,7 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
|
||||
wounds.Cut()
|
||||
if(parent)
|
||||
var/datum/wound/W
|
||||
if(clean || max_damage < 50)
|
||||
W = new/datum/wound/lost_limb/small(max_damage/2)
|
||||
else
|
||||
W = new/datum/wound/lost_limb(max_damage)
|
||||
var/datum/wound/lost_limb/W = new (src, disintegrate, clean)
|
||||
parent.children -= src
|
||||
if(clean)
|
||||
parent.wounds |= W
|
||||
@@ -752,7 +760,7 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
I.loc = get_turf(src)
|
||||
qdel(src)
|
||||
if(DROPLIMB_BLUNT)
|
||||
var/obj/effect/decal/cleanable/blood/gibs/gore = new owner.species.single_gib_type(get_turf(victim))
|
||||
var/obj/effect/decal/cleanable/blood/gibs/gore = new victim.species.single_gib_type(get_turf(victim))
|
||||
if(victim.species.flesh_color)
|
||||
gore.fleshcolor = victim.species.flesh_color
|
||||
if(victim.species.blood_color)
|
||||
|
||||
@@ -315,12 +315,32 @@ datum/wound/cut/massive
|
||||
|
||||
/** EXTERNAL ORGAN LOSS **/
|
||||
/datum/wound/lost_limb
|
||||
damage_type = CUT
|
||||
stages = list("ripped stump" = 65, "bloody stump" = 50, "clotted stump" = 25, "scarred stump" = 0)
|
||||
max_bleeding_stage = 3
|
||||
|
||||
can_merge(var/datum/wound/other)
|
||||
return 0 //cannot be merged
|
||||
/datum/wound/lost_limb/New(var/obj/item/organ/external/lost_limb, var/losstype, var/clean)
|
||||
var/damage_amt = lost_limb.max_damage
|
||||
if(clean) damage_amt /= 2
|
||||
|
||||
switch(losstype)
|
||||
if(DROPLIMB_EDGE, DROPLIMB_BLUNT)
|
||||
damage_type = CUT
|
||||
max_bleeding_stage = 3
|
||||
stages = list(
|
||||
"ripped stump" = damage_amt*1.3,
|
||||
"bloody stump" = damage_amt,
|
||||
"clotted stump" = damage_amt*0.5,
|
||||
"scarred stump" = 0
|
||||
)
|
||||
if(DROPLIMB_BURN)
|
||||
damage_type = BURN
|
||||
max_bleeding_stage = 1
|
||||
stages = list(
|
||||
"ripped charred stump" = damage_amt*1.3,
|
||||
"charred stump" = damage_amt,
|
||||
"scarred stump" = damage_amt*0.5,
|
||||
"scarred stump" = 0
|
||||
)
|
||||
|
||||
..(damage_amt)
|
||||
|
||||
/datum/wound/lost_limb/small
|
||||
stages = list("ripped hole" = 40, "bloody hole" = 30, "clotted hole" = 15, "scarred hole" = 0)
|
||||
/datum/wound/lost_limb/can_merge(var/datum/wound/other)
|
||||
return 0 //cannot be merged
|
||||
@@ -11,8 +11,8 @@
|
||||
if(istype(M))
|
||||
transform = M
|
||||
|
||||
/obj/effect/projectile/proc/activate()
|
||||
spawn(3)
|
||||
/obj/effect/projectile/proc/activate(var/kill_delay = 3)
|
||||
spawn(kill_delay)
|
||||
qdel(src) //see effect_system.dm - sets loc to null and lets GC handle removing these effects
|
||||
|
||||
return
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
var/dispersion = 0.0
|
||||
|
||||
var/damage = 10
|
||||
var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here
|
||||
var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, HALLOSS are the only things that should be in here
|
||||
var/nodamage = 0 //Determines if the projectile will skip any damage inflictions
|
||||
var/taser_effect = 0 //If set then the projectile will apply it's agony damage using stun_effect_act() to mobs it hits, and other damage will be ignored
|
||||
var/check_armour = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid
|
||||
@@ -296,25 +296,26 @@
|
||||
before_move()
|
||||
Move(location.return_turf())
|
||||
|
||||
if(first_step)
|
||||
muzzle_effect(effect_transform)
|
||||
first_step = 0
|
||||
else
|
||||
tracer_effect(effect_transform)
|
||||
|
||||
if(!bumped && !isturf(original))
|
||||
if(loc == get_turf(original))
|
||||
if(!(original in permutated))
|
||||
if(Bump(original))
|
||||
return
|
||||
|
||||
if(first_step)
|
||||
muzzle_effect(effect_transform)
|
||||
first_step = 0
|
||||
else if(!bumped)
|
||||
tracer_effect(effect_transform)
|
||||
|
||||
if(!hitscan)
|
||||
sleep(step_delay) //add delay between movement iterations if it's not a hitscan weapon
|
||||
|
||||
/obj/item/projectile/proc/process_step(first_step = 0)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/projectile/proc/before_move()
|
||||
return
|
||||
|
||||
/obj/item/projectile/proc/setup_trajectory()
|
||||
// trajectory dispersion
|
||||
@@ -332,6 +333,8 @@
|
||||
effect_transform.Scale(trajectory.return_hypotenuse(), 1)
|
||||
effect_transform.Turn(-trajectory.return_angle()) //no idea why this has to be inverted, but it works
|
||||
|
||||
transform = turn(transform, -(trajectory.return_angle() + 90)) //no idea why 90 needs to be added, but it works
|
||||
|
||||
/obj/item/projectile/proc/muzzle_effect(var/matrix/T)
|
||||
if(silenced)
|
||||
return
|
||||
@@ -353,7 +356,10 @@
|
||||
P.set_transform(M)
|
||||
P.pixel_x = location.pixel_x
|
||||
P.pixel_y = location.pixel_y
|
||||
P.activate()
|
||||
if(!hitscan)
|
||||
P.activate(step_delay) //if not a hitscan projectile, remove after a single delay
|
||||
else
|
||||
P.activate()
|
||||
|
||||
/obj/item/projectile/proc/impact_effect(var/matrix/M)
|
||||
if(ispath(tracer_type))
|
||||
@@ -379,7 +385,7 @@
|
||||
return //cannot shoot yourself
|
||||
if(istype(A, /obj/item/projectile))
|
||||
return
|
||||
if(istype(A, /mob/living))
|
||||
if(istype(A, /mob/living) || istype(A, /obj/mecha) || istype(A, /obj/vehicle))
|
||||
result = 2 //We hit someone, return 1!
|
||||
return
|
||||
result = 1
|
||||
@@ -418,15 +424,14 @@
|
||||
if(istype(M))
|
||||
return 1
|
||||
|
||||
/proc/check_trajectory(atom/target as mob, var/mob/living/user as mob, var/pass_flags=PASSTABLE|PASSGLASS|PASSGRILLE, flags=null) //Checks if you can hit them or not.
|
||||
if(!istype(target) || !istype(user))
|
||||
/proc/check_trajectory(atom/target as mob|obj, atom/firer as mob|obj, var/pass_flags=PASSTABLE|PASSGLASS|PASSGRILLE, flags=null) //Checks if you can hit them or not.
|
||||
if(!istype(target) || !istype(firer))
|
||||
return 0
|
||||
var/obj/item/projectile/test/trace = new /obj/item/projectile/test(get_step_to(user,target)) //Making the test....
|
||||
var/obj/item/projectile/test/trace = new /obj/item/projectile/test(get_turf(firer)) //Making the test....
|
||||
trace.target = target
|
||||
if(!isnull(flags))
|
||||
trace.flags = flags //Set the flags...
|
||||
trace.pass_flags = pass_flags //And the pass flags to that of the real projectile...
|
||||
trace.firer = user
|
||||
var/output = trace.process() //Test it!
|
||||
qdel(trace) //No need for it anymore
|
||||
return output //Send it back to the gun!
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
eyeblur = 4
|
||||
var/frequency = 1
|
||||
hitscan = 1
|
||||
invisibility = 101 //beam projectiles are invisible as they are rendered by the effect engine
|
||||
|
||||
muzzle_type = /obj/effect/projectile/laser/muzzle
|
||||
tracer_type = /obj/effect/projectile/laser/tracer
|
||||
|
||||
@@ -261,6 +261,7 @@
|
||||
|
||||
//These are called by the on-screen buttons, adjusting what the victim can and cannot do.
|
||||
/client/proc/add_gun_icons()
|
||||
if(!usr) return 1 // This can runtime if someone manages to throw a gun out of their hand before the proc is called.
|
||||
screen += usr.item_use_icon
|
||||
screen += usr.gun_move_icon
|
||||
screen += usr.radio_use_icon
|
||||
|
||||
@@ -95,8 +95,9 @@
|
||||
// attack with item, place item on conveyor
|
||||
/obj/machinery/conveyor/attackby(var/obj/item/I, mob/user)
|
||||
if(isrobot(user)) return //Carn: fix for borgs dropping their modules on conveyor belts
|
||||
user.drop_item()
|
||||
if(I && I.loc) I.loc = src.loc
|
||||
if(I.loc != user) return // This should stop mounted modules ending up outside the module.
|
||||
|
||||
user.drop_item(src)
|
||||
return
|
||||
|
||||
// attack with hand, move pulled object onto conveyor
|
||||
|
||||
@@ -176,6 +176,10 @@
|
||||
user << "<span class='warning'>Plate \the [src] before reinforcing it!</span>"
|
||||
return
|
||||
|
||||
if(flipped)
|
||||
user << "<span class='warning'>Put \the [src] back in place before reinforcing it!</span>"
|
||||
return
|
||||
|
||||
reinforced = common_material_add(S, user, "reinforc")
|
||||
if(reinforced)
|
||||
update_desc()
|
||||
|
||||
@@ -79,6 +79,13 @@
|
||||
return
|
||||
..()
|
||||
|
||||
//cargo trains are open topped, so there is a chance the projectile will hit the mob ridding the train instead
|
||||
/obj/vehicle/train/cargo/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(buckled_mob && prob(70))
|
||||
buckled_mob.bullet_act(Proj)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/vehicle/train/cargo/update_icon()
|
||||
if(open)
|
||||
icon_state = initial(icon_state) + "_open"
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
//uniqueID = rand(0,10000)
|
||||
var/datum/disease2/effectholder/holder = pick(effects)
|
||||
holder.minormutate()
|
||||
infectionchance = min(50,infectionchance + rand(0,10))
|
||||
//infectionchance = min(50,infectionchance + rand(0,10))
|
||||
|
||||
/datum/disease2/disease/proc/majormutate()
|
||||
uniqueID = rand(0,10000)
|
||||
|
||||
@@ -51,7 +51,7 @@ proc/infection_check(var/mob/living/carbon/M, var/vector = "Airborne")
|
||||
if (vector == "Airborne")
|
||||
var/obj/item/I = M.wear_mask
|
||||
if (istype(I))
|
||||
protection = max(protection, round(0.06*I.armor["bio"]))
|
||||
protection = max(protection, I.armor["bio"])
|
||||
|
||||
return prob(protection)
|
||||
|
||||
@@ -148,12 +148,12 @@ proc/airborne_can_reach(turf/source, turf/target)
|
||||
// log_debug("Could not reach target")
|
||||
|
||||
if (vector == "Contact")
|
||||
if (in_range(src, victim))
|
||||
if (Adjacent(victim))
|
||||
// log_debug("In range, infecting")
|
||||
infect_virus2(victim,V)
|
||||
|
||||
//contact goes both ways
|
||||
if (victim.virus2.len > 0 && vector == "Contact")
|
||||
if (victim.virus2.len > 0 && vector == "Contact" && Adjacent(victim))
|
||||
// log_debug("Spreading [vector] diseases from [victim] to [src]")
|
||||
var/nudity = 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user