mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-15 09:03:53 +01:00
Merge branch 'master' into Arokha/machinerybreak
This commit is contained in:
@@ -1609,7 +1609,7 @@ datum/admins/var/obj/item/weapon/paper/admin/faxreply // var to hold fax replies
|
||||
if(!P.stamped)
|
||||
P.stamped = new
|
||||
P.stamped += /obj/item/weapon/stamp/centcomm
|
||||
P.overlays += stampoverlay
|
||||
P.add_overlay(stampoverlay)
|
||||
|
||||
var/obj/item/rcvdcopy
|
||||
rcvdcopy = destination.copy(P)
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
|
||||
if(path_display)
|
||||
var/turf/T = src.path[1]
|
||||
T.overlays -= path_overlay
|
||||
T.cut_overlay(path_overlay)
|
||||
|
||||
// step_towards(holder, src.path[1])
|
||||
if(holder.IMove(get_step_towards(holder, src.path[1])) != MOVEMENT_ON_COOLDOWN)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
ai_log("forget_path() : Entering.", AI_LOG_DEBUG)
|
||||
if(path_display)
|
||||
for(var/turf/T in path)
|
||||
T.overlays -= path_overlay
|
||||
T.cut_overlay(path_overlay)
|
||||
path.Cut()
|
||||
ai_log("forget_path() : Exiting.", AI_LOG_DEBUG)
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
ai_log("get_path() : Made new path.",AI_LOG_DEBUG)
|
||||
if(path_display)
|
||||
for(var/turf/T in path)
|
||||
T.overlays |= path_overlay
|
||||
T.add_overlay(path_overlay)
|
||||
else
|
||||
ai_log("get_path() : Failed to make new path. Exiting.",AI_LOG_DEBUG)
|
||||
return 0
|
||||
|
||||
@@ -222,17 +222,17 @@
|
||||
lose_target_position()
|
||||
|
||||
if(last_turf_display && target_last_seen_turf)
|
||||
target_last_seen_turf.overlays -= last_turf_overlay
|
||||
target_last_seen_turf.cut_overlay(last_turf_overlay)
|
||||
|
||||
target_last_seen_turf = get_turf(target)
|
||||
|
||||
if(last_turf_display)
|
||||
target_last_seen_turf.overlays += last_turf_overlay
|
||||
target_last_seen_turf.add_overlay(last_turf_overlay)
|
||||
|
||||
// Resets the last known position to null.
|
||||
/datum/ai_holder/proc/lose_target_position()
|
||||
if(last_turf_display && target_last_seen_turf)
|
||||
target_last_seen_turf.overlays -= last_turf_overlay
|
||||
target_last_seen_turf.cut_overlay(last_turf_overlay)
|
||||
ai_log("lose_target_position() : Last position is being reset.", AI_LOG_INFO)
|
||||
target_last_seen_turf = null
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
/obj/item/weapon/telecube/proc/teleport_to_mate(var/atom/movable/A, var/areaporting = FALSE)
|
||||
. = FALSE
|
||||
|
||||
if(!A)
|
||||
if(!istype(A))
|
||||
return .
|
||||
|
||||
if(A == src || A == mate)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "A small electronic device able to ignite combustable substances."
|
||||
icon_state = "igniter"
|
||||
origin_tech = list(TECH_MAGNET = 1)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 50, "waste" = 10)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 500, MAT_GLASS = 50)
|
||||
|
||||
secured = 1
|
||||
wires = WIRE_RECEIVE
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted."
|
||||
icon_state = "infrared"
|
||||
origin_tech = list(TECH_MAGNET = 2)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 1000, "glass" = 500, "waste" = 100)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 1000, MAT_GLASS = 500)
|
||||
|
||||
wires = WIRE_PULSE
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "A handy little spring-loaded trap for catching pesty rodents."
|
||||
icon_state = "mousetrap"
|
||||
origin_tech = list(TECH_COMBAT = 1)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 100, "waste" = 10)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 100)
|
||||
var/armed = 0
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "Used for scanning and alerting when someone enters a certain proximity."
|
||||
icon_state = "prox"
|
||||
origin_tech = list(TECH_MAGNET = 1)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 800, "glass" = 200, "waste" = 50)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 800, MAT_GLASS = 200)
|
||||
wires = WIRE_PULSE
|
||||
|
||||
secured = 0
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
icon_state = "signaller"
|
||||
item_state = "signaler"
|
||||
origin_tech = list(TECH_MAGNET = 1)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 1000, "glass" = 200, "waste" = 100)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 1000, MAT_GLASS = 200)
|
||||
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
|
||||
|
||||
secured = TRUE
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "Used to time things. Works well with contraptions which has to count down. Tick tock."
|
||||
icon_state = "timer"
|
||||
origin_tech = list(TECH_MAGNET = 1)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 50, "waste" = 10)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 500, MAT_GLASS = 50)
|
||||
|
||||
wires = WIRE_PULSE
|
||||
|
||||
@@ -53,10 +53,10 @@
|
||||
time = 10
|
||||
|
||||
/obj/item/device/assembly/timer/update_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
attached_overlays = list()
|
||||
if(timing)
|
||||
overlays += "timer_timing"
|
||||
add_overlay("timer_timing")
|
||||
attached_overlays += "timer_timing"
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "A small electronic device able to record a voice sample, and send a signal when that sample is repeated."
|
||||
icon_state = "voice"
|
||||
origin_tech = list(TECH_MAGNET = 1)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 50, "waste" = 10)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 500, MAT_GLASS = 50)
|
||||
var/listening = 0
|
||||
var/recorded //the activation message
|
||||
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
/datum/asset/simple/tgui_common
|
||||
// keep_local_name = TRUE
|
||||
assets = list(
|
||||
"tgui-common.bundle.js" = file("tgui/public/tgui-common.bundle.js"),
|
||||
)
|
||||
|
||||
/datum/asset/simple/tgui
|
||||
// keep_local_name = TRUE
|
||||
assets = list(
|
||||
"tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js',
|
||||
"tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css',
|
||||
"tgui.bundle.js" = file("tgui/public/tgui.bundle.js"),
|
||||
"tgui.bundle.css" = file("tgui/public/tgui.bundle.css"),
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/simple/headers
|
||||
assets = list(
|
||||
"alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
|
||||
@@ -175,6 +182,14 @@
|
||||
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css'
|
||||
)
|
||||
|
||||
/datum/asset/simple/tgfont
|
||||
assets = list(
|
||||
"tgfont.eot" = file("tgui/packages/tgfont/dist/tgfont.eot"),
|
||||
"tgfont.woff2" = file("tgui/packages/tgfont/dist/tgfont.woff2"),
|
||||
"tgfont.css" = file("tgui/packages/tgfont/dist/tgfont.css"),
|
||||
)
|
||||
|
||||
|
||||
// /datum/asset/spritesheet/goonchat
|
||||
// name = "chat"
|
||||
|
||||
|
||||
@@ -148,6 +148,13 @@ obj/machinery/gateway/centerstation/process()
|
||||
if(dest)
|
||||
M.forceMove(dest.loc)
|
||||
M.set_dir(SOUTH)
|
||||
//VOREStation Addition Start: Mcguffin time!
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.client)
|
||||
awaygate.entrydetect()
|
||||
//VOREStation Addition End: Mcguffin time!
|
||||
|
||||
//VOREStation Addition Start: Abduction!
|
||||
if(istype(M, /mob/living) && dest.abductor)
|
||||
var/mob/living/L = M
|
||||
@@ -318,4 +325,4 @@ obj/machinery/gateway/centerstation/process()
|
||||
else
|
||||
to_chat(user, "<font color='blue'><b>Recalibration successful!</b>:</font><font color='black'> This gate's systems have been fine tuned. Travel to this gate will now be on target.</font>")
|
||||
calibrated = 1
|
||||
return
|
||||
return
|
||||
@@ -0,0 +1,79 @@
|
||||
//This gateway type takes a special item that you will have to find on the map to activate, instead of using a multitool//
|
||||
|
||||
/obj/machinery/gateway/centeraway/mcguffin
|
||||
icon = 'icons/obj/machines/gateway_vr.dmi'
|
||||
calibrated = 0
|
||||
var/mcguffin_type = /obj/item/device/mcguffin/brass //you should be able to change the var to be whatever kind of path you like, so maybe you can use other things on it sometimes
|
||||
var/key //holds a ref to the key we spawned
|
||||
|
||||
/obj/machinery/gateway/centeraway/mcguffin/attackby(obj/item/device/W as obj, mob/user as mob)
|
||||
if(calibrated && stationgate)
|
||||
to_chat(user, "<span class='info'>The gate is already configured, you should be able to activate it.</span>")
|
||||
return
|
||||
else if(!stationgate)
|
||||
to_chat(user, "<span class='danger'>Error: Configuration failed. No destination found... That can't be good.</span>")
|
||||
return
|
||||
|
||||
if(istype(W,mcguffin_type) && !calibrated)
|
||||
to_chat(user, "<span class='emote'>As the device nears the gateway, mechanical clunks and whirrs can be heard. <br><font color='blue'><b>Configuration successful! </b></font><br>This gate's systems have been fine tuned. Travel to this gate will now be on target.</span>")
|
||||
calibrated = 1
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='danger'>This device does not seem to interface correctly with the gateway. Perhaps you should try something else.</span>")
|
||||
return
|
||||
|
||||
//If you use this kind of gateway you NEED one of these on the map or the players won't be able to leave//
|
||||
//You should use the random spawner though so it won't always be in the same place//
|
||||
/obj/item/device/mcguffin/brass
|
||||
name = "mysterious brass device"
|
||||
desc = "A curious object made of what appears to be brass and silver. Its purpose is unclear by looking at it. Perhaps it should be used with something of similar materials?"
|
||||
icon = 'icons/obj/machines/gateway_vr.dmi'
|
||||
icon_state = "mcguffin"
|
||||
drop_sound = 'sound/items/drop/wrench.ogg'
|
||||
pickup_sound = 'sound/items/pickup/wrench.ogg'
|
||||
|
||||
/obj/effect/landmark/mcguffin_spawner
|
||||
name = "gateway key spawner"
|
||||
icon = 'icons/mob/randomlandmarks.dmi'
|
||||
icon_state = "key"
|
||||
|
||||
/obj/machinery/gateway/centeraway/proc/entrydetect()
|
||||
return
|
||||
|
||||
/obj/machinery/gateway/centeraway/mcguffin/entrydetect()
|
||||
if(key)
|
||||
return
|
||||
|
||||
var/list/spawners = list()
|
||||
for(var/obj/effect/landmark/mcguffin_spawner/sp in world)
|
||||
spawners += sp
|
||||
|
||||
var/obj/effect/landmark/mcguffin_spawner/the_cool_one = pick(spawners)
|
||||
|
||||
var/atom/destination = get_turf(the_cool_one)
|
||||
var/obj/structure/closet/CL = locate() in destination
|
||||
if(CL)
|
||||
destination = CL
|
||||
|
||||
if(!destination)
|
||||
warning("A gateway is trying to spawn it's mcguffin but there are no mapped in spawner landmarks")
|
||||
destination = get_turf(src)
|
||||
|
||||
key = new mcguffin_type(destination)
|
||||
|
||||
/obj/machinery/gateway/centeraway/mcguffin/Bumped(atom/movable/M as mob|obj)
|
||||
if(!ready) return
|
||||
if(!active) return
|
||||
M.forceMove(get_step(stationgate.loc, SOUTH))
|
||||
M.set_dir(SOUTH)
|
||||
M << 'sound/effects/swooshygate.ogg'
|
||||
playsound(src, 'sound/effects/swooshygate.ogg', 100, 1)
|
||||
|
||||
/obj/machinery/gateway/brass
|
||||
name = "mysterious brass gateway"
|
||||
desc = "A gateway of strange construction. It appears to be made primarily of materials resembling brass and silver."
|
||||
icon = 'icons/obj/machines/gateway_vr.dmi'
|
||||
|
||||
//No, you can't digest the key to leave the gateway.
|
||||
/obj/item/device/mcguffin/digest_act(var/atom/movable/item_storage = null)
|
||||
return FALSE
|
||||
@@ -119,14 +119,14 @@ var/list/blob_cores = list()
|
||||
return ..()
|
||||
|
||||
/obj/structure/blob/core/update_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
color = null
|
||||
var/mutable_appearance/blob_overlay = mutable_appearance('icons/mob/blob.dmi', "blob")
|
||||
if(overmind)
|
||||
blob_overlay.color = overmind.blob_type.color
|
||||
name = "[overmind.blob_type.name] [base_name]"
|
||||
overlays += blob_overlay
|
||||
overlays += mutable_appearance('icons/mob/blob.dmi', "blob_core_overlay")
|
||||
add_overlay(blob_overlay)
|
||||
add_overlay("blob_core_overlay")
|
||||
|
||||
/obj/structure/blob/core/process()
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -21,14 +21,14 @@ var/list/blob_nodes = list()
|
||||
return ..()
|
||||
|
||||
/obj/structure/blob/node/update_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
color = null
|
||||
var/mutable_appearance/blob_overlay = mutable_appearance('icons/mob/blob.dmi', "blob")
|
||||
if(overmind)
|
||||
name = "[overmind.blob_type.name] [base_name]"
|
||||
blob_overlay.color = overmind.blob_type.color
|
||||
overlays += blob_overlay
|
||||
overlays += mutable_appearance('icons/mob/blob.dmi', "blob_node_overlay")
|
||||
add_overlay(blob_overlay)
|
||||
add_overlay("blob_node_overlay")
|
||||
|
||||
/obj/structure/blob/node/process()
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -61,14 +61,14 @@
|
||||
set_light(0)
|
||||
|
||||
if(is_infesting)
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
icon = infested.icon
|
||||
overlays = infested.overlays
|
||||
add_overlay(infested.overlays)
|
||||
var/mutable_appearance/blob_head_overlay = mutable_appearance('icons/mob/blob.dmi', "blob_head")
|
||||
if(overmind)
|
||||
blob_head_overlay.color = overmind.blob_type.complementary_color
|
||||
color = initial(color)//looks better.
|
||||
overlays += blob_head_overlay
|
||||
add_overlay(blob_head_overlay)
|
||||
|
||||
/mob/living/simple_mob/hostile/blob/spore/Life()
|
||||
if(can_infest && !is_infesting && isturf(src.loc))
|
||||
|
||||
@@ -338,6 +338,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
character.set_gender(pref.biological_gender)
|
||||
|
||||
// Destroy/cyborgize organs and limbs.
|
||||
character.synthetic = null //Clear the existing var.
|
||||
for(var/name in list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO))
|
||||
var/status = pref.organ_data[name]
|
||||
var/obj/item/organ/external/O = character.organs_by_name[name]
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
display_name = "pilot qualification pin"
|
||||
description = "An iron pin denoting the qualification to fly SCG spacecraft."
|
||||
path = /obj/item/clothing/accessory/solgov/specialty/pilot
|
||||
allowed_roles = list("Pathfinder","Pilot","Field Medic","Talon Pilot")
|
||||
allowed_roles = list("Pathfinder","Pilot","Field Medic","Talon Pilot")
|
||||
|
||||
/datum/gear/accessory/flops
|
||||
display_name = "drop straps"
|
||||
@@ -112,3 +112,11 @@
|
||||
/datum/gear/accessory/flops/New()
|
||||
..()
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
|
||||
/*
|
||||
Talon pin
|
||||
*/
|
||||
/datum/gear/accessory/talonpin
|
||||
display_name = "ITV pin"
|
||||
description = "A small enamel pin of the ITV logo."
|
||||
path = /obj/item/clothing/accessory/talon
|
||||
@@ -770,6 +770,12 @@
|
||||
ckeywhitelist = list("pandora029")
|
||||
character_name = list("Evelyn Tareen")
|
||||
|
||||
/datum/gear/fluff/evelyn_coat
|
||||
path = /obj/item/clothing/suit/storage/hooded/wintercoat/security/fluff/evelyn/
|
||||
display_name = "warden's navy winter coat"
|
||||
ckeywhitelist = list("pandora029")
|
||||
character_name = list("Evelyn Tareen")
|
||||
|
||||
/datum/gear/fluff/lily_medal
|
||||
path = /obj/item/clothing/accessory/medal/silver/unity
|
||||
display_name = "Lily's Unity Medal"
|
||||
|
||||
@@ -47,4 +47,16 @@
|
||||
|
||||
/datum/gear/head/tigerpeltpink
|
||||
display_name = "pink tiger pelt"
|
||||
path = /obj/item/clothing/head/pelt/tigerpeltpink
|
||||
path = /obj/item/clothing/head/pelt/tigerpeltpink
|
||||
|
||||
/*
|
||||
Talon hats
|
||||
*/
|
||||
/datum/gear/head/cap/talon
|
||||
display_name = "cap, ITV"
|
||||
path = /obj/item/clothing/head/soft/talon
|
||||
|
||||
/datum/gear/head/beret/talon
|
||||
display_name = "beret, ITV"
|
||||
path = /obj/item/clothing/head/beret
|
||||
|
||||
|
||||
@@ -72,4 +72,11 @@
|
||||
|
||||
/datum/gear/suit/oversize/New()
|
||||
..()
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
|
||||
/*
|
||||
Talon winter coat
|
||||
*/
|
||||
/datum/gear/suit/wintercoat/talon
|
||||
display_name = "winter coat, ITV"
|
||||
path = /obj/item/clothing/suit/storage/hooded/wintercoat/talon
|
||||
@@ -215,4 +215,12 @@ Bluespace jumpsuit
|
||||
/datum/gear/uniform/hfjumpsuit
|
||||
display_name = "HYPER jumpsuit"
|
||||
path = /obj/item/clothing/under/hyperfiber
|
||||
cost = 2
|
||||
cost = 2
|
||||
|
||||
/*
|
||||
Talon jumpsuit
|
||||
*/
|
||||
/datum/gear/uniform/talonbasic
|
||||
display_name = "ITV Jumpsuit"
|
||||
description = "A jumpsuit that is usually issued to ITV contractors, however others can purchase it to show their support towards ITV."
|
||||
path = /obj/item/clothing/under/rank/talon/basic
|
||||
@@ -61,6 +61,10 @@
|
||||
path = /obj/item/weapon/storage/backpack/dufflebag/explorer
|
||||
allowed_roles = list("Pathfinder","Explorer")
|
||||
|
||||
/datum/gear/utility/dufflebag/talon
|
||||
display_name = "ITV dufflebag"
|
||||
path = /obj/item/weapon/storage/backpack/dufflebag/explorer
|
||||
|
||||
/datum/gear/utility/ID
|
||||
display_name = "contractor identification card"
|
||||
path = /obj/item/weapon/card/id/event/polymorphic/altcard
|
||||
|
||||
@@ -86,7 +86,8 @@ datum/preferences
|
||||
"2" = "character_preview_map:2,5",
|
||||
"4" = "character_preview_map:2,3",
|
||||
"8" = "character_preview_map:2,1",
|
||||
"BG" = "character_preview_map:1,1 to 3,8"
|
||||
"BG" = "character_preview_map:1,1 to 3,8",
|
||||
"PMH" = "character_preview_map:2,7"
|
||||
)
|
||||
|
||||
//Jobs, uses bitflags
|
||||
@@ -270,6 +271,13 @@ datum/preferences
|
||||
if(!client)
|
||||
return
|
||||
|
||||
var/obj/screen/setup_preview/pm_helper/PMH = LAZYACCESS(char_render_holders, "PMH")
|
||||
if(!PMH)
|
||||
PMH = new
|
||||
LAZYSET(char_render_holders, "PMH", PMH)
|
||||
client.screen |= PMH
|
||||
PMH.screen_loc = preview_screen_locs["PMH"]
|
||||
|
||||
var/obj/screen/setup_preview/bg/BG = LAZYACCESS(char_render_holders, "BG")
|
||||
if(!BG)
|
||||
BG = new
|
||||
|
||||
@@ -6,55 +6,46 @@
|
||||
|
||||
var/list/Lines = list()
|
||||
|
||||
if(holder && (R_ADMIN & holder.rights || R_MOD & holder.rights))
|
||||
for(var/client/C in GLOB.clients)
|
||||
var/entry = "\t[C.key]"
|
||||
if(C.holder && C.holder.fakekey)
|
||||
entry += " <i>(as [C.holder.fakekey])</i>"
|
||||
entry += " - Playing as [C.mob.real_name]"
|
||||
switch(C.mob.stat)
|
||||
if(UNCONSCIOUS)
|
||||
entry += " - <font color='darkgray'><b>Unconscious</b></font>"
|
||||
if(DEAD)
|
||||
if(isobserver(C.mob))
|
||||
var/mob/observer/dead/O = C.mob
|
||||
if(O.started_as_observer)
|
||||
entry += " - <font color='gray'>Observing</font>"
|
||||
else
|
||||
entry += " - <font color='black'><b>DEAD</b></font>"
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(!check_rights_for(src, R_ADMIN|R_MOD))
|
||||
Lines += "\t[C.holder?.fakekey || C.key]"
|
||||
continue
|
||||
var/entry = "\t[C.key]"
|
||||
if(C.holder?.fakekey)
|
||||
entry += " <i>(as [C.holder.fakekey])</i>"
|
||||
entry += " - Playing as [C.mob.real_name]"
|
||||
switch(C.mob.stat)
|
||||
if(UNCONSCIOUS)
|
||||
entry += " - <font color='darkgray'><b>Unconscious</b></font>"
|
||||
if(DEAD)
|
||||
if(isobserver(C.mob))
|
||||
var/mob/observer/dead/O = C.mob
|
||||
if(O.started_as_observer)
|
||||
entry += " - <font color='gray'>Observing</font>"
|
||||
else
|
||||
entry += " - <font color='black'><b>DEAD</b></font>"
|
||||
else
|
||||
entry += " - <font color='black'><b>DEAD</b></font>"
|
||||
|
||||
var/age
|
||||
if(isnum(C.player_age))
|
||||
age = C.player_age
|
||||
else
|
||||
age = 0
|
||||
if(C.player_age != initial(C.player_age) && isnum(C.player_age)) // database is on
|
||||
var/age = C.player_age
|
||||
switch(age)
|
||||
if(0 to 1)
|
||||
age = "<font color='#ff0000'><b>[age] days old</b></font>"
|
||||
if(1 to 10)
|
||||
age = "<font color='#ff8c00'><b>[age] days old</b></font>"
|
||||
else
|
||||
entry += " - [age] days old"
|
||||
|
||||
if(age <= 1)
|
||||
age = "<font color='#ff0000'><b>[age]</b></font>"
|
||||
else if(age < 10)
|
||||
age = "<font color='#ff8c00'><b>[age]</b></font>"
|
||||
if(is_special_character(C.mob))
|
||||
entry += " - <b><font color='red'>Antagonist</font></b>"
|
||||
|
||||
entry += " - [age]"
|
||||
if(C.is_afk())
|
||||
var/seconds = C.last_activity_seconds()
|
||||
entry += " (AFK - [round(seconds / 60)] minutes, [seconds % 60] seconds)"
|
||||
|
||||
if(is_special_character(C.mob))
|
||||
entry += " - <b><font color='red'>Antagonist</font></b>"
|
||||
|
||||
if(C.is_afk())
|
||||
var/seconds = C.last_activity_seconds()
|
||||
entry += " (AFK - "
|
||||
entry += "[round(seconds / 60)] minutes, "
|
||||
entry += "[seconds % 60] seconds)"
|
||||
|
||||
entry += " (<A HREF='?_src_=holder;adminmoreinfo=\ref[C.mob]'>?</A>)"
|
||||
Lines += entry
|
||||
else
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(C.holder && C.holder.fakekey)
|
||||
Lines += C.holder.fakekey
|
||||
else
|
||||
Lines += C.key
|
||||
entry += " (<A HREF='?_src_=holder;adminmoreinfo=\ref[C.mob]'>?</A>)"
|
||||
Lines += entry
|
||||
|
||||
for(var/line in sortList(Lines))
|
||||
msg += "[line]\n"
|
||||
@@ -66,11 +57,6 @@
|
||||
set category = "Admin"
|
||||
set name = "Staffwho"
|
||||
|
||||
var/message = get_staffwho_message(holder)
|
||||
to_chat(src, message)
|
||||
|
||||
// VOREStation Edit - This whole proc has various vorestation edits throughout. Practically every other line.
|
||||
/proc/get_staffwho_message(datum/admins/holder)
|
||||
var/msg = ""
|
||||
var/modmsg = ""
|
||||
var/devmsg = ""
|
||||
@@ -79,117 +65,50 @@
|
||||
var/num_admins_online = 0
|
||||
var/num_devs_online = 0
|
||||
var/num_event_managers_online = 0
|
||||
|
||||
if(holder)
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(R_ADMIN & C.holder.rights && R_BAN & C.holder.rights)
|
||||
|
||||
if(C.holder.fakekey && !((R_ADMIN & holder.rights) || (R_MOD & holder.rights))) //Event Managerss can't see stealthmins
|
||||
continue
|
||||
|
||||
msg += "\t[C] is a [C.holder.rank]"
|
||||
|
||||
if(C.holder.fakekey)
|
||||
msg += " <i>(as [C.holder.fakekey])</i>"
|
||||
|
||||
if(isobserver(C.mob))
|
||||
msg += " - Observing"
|
||||
else if(istype(C.mob,/mob/new_player))
|
||||
msg += " - Lobby"
|
||||
else
|
||||
msg += " - Playing"
|
||||
|
||||
if(C.is_afk())
|
||||
var/seconds = C.last_activity_seconds()
|
||||
msg += " (AFK - "
|
||||
msg += "[round(seconds / 60)] minutes, "
|
||||
msg += "[seconds % 60] seconds)"
|
||||
msg += "\n"
|
||||
|
||||
num_admins_online++
|
||||
else if(R_ADMIN & C.holder.rights && !(R_SERVER & C.holder.rights))
|
||||
modmsg += "\t[C] is a [C.holder.rank]"
|
||||
|
||||
if(C.holder.fakekey && !((R_ADMIN & holder.rights) || (R_MOD & holder.rights)))
|
||||
continue
|
||||
if(C.holder.fakekey)
|
||||
msg += " <i>(as [C.holder.fakekey])</i>"
|
||||
|
||||
if(isobserver(C.mob))
|
||||
modmsg += " - Observing"
|
||||
else if(istype(C.mob,/mob/new_player))
|
||||
modmsg += " - Lobby"
|
||||
else
|
||||
modmsg += " - Playing"
|
||||
|
||||
if(C.is_afk())
|
||||
var/seconds = C.last_activity_seconds()
|
||||
modmsg += " (AFK - "
|
||||
modmsg += "[round(seconds / 60)] minutes, "
|
||||
modmsg += "[seconds % 60] seconds)"
|
||||
modmsg += "\n"
|
||||
num_mods_online++
|
||||
|
||||
else if(R_SERVER & C.holder.rights)
|
||||
if(C.holder.fakekey && !((R_ADMIN & holder.rights) || (R_MOD & holder.rights)))
|
||||
continue
|
||||
devmsg += "\t[C] is a [C.holder.rank]"
|
||||
if(C.holder.fakekey)
|
||||
devmsg += " <i>(as [C.holder.fakekey])</i>"
|
||||
if(isobserver(C.mob))
|
||||
devmsg += " - Observing"
|
||||
else if(istype(C.mob,/mob/new_player))
|
||||
devmsg += " - Lobby"
|
||||
else
|
||||
devmsg += " - Playing"
|
||||
|
||||
if(C.is_afk())
|
||||
var/seconds = C.last_activity_seconds()
|
||||
devmsg += "(AFK - "
|
||||
devmsg += "[round(seconds / 60)] minutes, "
|
||||
devmsg += "[seconds % 60] seconds)"
|
||||
devmsg += "\n"
|
||||
num_devs_online++
|
||||
for(var/client/C in GLOB.admins) // VOREStation Edit - GLOB
|
||||
var/temp = ""
|
||||
var/category = R_ADMIN
|
||||
// VOREStation Edit - Apply stealthmin protection to all levels
|
||||
if(C.holder.fakekey && check_rights(R_ADMIN|R_MOD, FALSE, src)) // Only admins and mods can see stealthmins
|
||||
continue
|
||||
// VOREStation Edit End
|
||||
if(check_rights(R_BAN, FALSE, C)) // admins //VOREStation Edit
|
||||
num_admins_online++
|
||||
else if(check_rights(R_ADMIN, FALSE, C) && !check_rights(R_SERVER, FALSE, C)) // mods //VOREStation Edit: Game masters
|
||||
category = R_MOD
|
||||
num_mods_online++
|
||||
else if(check_rights(R_SERVER, FALSE, C)) // developers
|
||||
category = R_SERVER
|
||||
num_devs_online++
|
||||
else if(check_rights(R_STEALTH, FALSE, C)) // event managers //VOREStation Edit: Retired Staff
|
||||
category = R_EVENT
|
||||
num_event_managers_online++
|
||||
|
||||
temp += "\t[C] is a [C.holder.rank]"
|
||||
if(holder)
|
||||
if(C.holder.fakekey)
|
||||
temp += " <i>(as [C.holder.fakekey])</i>"
|
||||
|
||||
if(isobserver(C.mob))
|
||||
temp += " - Observing"
|
||||
else if(istype(C.mob,/mob/new_player))
|
||||
temp += " - Lobby"
|
||||
else
|
||||
if(C.holder.fakekey && !((R_ADMIN & holder.rights) || (R_MOD & holder.rights)))
|
||||
continue
|
||||
eventMmsg += "\t[C] is a [C.holder.rank]"
|
||||
if(C.holder.fakekey)
|
||||
eventMmsg += " <i>(as [C.holder.fakekey])</i>"
|
||||
if(isobserver(C.mob))
|
||||
eventMmsg += " - Observing"
|
||||
else if(istype(C.mob,/mob/new_player))
|
||||
eventMmsg += " - Lobby"
|
||||
else
|
||||
eventMmsg += " - Playing"
|
||||
temp += " - Playing"
|
||||
|
||||
if(C.is_afk())
|
||||
var/seconds = C.last_activity_seconds()
|
||||
eventMmsg += " (AFK - "
|
||||
eventMmsg += "[round(seconds / 60)] minutes, "
|
||||
eventMmsg += "[seconds % 60] seconds)"
|
||||
eventMmsg += "\n"
|
||||
num_event_managers_online++
|
||||
|
||||
else
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(R_ADMIN & C.holder.rights && R_BAN & C.holder.rights)
|
||||
if(!C.holder.fakekey)
|
||||
msg += "\t[C] is a [C.holder.rank]\n"
|
||||
num_admins_online++
|
||||
else if(R_ADMIN & C.holder.rights && !(R_SERVER & C.holder.rights))
|
||||
if(!C.holder.fakekey)
|
||||
modmsg += "\t[C] is a [C.holder.rank]\n"
|
||||
num_mods_online++
|
||||
else if(R_SERVER & C.holder.rights)
|
||||
if(!C.holder.fakekey)
|
||||
devmsg += "\t[C] is a [C.holder.rank]\n"
|
||||
num_devs_online++
|
||||
else
|
||||
if(!C.holder.fakekey)
|
||||
eventMmsg += "\t[C] is a [C.holder.rank]\n"
|
||||
num_event_managers_online++
|
||||
if(C.is_afk())
|
||||
var/seconds = C.last_activity_seconds()
|
||||
temp += " (AFK - [round(seconds / 60)] minutes, [seconds % 60] seconds)"
|
||||
temp += "\n"
|
||||
switch(category)
|
||||
if(R_ADMIN)
|
||||
msg += temp
|
||||
if(R_MOD)
|
||||
modmsg += temp
|
||||
if(R_SERVER)
|
||||
devmsg += temp
|
||||
if(R_EVENT)
|
||||
eventMmsg += temp
|
||||
|
||||
msg = "<b>Current Admins ([num_admins_online]):</b>\n" + msg
|
||||
|
||||
@@ -204,5 +123,4 @@
|
||||
|
||||
msg += "\n<span class='info'>Adminhelps are also sent to Discord. If no admins are available in game try anyway and an admin on Discord may see it and respond.</span>"
|
||||
|
||||
return msg
|
||||
|
||||
to_chat(src, msg)
|
||||
|
||||
+1094
-1096
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@
|
||||
//HELMET: May have a lighting overlay
|
||||
/obj/item/clothing/head/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer = 0,var/icon/clip_mask = null)
|
||||
var/image/standing = ..()
|
||||
if(on && slot_name == slot_head_str)
|
||||
if(light_on && slot_name == slot_head_str)
|
||||
var/cache_key = "[light_overlay][LAZYACCESS(sprite_sheets,body_type) ? "_[body_type]" : ""]"
|
||||
if(standing && light_overlay_cache[cache_key])
|
||||
standing.add_overlay(light_overlay_cache[cache_key])
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
name = "hard hat"
|
||||
desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight."
|
||||
icon_state = "hardhat0_yellow"
|
||||
brightness_on = 4 //luminosity when on
|
||||
light_range = 4 //luminosity when on
|
||||
light_cone_y_offset = 14
|
||||
light_overlay = "hardhat_light"
|
||||
armor = list(melee = 30, bullet = 5, laser = 20,energy = 10, bomb = 20, bio = 10, rad = 20)
|
||||
flags_inv = 0
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
icon_state = "flexitac"
|
||||
armor = list(melee = 40, bullet = 40, laser = 60, energy = 35, bomb = 30, bio = 0, rad = 0)
|
||||
siemens_coefficient = 0.6
|
||||
brightness_on = 6
|
||||
light_range = 6
|
||||
light_overlay = "helmet_light_dual_green"
|
||||
action_button_name = "Toggle Head-light"
|
||||
min_cold_protection_temperature = T0C - 20
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
light_range = 3
|
||||
light_power = 1
|
||||
light_color = "#B18B25" //clockwork slab background top color
|
||||
light_on = TRUE
|
||||
|
||||
/obj/item/clothing/head/hood/winter/narsie
|
||||
name = "runed winter hood"
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
name = "techpriest hood"
|
||||
armor = list(melee = 20, bullet = 10, laser = 10, energy = 10, bomb = 25, bio = 50, rad = 25)
|
||||
|
||||
// Armor versions here
|
||||
// Armor versions here
|
||||
/obj/item/clothing/head/hood/galahad
|
||||
name = "galahad hood"
|
||||
armor = list(melee = 80, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0)
|
||||
siemens_coefficient = 2
|
||||
|
||||
|
||||
/obj/item/clothing/head/hood/lancelot
|
||||
name = "lancelot hood"
|
||||
armor = list(melee = 80, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0)
|
||||
siemens_coefficient = 2
|
||||
|
||||
|
||||
/obj/item/clothing/head/hood/robin
|
||||
name = "robin hood"
|
||||
armor = list(melee = 80, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0)
|
||||
@@ -21,9 +21,16 @@
|
||||
// Costume Versions Here
|
||||
/obj/item/clothing/head/hood/galahad_costume
|
||||
name = "galahad costume hood"
|
||||
|
||||
|
||||
/obj/item/clothing/head/hood/lancelot_costume
|
||||
name = "lancelot costume hood"
|
||||
|
||||
|
||||
/obj/item/clothing/head/hood/robin_costume
|
||||
name = "robin costume hood"
|
||||
name = "robin costume hood"
|
||||
|
||||
// Talon Winter Hood
|
||||
/obj/item/clothing/head/hood/winter/talon
|
||||
name = "ITV winter hood"
|
||||
desc = "A cozy winter hood attached to a heavy winter jacket."
|
||||
icon_override = 'icons/mob/head_vr.dmi'
|
||||
icon_state = "winterhood_talon"
|
||||
@@ -167,7 +167,7 @@
|
||||
icon_state = "hardhat0_pumpkin"//Could stand to be renamed
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|BLOCKHAIR
|
||||
body_parts_covered = HEAD|FACE|EYES
|
||||
brightness_on = 2
|
||||
light_range = 2
|
||||
light_overlay = "jackolantern"
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
drop_sound = 'sound/items/drop/herb.ogg'
|
||||
|
||||
@@ -93,4 +93,39 @@
|
||||
desc = "A fancy visor showing alignment to pizza delivery service. Extremely risky career choice."
|
||||
icon_state = "pizzadelivery"
|
||||
icon = 'icons/obj/clothing/hats_vr.dmi'
|
||||
icon_override = 'icons/mob/head_vr.dmi'
|
||||
icon_override = 'icons/mob/head_vr.dmi'
|
||||
|
||||
//////////TALON HATS//////////
|
||||
|
||||
/obj/item/clothing/head/soft/talon
|
||||
name = "ITV baseball cap"
|
||||
desc = "It's a ballcap bearing the colors of ITV."
|
||||
icon = 'icons/obj/clothing/hats_vr.dmi'
|
||||
icon_override = 'icons/mob/head_vr.dmi'
|
||||
icon_state = "talonsoft"
|
||||
item_state = "talonsoft"
|
||||
item_state_slots = list(slot_r_hand_str = "blacksoft", slot_l_hand_str = "blacksoft")
|
||||
|
||||
/obj/item/clothing/head/caphat/talon
|
||||
name = "ITV nautical hat"
|
||||
desc = "It's a classic nautical hat bearing the colors of ITV. Perfect for commanding the Talon."
|
||||
icon = 'icons/obj/clothing/hats_vr.dmi'
|
||||
icon_override = 'icons/mob/head_vr.dmi'
|
||||
icon_state = "talon_captain_cap"
|
||||
item_state = "taloncaptaincap"
|
||||
|
||||
obj/item/clothing/head/beret/talon
|
||||
name = "ITV beret"
|
||||
desc = "It's a basic baret colored to match ITV's uniforms."
|
||||
icon = 'icons/obj/clothing/hats_vr.dmi'
|
||||
icon_override = 'icons/mob/head_vr.dmi'
|
||||
icon_state = "beret_talon"
|
||||
item_state = "baret_talon"
|
||||
|
||||
obj/item/clothing/head/beret/talon/command
|
||||
name = "ITV officer beret"
|
||||
desc = "It's a basic baret colored to match ITV's uniforms with a badge pinned on the front. Perfect for commanders."
|
||||
icon = 'icons/obj/clothing/hats_vr.dmi'
|
||||
icon_override = 'icons/mob/head_vr.dmi'
|
||||
icon_state = "beret_talon_officer"
|
||||
item_state = "baret_talon_command"
|
||||
@@ -44,3 +44,24 @@
|
||||
src.icon_state = initial(icon_state)
|
||||
to_chat(user, "You lower the visor on the pilot helmet.")
|
||||
update_clothing_icon() //so our mob-overlays update
|
||||
|
||||
//////////Talon Pilot Headgear//////////
|
||||
|
||||
/obj/item/clothing/head/pilot_vr/talon
|
||||
name = "ITV pilot helmet"
|
||||
desc = "An ITV version of the standard pilot helmet. Protects the head from impacts. This one has a retractable visor"
|
||||
icon_state = "pilot3"
|
||||
item_icons = list(slot_head_str = 'icons/mob/head_vr.dmi')
|
||||
sprite_sheets = list(
|
||||
SPECIES_TESHARI = 'icons/mob/species/teshari/helmet_vr.dmi'
|
||||
)
|
||||
action_button_name = "Toggle Visor"
|
||||
|
||||
/obj/item/clothing/head/pilot_vr/alt/attack_self(mob/user as mob)
|
||||
if(src.icon_state == initial(icon_state))
|
||||
src.icon_state = "[icon_state]up"
|
||||
to_chat(user, "You raise the visor on the pilot helmet.")
|
||||
else
|
||||
src.icon_state = initial(icon_state)
|
||||
to_chat(user, "You lower the visor on the pilot helmet.")
|
||||
update_clothing_icon() //so our mob-overlays update
|
||||
|
||||
@@ -585,8 +585,7 @@
|
||||
|
||||
/obj/item/weapon/rig/update_icon(var/update_mob_icon)
|
||||
|
||||
//TODO: Maybe consider a cache for this (use mob_icon as blank canvas, use suit icon overlay).
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
if(!mob_icon || update_mob_icon)
|
||||
var/species_icon = 'icons/mob/rig_back.dmi'
|
||||
// Since setting mob_icon will override the species checks in
|
||||
@@ -598,7 +597,7 @@
|
||||
if(installed_modules.len)
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
if(module.suit_overlay)
|
||||
chest.overlays += image("icon" = 'icons/mob/rig_modules.dmi', "icon_state" = "[module.suit_overlay]", "dir" = SOUTH)
|
||||
chest.add_overlay(image('icons/mob/rig_modules.dmi', icon_state = "[module.suit_overlay]", dir = SOUTH))
|
||||
|
||||
if(wearer)
|
||||
wearer.update_inv_shoes()
|
||||
@@ -729,8 +728,8 @@
|
||||
to_chat(H, "<span class='notice'>Your [use_obj.name] [use_obj.gender == PLURAL ? "deploy" : "deploys"] swiftly.</span>")
|
||||
playsound(src, 'sound/machines/rig/rigservo.ogg', 10, FALSE)
|
||||
|
||||
if(piece == "helmet" && helmet)
|
||||
helmet.update_light(H)
|
||||
if(piece == "helmet" && helmet?.light_system == STATIC_LIGHT)
|
||||
helmet.update_light()
|
||||
|
||||
/obj/item/weapon/rig/proc/deploy(mob/M,var/sealed)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
body_parts_covered = HEAD|FACE|EYES
|
||||
heat_protection = HEAD|FACE|EYES
|
||||
cold_protection = HEAD|FACE|EYES
|
||||
brightness_on = 4
|
||||
light_range = 4
|
||||
sprite_sheets = list(
|
||||
SPECIES_TAJ = 'icons/mob/species/tajaran/helmet.dmi',
|
||||
SPECIES_SKRELL = 'icons/mob/species/skrell/helmet.dmi',
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
|
||||
action_button_name = "Toggle Helmet Light"
|
||||
light_overlay = "helmet_light"
|
||||
brightness_on = 4
|
||||
on = 0
|
||||
light_range = 4
|
||||
|
||||
/obj/item/clothing/head/helmet/space/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
/obj/item/clothing/suit/space/void/responseteam/command/Initialize()
|
||||
..()
|
||||
helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/command //autoinstall the helmet
|
||||
attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/command) //autoinstall the helmet
|
||||
|
||||
/obj/item/clothing/suit/space/void/responseteam/medical
|
||||
name = "Mark VII-M Emergency Medical Response Suit"
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/obj/item/clothing/suit/space/void/responseteam/medical/Initialize()
|
||||
..()
|
||||
helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/medical //autoinstall the helmet
|
||||
attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/medical) //autoinstall the helmet
|
||||
|
||||
/obj/item/clothing/suit/space/void/responseteam/engineer
|
||||
name = "Mark VII-E Emergency Engineering Response Suit"
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
/obj/item/clothing/suit/space/void/responseteam/engineer/Initialize()
|
||||
..()
|
||||
helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/engineer //autoinstall the helmet
|
||||
attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/engineer) //autoinstall the helmet
|
||||
|
||||
/obj/item/clothing/suit/space/void/responseteam/security
|
||||
name = "Mark VII-S Emergency Security Response Suit"
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
/obj/item/clothing/suit/space/void/responseteam/security/Initialize()
|
||||
..()
|
||||
helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/security //autoinstall the helmet
|
||||
attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/security) //autoinstall the helmet
|
||||
|
||||
/obj/item/clothing/suit/space/void/responseteam/janitor
|
||||
name = "Mark VII-J Emergency Cleanup Response Suit"
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
/obj/item/clothing/suit/space/void/responseteam/janitor/Initialize()
|
||||
..()
|
||||
helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/janitor //autoinstall the helmet
|
||||
attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/janitor) //autoinstall the helmet
|
||||
|
||||
|
||||
//override the attackby screwdriver proc so that people can't remove the helmet
|
||||
|
||||
@@ -120,7 +120,6 @@
|
||||
to_chat(M, "Your suit's cooling unit deploys.")
|
||||
cooler.canremove = 0
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/void/dropped()
|
||||
..()
|
||||
|
||||
@@ -150,6 +149,22 @@
|
||||
cooler.canremove = 1
|
||||
cooler.forceMove(src)
|
||||
|
||||
/obj/item/clothing/suit/space/void/proc/attach_helmet(var/obj/item/clothing/head/helmet/space/void/helm)
|
||||
if(!istype(helm) || helmet)
|
||||
return
|
||||
|
||||
helm.forceMove(src)
|
||||
helm.set_light_flags(helm.light_flags | LIGHT_ATTACHED)
|
||||
helmet = helm
|
||||
|
||||
/obj/item/clothing/suit/space/void/proc/remove_helmet()
|
||||
if(!helmet)
|
||||
return
|
||||
|
||||
helmet.forceMove(get_turf(src))
|
||||
helmet.set_light_flags(helmet.light_flags & ~LIGHT_ATTACHED)
|
||||
helmet = null
|
||||
|
||||
/obj/item/clothing/suit/space/void/verb/toggle_helmet()
|
||||
|
||||
set name = "Toggle Helmet"
|
||||
@@ -184,7 +199,9 @@
|
||||
helmet.pickup(H)
|
||||
helmet.canremove = 0
|
||||
to_chat(H, "<span class='info'>You deploy your suit helmet, sealing you off from the world.</span>")
|
||||
helmet.update_light(H)
|
||||
|
||||
if(helmet.light_system == STATIC_LIGHT)
|
||||
helmet.update_light()
|
||||
|
||||
/obj/item/clothing/suit/space/void/verb/eject_tank()
|
||||
|
||||
@@ -243,9 +260,8 @@
|
||||
src.cooler = null
|
||||
else if(choice == helmet)
|
||||
to_chat(user, "You detach \the [helmet] from \the [src]'s helmet mount.")
|
||||
helmet.forceMove(get_turf(src))
|
||||
remove_helmet()
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
src.helmet = null
|
||||
else if(choice == boots)
|
||||
to_chat(user, "You detach \the [boots] from \the [src]'s boot mounts.")
|
||||
boots.forceMove(get_turf(src))
|
||||
@@ -260,8 +276,7 @@
|
||||
else
|
||||
to_chat(user, "You attach \the [W] to \the [src]'s helmet mount.")
|
||||
user.drop_item()
|
||||
W.forceMove(src)
|
||||
src.helmet = W
|
||||
attach_helmet(W)
|
||||
return
|
||||
else if(istype(W,/obj/item/clothing/shoes/magboots))
|
||||
if(boots)
|
||||
|
||||
@@ -322,6 +322,7 @@
|
||||
light_range = 3
|
||||
light_power = 1
|
||||
light_color = "#B18B25" //clockwork slab background top color
|
||||
light_on = TRUE
|
||||
|
||||
/obj/item/clothing/suit/storage/hooded/wintercoat/narsie
|
||||
name = "runed winter coat"
|
||||
@@ -336,6 +337,7 @@
|
||||
hoodtype = /obj/item/clothing/head/hood/winter/cosmic
|
||||
light_power = 1.8
|
||||
light_range = 1.2
|
||||
light_on = TRUE
|
||||
|
||||
// winter coats end here
|
||||
|
||||
|
||||
@@ -67,4 +67,14 @@
|
||||
name = "crusader's armor"
|
||||
desc = "ye olde knight, risen again. This one seems slightly faster than the rest, but weaker."
|
||||
icon_state = "robin"
|
||||
hoodtype = /obj/item/clothing/head/hood/robin_costume
|
||||
hoodtype = /obj/item/clothing/head/hood/robin_costume
|
||||
|
||||
// Talon Winter Coat
|
||||
/obj/item/clothing/suit/storage/hooded/wintercoat/talon
|
||||
name = "ITV winter coat"
|
||||
desc = "A cozy winter coat, covered in thick fur and baring the colors of ITV."
|
||||
icon = 'icons/obj/clothing/suits_vr.dmi'
|
||||
icon_override = 'icons/mob/suit_vr.dmi'
|
||||
icon_state = "taloncoat"
|
||||
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
|
||||
hoodtype = /obj/item/clothing/head/hood/winter/talon
|
||||
|
||||
@@ -100,3 +100,12 @@
|
||||
icon_override = 'icons/mob/suit_vr.dmi'
|
||||
icon_state = "cyberpunksleek_long"
|
||||
item_state = "cyberpunksleek_long"
|
||||
|
||||
//Talon Hoodie
|
||||
/obj/item/clothing/suit/storage/toggle/hoodie/talon
|
||||
name = "ITV hoodie"
|
||||
desc = "A warm, blue sweatshirt bearing ITV markings."
|
||||
icon = 'icons/obj/clothing/suits_vr.dmi'
|
||||
icon_override = 'icons/mob/suit_vr.dmi'
|
||||
icon_state = "talonhoodie"
|
||||
item_state_slots = list(slot_r_hand_str = "suit_blue", slot_l_hand_str = "suit_blue")
|
||||
@@ -366,3 +366,12 @@
|
||||
item_state = "silverthree"
|
||||
overlay_state = "silverthree"
|
||||
desc = "A silver medal awarded to a group which has demonstrated exceptional teamwork to achieve a notable feat. This one has three bronze service stars, denoting that it has been awarded four times."
|
||||
|
||||
/obj/item/clothing/accessory/talon
|
||||
name = "ITV pin"
|
||||
desc = "A collectable enamel pin that resembles ITV's company logo."
|
||||
icon = 'icons/obj/clothing/ties_vr.dmi'
|
||||
icon_override = 'icons/mob/ties_vr.dmi'
|
||||
icon_state = "talon_pin"
|
||||
item_state = "talonpin"
|
||||
overlay_state = "talonpin"
|
||||
@@ -146,3 +146,60 @@
|
||||
icon_state = "pizzadelivery"
|
||||
item_state = "pizzadelivery"
|
||||
rolled_down = 0
|
||||
|
||||
//////////////////////TALON JUMPSUITS//////////////////////
|
||||
|
||||
/obj/item/clothing/under/rank/talon/basic
|
||||
name = "ITV jumpsuit"
|
||||
desc = "A basic jumpsuit that bares the ITV logo on the breast."
|
||||
icon = 'icons/obj/clothing/uniforms_vr.dmi'
|
||||
index = "vr"
|
||||
rolled_down_icon = 'icons/mob/uniform_rolled_down_vr.dmi'
|
||||
icon_override = 'icons/mob/uniform_vr.dmi'
|
||||
icon_state = "talon_basic"
|
||||
item_state = "talon_basic"
|
||||
rolled_sleeves = 0
|
||||
|
||||
/obj/item/clothing/under/rank/talon/proper
|
||||
name = "ITV proper jumpsuit"
|
||||
desc = "A neat and proper uniform for a proper company."
|
||||
icon = 'icons/obj/clothing/uniforms_vr.dmi'
|
||||
index = "vr"
|
||||
rolled_down_icon = 'icons/mob/uniform_rolled_down_vr.dmi'
|
||||
icon_override = 'icons/mob/uniform_vr.dmi'
|
||||
icon_state = "talon_jumpsuit"
|
||||
item_state = "talon_jumpsuit"
|
||||
rolled_sleeves = 0
|
||||
|
||||
/obj/item/clothing/under/rank/talon/security
|
||||
name = "ITV security jumpsuit"
|
||||
desc = "A sleek, streamlined version of ITV's standard jumpsuit that bares security markings."
|
||||
icon = 'icons/obj/clothing/uniforms_vr.dmi'
|
||||
index = "vr"
|
||||
rolled_down_icon = 'icons/mob/uniform_rolled_down_vr.dmi'
|
||||
icon_override = 'icons/mob/uniform_vr.dmi'
|
||||
icon_state = "talon_security"
|
||||
item_state = "talon_security"
|
||||
rolled_sleeves = 0
|
||||
|
||||
/obj/item/clothing/under/rank/talon/pilot
|
||||
name = "ITV pilot jumpsuit"
|
||||
desc = "A sleek, streamlined version of ITV's standard jumpsuit. Made from cushioned fabric to handle intense flight."
|
||||
icon = 'icons/obj/clothing/uniforms_vr.dmi'
|
||||
index = "vr"
|
||||
rolled_down_icon = 'icons/mob/uniform_rolled_down_vr.dmi'
|
||||
icon_override = 'icons/mob/uniform_vr.dmi'
|
||||
icon_state = "talon_pilot"
|
||||
item_state = "talon_pilot"
|
||||
rolled_sleeves = 0
|
||||
|
||||
/obj/item/clothing/under/rank/talon/command
|
||||
name = "ITV command jumpsuit"
|
||||
desc = "A commanding jumpsuit fit for a commanding officer."
|
||||
icon = 'icons/obj/clothing/uniforms_vr.dmi'
|
||||
index = "vr"
|
||||
rolled_down_icon = 'icons/mob/uniform_rolled_down_vr.dmi'
|
||||
icon_override = 'icons/mob/uniform_vr.dmi'
|
||||
icon_state = "talon_captain"
|
||||
item_state = "talon_captain"
|
||||
rolled_sleeves = 0
|
||||
@@ -75,7 +75,7 @@
|
||||
var/set_overlays = (compass_static_labels | compass_waypoint_markers)
|
||||
if(show_heading)
|
||||
set_overlays |= compass_heading_marker
|
||||
overlays = set_overlays
|
||||
overlays = set_overlays // ???
|
||||
|
||||
/obj/compass_holder/proc/clear_waypoint(var/id)
|
||||
LAZYREMOVE(compass_waypoints, id)
|
||||
|
||||
@@ -111,7 +111,8 @@
|
||||
var/obj/item/weapon/paper/P = new(src)
|
||||
P.name = "[src] report #[++report_num]: [bloodsamp.name]"
|
||||
P.stamped = list(/obj/item/weapon/stamp)
|
||||
P.overlays = list("paper_stamped")
|
||||
P.cut_overlays()
|
||||
P.add_overlay("paper_stamped")
|
||||
//dna data itself
|
||||
var/data = "No scan information available."
|
||||
if(bloodsamp.dna != null)
|
||||
|
||||
@@ -62,8 +62,8 @@
|
||||
var/image/img = image("icon"=I, "layer"=FLOAT_LAYER) //take a snapshot. (necessary to stop the underlays appearing under our inventory-HUD slots ~Carn
|
||||
I.pixel_x = xx //and then return it
|
||||
I.pixel_y = yy
|
||||
overlays += img
|
||||
overlays += "evidence" //should look nicer for transparent stuff. not really that important, but hey.
|
||||
add_overlay(img)
|
||||
add_overlay("evidence") //should look nicer for transparent stuff. not really that important, but hey.
|
||||
|
||||
desc = "An evidence bag containing [I]."
|
||||
I.loc = src
|
||||
@@ -77,7 +77,7 @@
|
||||
var/obj/item/I = contents[1]
|
||||
user.visible_message("[user] takes [I] out of [src]", "You take [I] out of [src].",\
|
||||
"You hear someone rustle around in a plastic bag, and remove something.")
|
||||
overlays.Cut() //remove the overlays
|
||||
cut_overlays() //remove the overlays
|
||||
|
||||
user.put_in_hands(I)
|
||||
stored_item = null
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
stored_alpha.Cut()
|
||||
if(reset_objects.len)
|
||||
for(var/obj/item/I in reset_objects)
|
||||
I.overlays -= I.blood_overlay
|
||||
I.cut_overlay(I.blood_overlay)
|
||||
if(I.fluorescent == 2) I.fluorescent = 1
|
||||
reset_objects.Cut()
|
||||
|
||||
@@ -66,5 +66,5 @@
|
||||
if(istype(A, /obj/item))
|
||||
var/obj/item/O = A
|
||||
if(O.was_bloodied && !(O.blood_overlay in O.overlays))
|
||||
O.overlays |= O.blood_overlay
|
||||
O.add_overlay(O.blood_overlay)
|
||||
reset_objects |= O
|
||||
@@ -379,7 +379,7 @@ log transactions
|
||||
if(!R.stamped)
|
||||
R.stamped = new
|
||||
R.stamped += /obj/item/weapon/stamp
|
||||
R.overlays += stampoverlay
|
||||
R.add_overlay(stampoverlay)
|
||||
R.stamps += "<HR><i>This paper has been stamped by the Automatic Teller Machine.</i>"
|
||||
|
||||
if(prob(50))
|
||||
@@ -421,7 +421,7 @@ log transactions
|
||||
if(!R.stamped)
|
||||
R.stamped = new
|
||||
R.stamped += /obj/item/weapon/stamp
|
||||
R.overlays += stampoverlay
|
||||
R.add_overlay(stampoverlay)
|
||||
R.stamps += "<HR><i>This paper has been stamped by the Automatic Teller Machine.</i>"
|
||||
|
||||
if(prob(50))
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
if(!R.stamped)
|
||||
R.stamped = new
|
||||
R.stamped += /obj/item/weapon/stamp
|
||||
R.overlays += stampoverlay
|
||||
R.add_overlay(stampoverlay)
|
||||
R.stamps += "<HR><i>This paper has been stamped by the Accounts Database.</i>"
|
||||
|
||||
//add the account
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
R.offset_y += 0
|
||||
R.ico += "paper_stamp-cent"
|
||||
R.stamped += /obj/item/weapon/stamp
|
||||
R.overlays += stampoverlay
|
||||
R.add_overlay(stampoverlay)
|
||||
R.stamps += "<HR><i>This paper has been stamped by the EFTPOS device.</i>"
|
||||
|
||||
/obj/item/device/eftpos/Destroy()
|
||||
@@ -64,7 +64,7 @@
|
||||
if(!R.stamped)
|
||||
R.stamped = new
|
||||
R.stamped += /obj/item/weapon/stamp
|
||||
R.overlays += stampoverlay
|
||||
R.add_overlay(stampoverlay)
|
||||
R.stamps += "<HR><i>This paper has been stamped by the EFTPOS device.</i>"
|
||||
var/obj/item/smallDelivery/D = new(R.loc)
|
||||
R.loc = D
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/spacecash/update_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
name = "[worth] [initial_name]\s"
|
||||
if(worth in list(1000,500,200,100,50,20,10,1))
|
||||
icon_state = "spacecash[worth]"
|
||||
@@ -53,14 +53,14 @@
|
||||
M.Translate(rand(-6, 6), rand(-4, 8))
|
||||
M.Turn(pick(-45, -27.5, 0, 0, 0, 0, 0, 0, 0, 27.5, 45))
|
||||
banknote.transform = M
|
||||
src.overlays += banknote
|
||||
add_overlay(banknote)
|
||||
if(num == 0) // Less than one thaler, let's just make it look like 1 for ease
|
||||
var/image/banknote = image('icons/obj/items.dmi', "spacecash1")
|
||||
var/matrix/M = matrix()
|
||||
M.Translate(rand(-6, 6), rand(-4, 8))
|
||||
M.Turn(pick(-45, -27.5, 0, 0, 0, 0, 0, 0, 0, 27.5, 45))
|
||||
banknote.transform = M
|
||||
src.overlays += banknote
|
||||
add_overlay(banknote)
|
||||
src.desc = "They are worth [worth] [initial_name]s."
|
||||
|
||||
/obj/item/weapon/spacecash/proc/adjust_worth(var/adjust_worth = 0, var/update = 1)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
if(cash_stored)
|
||||
spawn_money(cash_stored, loc, user)
|
||||
cash_stored = 0
|
||||
overlays -= "register_cash"
|
||||
cut_overlay("register_cash")
|
||||
else
|
||||
open_cash_box()
|
||||
else
|
||||
@@ -181,7 +181,7 @@
|
||||
if(cash_open)
|
||||
to_chat(user, "You neatly sort the cash into the box.")
|
||||
cash_stored += SC.worth
|
||||
overlays |= "register_cash"
|
||||
add_overlay("register_cash")
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.drop_from_inventory(SC)
|
||||
@@ -468,15 +468,15 @@
|
||||
|
||||
if(cash_open)
|
||||
cash_open = 0
|
||||
overlays -= "register_approve"
|
||||
overlays -= "register_open"
|
||||
overlays -= "register_cash"
|
||||
cut_overlay("register_approve")
|
||||
cut_overlay("register_open")
|
||||
cut_overlay("register_cash")
|
||||
else if(!cash_locked)
|
||||
cash_open = 1
|
||||
overlays += "register_approve"
|
||||
overlays += "register_open"
|
||||
add_overlay("register_approve")
|
||||
add_overlay("register_open")
|
||||
if(cash_stored)
|
||||
overlays += "register_cash"
|
||||
add_overlay("register_cash")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>The cash box is locked.</span>")
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
to_chat(user, "<span class='notice'>There already is a string attached to this coin.</span>")
|
||||
return
|
||||
if (CC.use(1))
|
||||
overlays += image('icons/obj/items.dmi',"coin_string_overlay")
|
||||
add_overlay("coin_string_overlay")
|
||||
string_attached = 1
|
||||
to_chat(user, "<span class='notice'>You attach a string to the coin.</span>")
|
||||
else
|
||||
@@ -79,7 +79,7 @@
|
||||
var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc)
|
||||
CC.amount = 1
|
||||
CC.update_icon()
|
||||
overlays = list()
|
||||
cut_overlays()
|
||||
string_attached = null
|
||||
to_chat(user, "<font color='blue'>You detach the string from the coin.</font>")
|
||||
else ..()
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
//Weird coins that I would prefer didn't work with normal vending machines. Might use them to make weird vending machines later.
|
||||
|
||||
/obj/item/weapon/aliencoin
|
||||
icon = 'icons/obj/aliencoins.dmi'
|
||||
name = "curious coin"
|
||||
desc = "A curious triangular coin made primarily of some kind of dark, smooth metal. "
|
||||
icon_state = "triangle"
|
||||
randpixel = 8
|
||||
force = 0.5
|
||||
throwforce = 0.5
|
||||
w_class = ITEMSIZE_TINY
|
||||
slot_flags = SLOT_EARS
|
||||
var/sides = 2
|
||||
var/value = 1
|
||||
drop_sound = 'sound/items/drop/ring.ogg'
|
||||
pickup_sound = 'sound/items/pickup/ring.ogg'
|
||||
|
||||
/obj/item/weapon/aliencoin/New()
|
||||
randpixel_xy()
|
||||
|
||||
/obj/item/weapon/aliencoin/gold
|
||||
name = "curious coin"
|
||||
icon_state = "triangle-g"
|
||||
desc = "A curious triangular coin made primarily of some kind of dark, smooth metal. This one's markings appear to reveal a golden material underneath."
|
||||
value = 3
|
||||
|
||||
/obj/item/weapon/aliencoin/silver
|
||||
name = "curious coin"
|
||||
icon_state = "triangle-s"
|
||||
desc = "A curious triangular coin made primarily of some kind of dark, smooth metal. This one's markings appear to reveal a silver material underneath."
|
||||
value = 2
|
||||
|
||||
/obj/item/weapon/aliencoin/phoron
|
||||
name = "curious coin"
|
||||
icon_state = "triangle-p"
|
||||
desc = "A curious triangular coin made primarily of some kind of dark, smooth metal. This one's markings appear to reveal a purple material underneath."
|
||||
value = 4
|
||||
|
||||
|
||||
/obj/item/weapon/aliencoin/attack_self(mob/user as mob)
|
||||
var/result = rand(1, sides)
|
||||
var/comment = ""
|
||||
if(result == 1)
|
||||
comment = "tails"
|
||||
else if(result == 2)
|
||||
comment = "heads"
|
||||
user.visible_message("<span class='notice'>[user] has thrown [src]. It lands on [comment]! </span>", runemessage = "[src] landed on [comment]")
|
||||
if(rand(1,20) == 1)
|
||||
user.visible_message("<span class='notice'>[user] fumbled the [src]!</span>", runemessage = "fumbles [src]")
|
||||
user.remove_from_mob(src)
|
||||
|
||||
/obj/item/weapon/aliencoin/examine(var/mob/user)
|
||||
. = ..()
|
||||
if(Adjacent(user))
|
||||
. += "<span class='notice'>It has some writing along its edge that seems to be some language that you are not familiar with. The face of the coin is very smooth, with what appears to be some kind of angular logo along the left side, and a couple of lines of the alien text along the opposite side. The reverse side is similarly smooth, the top of it features what appears to be some kind of vortex, surrounded by six stars, three on either side, with further swirls and intricate patterns along the bottom sections of this face. Looking closely, you can see that there is more text hidden among the swirls.</span>"
|
||||
@@ -12,7 +12,7 @@
|
||||
emote_message_radio_synthetic = emote_message_synthetic_3p
|
||||
|
||||
/decl/emote/audible/deathgasp_alien
|
||||
key = "deathgasp"
|
||||
key = "adeathgasp"
|
||||
emote_message_3p = "lets out a waning guttural screech, green blood bubbling from its maw."
|
||||
|
||||
/decl/emote/audible/whimper
|
||||
@@ -29,7 +29,7 @@
|
||||
emote_message_3p = "scretches."
|
||||
|
||||
/decl/emote/audible/choke
|
||||
key ="choke"
|
||||
key = "choke"
|
||||
emote_message_3p = "chokes."
|
||||
conscious = FALSE
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
emote_message_3p = "boops."
|
||||
|
||||
/decl/emote/audible/beep
|
||||
key = "beep"
|
||||
key = "bbeep"
|
||||
emote_message_3p = "You beep."
|
||||
emote_message_3p = "beeps."
|
||||
emote_sound = 'sound/machines/twobeep.ogg'
|
||||
@@ -133,18 +133,18 @@
|
||||
emote_message_3p = "grunts."
|
||||
|
||||
/decl/emote/audible/bug_hiss
|
||||
key ="hiss"
|
||||
key = "bhiss"
|
||||
emote_message_3p_target = "hisses at TARGET."
|
||||
emote_message_3p = "hisses."
|
||||
emote_sound = 'sound/voice/BugHiss.ogg'
|
||||
|
||||
/decl/emote/audible/bug_buzz
|
||||
key ="buzz"
|
||||
key = "bbuzz"
|
||||
emote_message_3p = "buzzes its wings."
|
||||
emote_sound = 'sound/voice/BugBuzz.ogg'
|
||||
|
||||
/decl/emote/audible/bug_chitter
|
||||
key ="chitter"
|
||||
key = "chitter"
|
||||
emote_message_3p = "chitters."
|
||||
emote_sound = 'sound/voice/Bug.ogg'
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
emote_sound = 'sound/voice/teshsqueak.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
|
||||
|
||||
/decl/emote/audible/teshchirp
|
||||
key = "tchirp" // VOREStation Edit
|
||||
key = "tchirp"
|
||||
emote_message_1p = "You chirp!"
|
||||
emote_message_3p = "chirps!"
|
||||
emote_message_1p_target = "You chirp at TARGET!"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
return "You [H.species.scream_verb_1p]!"
|
||||
. = ..()
|
||||
|
||||
/decl/emote/audible/cough/get_emote_message_3p(var/atom/user, var/atom/target, var/extra_params)
|
||||
/decl/emote/audible/scream/get_emote_message_3p(var/atom/user, var/atom/target, var/extra_params)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
return "[H.species.scream_verb_3p]!"
|
||||
|
||||
@@ -12,21 +12,21 @@
|
||||
return ..() && isslime(user)
|
||||
|
||||
/decl/emote/slime/pout
|
||||
key = "pout"
|
||||
key = "mpout"
|
||||
mood = "pout"
|
||||
|
||||
/decl/emote/slime/sad
|
||||
key = "sad"
|
||||
key = "msad"
|
||||
mood = "sad"
|
||||
|
||||
/decl/emote/slime/angry
|
||||
key = "angry"
|
||||
key = "mangry"
|
||||
mood = "angry"
|
||||
|
||||
/decl/emote/slime/frown
|
||||
key = "frown"
|
||||
key = "mfrown"
|
||||
mood = "mischevous"
|
||||
|
||||
/decl/emote/slime/smile
|
||||
key = "smile"
|
||||
key = "msmile"
|
||||
mood = ":3"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/decl/emote/visible
|
||||
key ="tail"
|
||||
key = "tail"
|
||||
emote_message_3p = "waves USER_THEIR tail."
|
||||
message_type = VISIBLE_MESSAGE
|
||||
|
||||
@@ -9,48 +9,48 @@
|
||||
emote_message_3p = "scratches."
|
||||
|
||||
/decl/emote/visible/drool
|
||||
key ="drool"
|
||||
key = "drool"
|
||||
emote_message_3p = "drools."
|
||||
conscious = FALSE
|
||||
|
||||
/decl/emote/visible/nod
|
||||
key ="nod"
|
||||
key = "nod"
|
||||
emote_message_3p_target = "nods USER_THEIR head at TARGET."
|
||||
emote_message_3p = "nods USER_THEIR head."
|
||||
|
||||
/decl/emote/visible/sway
|
||||
key ="sway"
|
||||
key = "sways"
|
||||
emote_message_3p = "sways around dizzily."
|
||||
|
||||
/decl/emote/visible/sulk
|
||||
key ="sulk"
|
||||
key = "sulk"
|
||||
emote_message_3p = "sulks down sadly."
|
||||
|
||||
/decl/emote/visible/dance
|
||||
key ="dance"
|
||||
key = "dance"
|
||||
check_restraints = TRUE
|
||||
emote_message_3p = "dances around happily."
|
||||
|
||||
/decl/emote/visible/roll
|
||||
key ="roll"
|
||||
key = "roll"
|
||||
check_restraints = TRUE
|
||||
emote_message_3p = "rolls."
|
||||
|
||||
/decl/emote/visible/shake
|
||||
key ="shake"
|
||||
key = "shake"
|
||||
emote_message_3p = "shakes USER_THEIR head."
|
||||
|
||||
/decl/emote/visible/jump
|
||||
key ="jump"
|
||||
key = "jump"
|
||||
emote_message_3p = "jumps!"
|
||||
|
||||
/decl/emote/visible/shiver
|
||||
key ="shiver"
|
||||
key = "shiver"
|
||||
emote_message_3p = "shivers."
|
||||
conscious = FALSE
|
||||
|
||||
/decl/emote/visible/collapse
|
||||
key ="collapse"
|
||||
key = "collapse"
|
||||
emote_message_3p = "collapses!"
|
||||
|
||||
/decl/emote/visible/collapse/do_extra(var/mob/user)
|
||||
@@ -216,7 +216,7 @@
|
||||
emote_message_3p = "vibrates!"
|
||||
|
||||
/decl/emote/visible/deathgasp_robot
|
||||
key = "deathgasp"
|
||||
key = "rdeathgasp"
|
||||
emote_message_3p = "shudders violently for a moment, then becomes motionless, USER_THEIR eyes slowly darkening."
|
||||
|
||||
/decl/emote/visible/handshake
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
return
|
||||
|
||||
if(!use_emote.mob_can_use(src))
|
||||
to_chat(src, SPAN_WARNING("You cannot use the emote '[act]'. Type <b>say *help</b> for a list of usable emotes."))
|
||||
to_chat(src, SPAN_WARNING("You cannot use the emote '[act]'. Type <b>say *help</b> for a list of usable emotes."))
|
||||
return
|
||||
|
||||
if(m_type != use_emote.message_type && use_emote.conscious && stat != CONSCIOUS)
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
|
||||
/obj/item/weapon/material/fishing_net/update_icon() // Also updates name and desc
|
||||
underlays.Cut()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
|
||||
..()
|
||||
|
||||
|
||||
@@ -78,10 +78,10 @@
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/material/fishing_rod/update_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
..()
|
||||
if(strung)
|
||||
overlays += image(icon, "[icon_state]_string")
|
||||
add_overlay("[icon_state]_string")
|
||||
|
||||
/obj/item/weapon/material/fishing_rod/proc/update_bait()
|
||||
if(istype(Bait, bait_type))
|
||||
|
||||
@@ -118,8 +118,8 @@
|
||||
glass_center_of_mass = list("x"=16, "y"=8)
|
||||
glass_icon_file = 'icons/obj/drinks_vr.dmi'
|
||||
|
||||
/datum/reagent/ethanol/pink_moo
|
||||
glass_icon_state = "pinkmooglass"
|
||||
/datum/reagent/ethanol/pink_russian
|
||||
glass_icon_state = "pinkrussianglass"
|
||||
glass_center_of_mass = list("x"=16, "y"=9)
|
||||
glass_icon_file = 'icons/obj/drinks_vr.dmi'
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
matter = list("glass" = 175)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass/on_reagent_change()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
|
||||
if(reagents.total_volume)
|
||||
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]1")
|
||||
@@ -129,7 +129,7 @@
|
||||
if(8 to INFINITY) filling.icon_state = "[icon_state]12"
|
||||
|
||||
filling.color += reagents.get_color()
|
||||
overlays += filling
|
||||
add_overlay(filling)
|
||||
name = "shot glass of " + reagents.get_master_reagent_name() //No matter what, the glass will tell you the reagent's name. Might be too abusable in the future.
|
||||
else
|
||||
name = "shot glass"
|
||||
@@ -146,7 +146,7 @@
|
||||
icon_state = pick("fitness-cup_black", "fitness-cup_red", "fitness-cup_black")
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/on_reagent_change()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
|
||||
if(reagents.total_volume)
|
||||
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "fitness-cup10")
|
||||
@@ -164,7 +164,7 @@
|
||||
if(90 to INFINITY) filling.icon_state = "fitness-cup100"
|
||||
|
||||
filling.color += reagents.get_color()
|
||||
overlays += filling
|
||||
add_overlay(filling)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/proteinshake
|
||||
name = "protein shake"
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
var/fullname = "" //We need to build this from the contents of the var.
|
||||
var/i = 0
|
||||
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
|
||||
for(var/obj/item/weapon/reagent_containers/food/snacks/O in ingredients)
|
||||
|
||||
@@ -62,12 +62,12 @@
|
||||
I.color = O.filling_color
|
||||
I.pixel_x = pick(list(-1,0,1))
|
||||
I.pixel_y = (i*2)+1
|
||||
overlays += I
|
||||
add_overlay(I)
|
||||
|
||||
var/image/T = new(src.icon, "sandwich_top")
|
||||
T.pixel_x = pick(list(-1,0,1))
|
||||
T.pixel_y = (ingredients.len * 2)+1
|
||||
overlays += T
|
||||
add_overlay(T)
|
||||
|
||||
name = lowertext("[fullname] sandwich")
|
||||
if(length(name) > 80) name = "[pick(list("absurd","colossal","enormous","ridiculous"))] sandwich"
|
||||
|
||||
+245
-517
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
||||
// Chaos cake
|
||||
|
||||
/datum/recipe/chaoscake_layerone
|
||||
reagents = list("flour" = 300,"milk" = 200, "sugar" = 100, "egg" = 30)
|
||||
fruit = list("poisonberries" = 15, "cherries" = 15)
|
||||
reagents = list("flour" = 30,"milk" = 20, "sugar" = 10, "egg" = 9)
|
||||
fruit = list("poisonberries" = 2, "cherries" = 2)
|
||||
items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/,
|
||||
@@ -12,8 +12,8 @@
|
||||
result = /obj/structure/chaoscake
|
||||
|
||||
/datum/recipe/chaoscake_layertwo
|
||||
reagents = list("flour" = 300, "milk" = 200, "sugar" = 100, "egg" = 30, )
|
||||
fruit = list("vanilla" = 15, "banana" = 15)
|
||||
reagents = list("flour" = 30, "milk" = 20, "sugar" = 10, "egg" = 9, )
|
||||
fruit = list("vanilla" = 2, "banana" = 2)
|
||||
items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
@@ -23,8 +23,8 @@
|
||||
result = /obj/item/weapon/chaoscake_layer
|
||||
|
||||
/datum/recipe/chaoscake_layerthree
|
||||
reagents = list("flour" = 240, "milk" = 150, "sugar" = 80, "egg" = 24, "deathbell" = 100)
|
||||
fruit = list("grapes" = 30)
|
||||
reagents = list("flour" = 25, "milk" = 15, "sugar" = 10, "egg" = 6, "deathbell" = 10)
|
||||
fruit = list("grapes" = 3)
|
||||
items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
@@ -33,8 +33,8 @@
|
||||
result = /obj/item/weapon/chaoscake_layer/three
|
||||
|
||||
/datum/recipe/chaoscake_layerfour
|
||||
reagents = list("flour" = 240, "milk" = 150, "sugar" = 80, "egg" = 24, "milkshake" = 300)
|
||||
fruit = list("rice" = 30)
|
||||
reagents = list("flour" = 25, "milk" = 15, "sugar" = 10, "egg" = 6, "milkshake" = 30)
|
||||
fruit = list("rice" = 3)
|
||||
items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
@@ -43,14 +43,14 @@
|
||||
result = /obj/item/weapon/chaoscake_layer/four
|
||||
|
||||
/datum/recipe/chaoscake_layerfive
|
||||
reagents = list("flour" = 180, "milk" = 100, "sugar" = 60, "egg" = 18, "blood" = 300)
|
||||
fruit = list("tomato" = 20)
|
||||
reagents = list("flour" = 20, "milk" = 10, "sugar" = 10, "egg" = 6, "blood" = 30)
|
||||
fruit = list("tomato" = 2)
|
||||
items = list() //supposed to be made with lobster, still has to be ported.
|
||||
result = /obj/item/weapon/chaoscake_layer/five
|
||||
|
||||
/datum/recipe/chaoscake_layersix
|
||||
reagents = list("flour" = 180, "milk" = 100, "sugar" = 60, "egg" = 18, "sprinkles" = 10)
|
||||
fruit = list("apple" = 30)
|
||||
reagents = list("flour" = 20, "milk" = 10, "sugar" = 10, "egg" = 6, "sprinkles" = 5)
|
||||
fruit = list("apple" = 2)
|
||||
items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
@@ -62,8 +62,8 @@
|
||||
result = /obj/item/weapon/chaoscake_layer/six
|
||||
|
||||
/datum/recipe/chaoscake_layerseven
|
||||
reagents = list("flour" = 120, "milk" = 50, "sugar" = 40, "egg" = 12, "devilskiss" = 200)
|
||||
fruit = list("potato" = 10)
|
||||
reagents = list("flour" = 15, "milk" = 10, "sugar" = 5, "egg" = 3, "devilskiss" = 20)
|
||||
fruit = list("potato" = 1)
|
||||
items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
@@ -72,8 +72,8 @@
|
||||
result = /obj/item/weapon/chaoscake_layer/seven
|
||||
|
||||
/datum/recipe/chaoscake_layereight
|
||||
reagents = list("flour" = 120, "milk" = 50, "sugar" = 40, "egg" = 12, "cream" = 200)
|
||||
fruit = list("lemon" = 10)
|
||||
reagents = list("flour" = 15, "milk" = 10, "sugar" = 5, "egg" = 3, "cream" = 20)
|
||||
fruit = list("lemon" = 1)
|
||||
items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
@@ -82,8 +82,8 @@
|
||||
result = /obj/item/weapon/chaoscake_layer/eight
|
||||
|
||||
/datum/recipe/chaoscake_layernine
|
||||
reagents = list("water" = 100, "blood" = 100)
|
||||
fruit = list("goldapple" = 50)
|
||||
reagents = list("water" = 10, "blood" = 10)
|
||||
fruit = list("goldapple" = 1)
|
||||
items = list()
|
||||
result = /obj/item/weapon/chaoscake_layer/nine
|
||||
|
||||
|
||||
@@ -55,14 +55,14 @@ var/global/ingredientLimit = 20
|
||||
ingredients += S
|
||||
|
||||
if(src.addTop)
|
||||
overlays -= topping //thank you Comic
|
||||
if(!fullyCustom && !stackIngredients && overlays.len)
|
||||
overlays -= filling //we can't directly modify the overlay, so we have to remove it and then add it again
|
||||
cut_overlay(topping)
|
||||
if(!fullyCustom && !stackIngredients && our_overlays.len)
|
||||
cut_overlay(filling) //we can't directly modify the overlay, so we have to remove it and then add it again
|
||||
var/newcolor = S.filling_color != "#FFFFFF" ? S.filling_color : AverageColor(getFlatIcon(S, S.dir, 0), 1, 1)
|
||||
filling.color = BlendRGB(filling.color, newcolor, 1/ingredients.len)
|
||||
overlays += filling
|
||||
add_overlay(filling)
|
||||
else
|
||||
overlays += generateFilling(S)
|
||||
add_overlay(generateFilling(S))
|
||||
if(addTop)
|
||||
drawTopping()
|
||||
|
||||
@@ -129,7 +129,7 @@ var/global/ingredientLimit = 20
|
||||
/obj/item/weapon/reagent_containers/food/snacks/customizable/proc/drawTopping()
|
||||
var/image/I = topping
|
||||
I.pixel_y = (ingredients.len+1)*2
|
||||
overlays += I
|
||||
add_overlay(I)
|
||||
|
||||
|
||||
// Sandwiches //////////////////////////////////////////////////
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
icon_state = "bottle-[rand(1,4)]"
|
||||
|
||||
/obj/item/weapon/reagent_containers/glass/bottle/update_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
|
||||
if(reagents.total_volume && (icon_state == "bottle-1" || icon_state == "bottle-2" || icon_state == "bottle-3" || icon_state == "bottle-4"))
|
||||
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10")
|
||||
@@ -51,11 +51,11 @@
|
||||
if(91 to INFINITY) filling.icon_state = "[icon_state]-100"
|
||||
|
||||
filling.color = reagents.get_color()
|
||||
overlays += filling
|
||||
add_overlay(filling)
|
||||
|
||||
if (!is_open_container())
|
||||
var/image/lid = image(icon, src, "lid_bottle")
|
||||
overlays += lid
|
||||
add_overlay(lid)
|
||||
|
||||
/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline
|
||||
name = "inaprovaline bottle"
|
||||
|
||||
@@ -36,10 +36,10 @@
|
||||
|
||||
var/image/food_image = image(CI.object.icon, CI.object.icon_state)
|
||||
food_image.color = CI.object.color
|
||||
food_image.overlays += CI.object.overlays
|
||||
food_image.add_overlay(CI.object.overlays)
|
||||
food_image.transform *= 0.7
|
||||
|
||||
product.overlays += food_image
|
||||
product.add_overlay(food_image)
|
||||
*/
|
||||
|
||||
/obj/machinery/appliance/mixer/cereal/update_icon()
|
||||
@@ -83,4 +83,4 @@
|
||||
|
||||
result.color = result.filling_color
|
||||
for (var/i in images)
|
||||
result.overlays += images[i]
|
||||
result.add_overlay(images[i])
|
||||
|
||||
@@ -58,20 +58,20 @@
|
||||
|
||||
/obj/machinery/gibber/New()
|
||||
..()
|
||||
src.overlays += image('icons/obj/kitchen.dmi', "grjam")
|
||||
add_overlay("grjam")
|
||||
|
||||
/obj/machinery/gibber/update_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
if (dirty)
|
||||
src.overlays += image('icons/obj/kitchen.dmi', "grbloody")
|
||||
add_overlay("grbloody")
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
if (!occupant)
|
||||
src.overlays += image('icons/obj/kitchen.dmi', "grjam")
|
||||
add_overlay("grjam")
|
||||
else if (operating)
|
||||
src.overlays += image('icons/obj/kitchen.dmi', "gruse")
|
||||
add_overlay("gruse")
|
||||
else
|
||||
src.overlays += image('icons/obj/kitchen.dmi', "gridle")
|
||||
add_overlay("gridle")
|
||||
|
||||
/obj/machinery/gibber/relaymove(mob/user as mob)
|
||||
src.go_out()
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/icecream/proc/add_ice_cream(var/flavour_name)
|
||||
name = "[flavour_name] icecream"
|
||||
src.overlays += "icecream_[flavour_name]"
|
||||
add_overlay("icecream_[flavour_name]")
|
||||
desc = "Delicious [cone_type] cone with a dollop of [flavour_name] ice cream."
|
||||
ice_creamed = 1
|
||||
|
||||
|
||||
@@ -314,20 +314,18 @@
|
||||
|
||||
// When exact is false, extraneous ingredients are ignored
|
||||
// When exact is true, extraneous ingredients will fail the recipe
|
||||
// In both cases, the full complement of required inredients is still needed
|
||||
// In both cases, the full set of required ingredients is still needed
|
||||
/proc/select_recipe(var/list/datum/recipe/available_recipes, var/obj/obj as obj, var/exact)
|
||||
var/list/datum/recipe/possible_recipes = list()
|
||||
var/highest_count = 0
|
||||
var/count = 0
|
||||
for (var/datum/recipe/recipe in available_recipes)
|
||||
if(!recipe.check_reagents(obj.reagents, exact) || !recipe.check_items(obj, exact) || !recipe.check_fruit(obj, exact))
|
||||
continue
|
||||
possible_recipes |= recipe
|
||||
if (!possible_recipes.len)
|
||||
return null
|
||||
else if (possible_recipes.len == 1)
|
||||
return possible_recipes[1]
|
||||
else //okay, let's select the most complicated recipe
|
||||
sortTim(possible_recipes, /proc/cmp_recipe_complexity_dsc)
|
||||
return possible_recipes[1]
|
||||
// Taken from cmp_recipe_complexity_dsc, but is way faster.
|
||||
count = LAZYLEN(recipe.items) + LAZYLEN(recipe.reagents) + LAZYLEN(recipe.fruit)
|
||||
if(count >= highest_count)
|
||||
highest_count = count
|
||||
. = recipe
|
||||
|
||||
// Both of these are just placeholders to allow special behavior for mob holders, but you can do other things in here later if you feel like it.
|
||||
/datum/recipe/proc/before_cook(obj/container) // Called Before the Microwave starts delays and cooking stuff
|
||||
|
||||
@@ -410,7 +410,7 @@
|
||||
name = "a playing card"
|
||||
desc = "A playing card."
|
||||
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
|
||||
|
||||
if(cards.len == 1)
|
||||
@@ -418,7 +418,7 @@
|
||||
var/image/I = new(src.icon, (concealed ? "[P.back_icon]" : "[P.card_icon]") )
|
||||
I.pixel_x += (-5+rand(10))
|
||||
I.pixel_y += (-5+rand(10))
|
||||
overlays += I
|
||||
add_overlay(I)
|
||||
return
|
||||
|
||||
var/offset = FLOOR(20/cards.len, 1)
|
||||
@@ -450,7 +450,7 @@
|
||||
else
|
||||
I.pixel_x = -7+(offset*i)
|
||||
I.transform = M
|
||||
overlays += I
|
||||
add_overlay(I)
|
||||
i++
|
||||
|
||||
/obj/item/weapon/hand/dropped(mob/user as mob)
|
||||
|
||||
@@ -20,15 +20,15 @@
|
||||
legend.pixel_x = HOLOMAP_LEGEND_X(T.z)
|
||||
legend.pixel_y = HOLOMAP_LEGEND_Y(T.z)
|
||||
|
||||
station_map.overlays |= cursor
|
||||
station_map.overlays |= legend
|
||||
station_map.add_overlay(cursor)
|
||||
station_map.add_overlay(legend)
|
||||
|
||||
/datum/station_holomap/proc/initialize_holomap_bogus()
|
||||
station_map = image('icons/480x480.dmi', "stationmap")
|
||||
legend = image('icons/effects/64x64.dmi', "notfound")
|
||||
legend.pixel_x = 7 * WORLD_ICON_SIZE
|
||||
legend.pixel_y = 7 * WORLD_ICON_SIZE
|
||||
station_map.overlays |= legend
|
||||
station_map.add_overlay(legend)
|
||||
|
||||
// TODO - Strategic Holomap support
|
||||
// /datum/station_holomap/strategic/initialize_holomap(var/turf/T, var/isAI=null, var/mob/user=null)
|
||||
@@ -37,4 +37,4 @@
|
||||
// legend = image('icons/effects/64x64.dmi', "strategic")
|
||||
// legend.pixel_x = 3*WORLD_ICON_SIZE
|
||||
// legend.pixel_y = 3*WORLD_ICON_SIZE
|
||||
// station_map.overlays |= legend
|
||||
// station_map.add_overlay(legend)
|
||||
|
||||
@@ -265,7 +265,7 @@
|
||||
markerImage.appearance_flags = RESET_COLOR|PIXEL_SCALE
|
||||
markerImage.pixel_x = holomarker.x+holomarker.offset_x
|
||||
markerImage.pixel_y = holomarker.y+holomarker.offset_y
|
||||
map_app.overlays += markerImage
|
||||
map_app.add_overlay(markerImage)
|
||||
|
||||
var/obj/screen/mapper/map/tmp = new()
|
||||
tmp.appearance = map_app
|
||||
@@ -286,13 +286,10 @@
|
||||
continue
|
||||
var/mob_indicator = HOLOMAP_ERROR
|
||||
var/turf/TU = get_turf(HC)
|
||||
if(TU.z != T_z)
|
||||
// Mapper not on a turf or elsewhere
|
||||
if(!TU || (TU.z != T_z))
|
||||
continue
|
||||
|
||||
// Marker not on a turf
|
||||
if(!TU)
|
||||
continue
|
||||
|
||||
|
||||
// We're the marker
|
||||
if(HC == src)
|
||||
mob_indicator = HOLOMAP_YOU
|
||||
@@ -342,26 +339,27 @@
|
||||
handle_marker(mark,TU.x,TU.y)
|
||||
extras += mark
|
||||
|
||||
// Marker beacon items
|
||||
for(var/hb in mapping_beacons)
|
||||
var/obj/item/device/holomap_beacon/HB = hb
|
||||
if(HB.mapper_filter != mapper_filter)
|
||||
continue
|
||||
|
||||
var/turf/TB = get_turf(HB)
|
||||
if(TU.z != T_z)
|
||||
continue
|
||||
|
||||
var/marker_cache_key = "\ref[HB]_marker"
|
||||
if(!(marker_cache_key in icon_image_cache))
|
||||
var/obj/screen/mapper/marker/mark = new()
|
||||
mark.icon_state = "beacon"
|
||||
mark.layer = 1
|
||||
icon_image_cache[marker_cache_key] = mark
|
||||
|
||||
var/obj/screen/mapper/marker/mark = icon_image_cache[marker_cache_key]
|
||||
handle_marker(mark,TB.x,TB.y)
|
||||
extras += mark
|
||||
// Marker beacon items
|
||||
for(var/hb in mapping_beacons)
|
||||
var/obj/item/device/holomap_beacon/HB = hb
|
||||
if(HB.mapper_filter != mapper_filter)
|
||||
continue
|
||||
|
||||
var/turf/TB = get_turf(HB)
|
||||
// Marker beacon not on a turf or elsewhere
|
||||
if(!TB || (TB.z != T_z))
|
||||
continue
|
||||
|
||||
var/marker_cache_key = "\ref[HB]_marker"
|
||||
if(!(marker_cache_key in icon_image_cache))
|
||||
var/obj/screen/mapper/marker/mark = new()
|
||||
mark.icon_state = "beacon"
|
||||
mark.layer = 1
|
||||
icon_image_cache[marker_cache_key] = mark
|
||||
|
||||
var/obj/screen/mapper/marker/mark = icon_image_cache[marker_cache_key]
|
||||
handle_marker(mark,TB.x,TB.y)
|
||||
extras += mark
|
||||
|
||||
if(badmap)
|
||||
var/obj/O = icon_image_cache["bad"]
|
||||
@@ -419,7 +417,7 @@
|
||||
else
|
||||
in_list = FALSE
|
||||
mapping_beacons -= src
|
||||
icon_state = initial(icon_state) + in_list ? "_on" : ""
|
||||
icon_state = "[initial(icon_state)][in_list ? "_on" : ""]"
|
||||
to_chat(user,SPAN_NOTICE("The [src] is now [in_list ? "broadcasting" : "disabled"]."))
|
||||
|
||||
/obj/item/device/holomap_beacon/Destroy()
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
if(!holomap_datum)
|
||||
return //Not yet.
|
||||
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "station_mapb"
|
||||
else if((stat & NOPOWER) || !anchored)
|
||||
@@ -180,8 +180,8 @@
|
||||
if(bogus)
|
||||
holomap_datum.initialize_holomap_bogus()
|
||||
else
|
||||
small_station_map.icon = SSholomaps.extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPSMALL]_[original_zLevel]"]
|
||||
overlays |= small_station_map
|
||||
small_station_map = image(SSholomaps.extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPSMALL]_[original_zLevel]"], dir = src.dir)
|
||||
add_overlay(small_station_map)
|
||||
holomap_datum.initialize_holomap(get_turf(src))
|
||||
|
||||
// Put the little "map" overlay down where it looks nice
|
||||
@@ -189,12 +189,12 @@
|
||||
floor_markings.dir = src.dir
|
||||
floor_markings.pixel_x = -src.pixel_x
|
||||
floor_markings.pixel_y = -src.pixel_y
|
||||
overlays += floor_markings
|
||||
add_overlay(floor_markings)
|
||||
|
||||
if(panel_open)
|
||||
overlays += "station_map-panel"
|
||||
add_overlay("station_map-panel")
|
||||
else
|
||||
overlays -= "station_map-panel"
|
||||
cut_overlay("station_map-panel")
|
||||
|
||||
/obj/machinery/station_map/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
src.add_fingerprint(user)
|
||||
|
||||
@@ -13,22 +13,22 @@
|
||||
var/maxFrames = 5
|
||||
|
||||
/obj/machinery/beehive/update_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
icon_state = "beehive"
|
||||
if(closed)
|
||||
overlays += "lid"
|
||||
add_overlay("lid")
|
||||
if(frames)
|
||||
overlays += "empty[frames]"
|
||||
add_overlay("empty[frames]")
|
||||
if(honeycombs >= 100)
|
||||
overlays += "full[round(honeycombs / 100)]"
|
||||
add_overlay("full[round(honeycombs / 100)]")
|
||||
if(!smoked)
|
||||
switch(bee_count)
|
||||
if(1 to 40)
|
||||
overlays += "bees1"
|
||||
add_overlay("bees1")
|
||||
if(41 to 80)
|
||||
overlays += "bees2"
|
||||
add_overlay("bees2")
|
||||
if(81 to 100)
|
||||
overlays += "bees3"
|
||||
add_overlay("bees3")
|
||||
|
||||
/obj/machinery/beehive/examine(var/mob/user)
|
||||
. = ..()
|
||||
@@ -217,7 +217,7 @@
|
||||
|
||||
/obj/item/honey_frame/filled/New()
|
||||
..()
|
||||
overlays += "honeycomb"
|
||||
add_overlay("honeycomb")
|
||||
|
||||
/obj/item/beehive_assembly
|
||||
name = "beehive assembly"
|
||||
@@ -269,18 +269,18 @@ var/global/list/datum/stack_recipe/wax_recipes = list( \
|
||||
|
||||
/obj/item/bee_pack/New()
|
||||
..()
|
||||
overlays += "beepack-full"
|
||||
add_overlay("beepack-full")
|
||||
|
||||
/obj/item/bee_pack/proc/empty()
|
||||
full = 0
|
||||
name = "empty bee pack"
|
||||
desc = "A stasis pack for moving bees. It's empty."
|
||||
overlays.Cut()
|
||||
overlays += "beepack-empty"
|
||||
cut_overlays()
|
||||
add_overlay("beepack-empty")
|
||||
|
||||
/obj/item/bee_pack/proc/fill()
|
||||
full = initial(full)
|
||||
name = initial(name)
|
||||
desc = initial(desc)
|
||||
overlays.Cut()
|
||||
overlays += "beepack-full"
|
||||
cut_overlays()
|
||||
add_overlay("beepack-full")
|
||||
@@ -125,7 +125,7 @@
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown/update_icon()
|
||||
if(!seed || !SSplants || !SSplants.plant_icon_cache)
|
||||
return
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
var/image/plant_icon
|
||||
var/icon_key = "fruit-[seed.get_trait(TRAIT_PRODUCT_ICON)]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"
|
||||
if(SSplants.plant_icon_cache[icon_key])
|
||||
@@ -134,13 +134,13 @@
|
||||
plant_icon = image('icons/obj/hydroponics_products.dmi',"blank")
|
||||
var/image/fruit_base = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-product")
|
||||
fruit_base.color = "[seed.get_trait(TRAIT_PRODUCT_COLOUR)]"
|
||||
plant_icon.overlays |= fruit_base
|
||||
plant_icon.add_overlay(fruit_base)
|
||||
if("[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf" in cached_icon_states('icons/obj/hydroponics_products.dmi'))
|
||||
var/image/fruit_leaves = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf")
|
||||
fruit_leaves.color = "[seed.get_trait(TRAIT_PLANT_COLOUR)]"
|
||||
plant_icon.overlays |= fruit_leaves
|
||||
add_overlay(fruit_leaves)
|
||||
SSplants.plant_icon_cache[icon_key] = plant_icon
|
||||
overlays |= plant_icon
|
||||
add_overlay(plant_icon)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown/Crossed(var/mob/living/M)
|
||||
if(M.is_incorporeal())
|
||||
@@ -363,9 +363,9 @@ var/list/fruit_icon_cache = list()
|
||||
var/image/I = image(icon,"fruit_rind")
|
||||
I.color = rind_colour
|
||||
fruit_icon_cache["rind-[rind_colour]"] = I
|
||||
overlays |= fruit_icon_cache["rind-[rind_colour]"]
|
||||
add_overlay(fruit_icon_cache["rind-[rind_colour]"])
|
||||
if(!fruit_icon_cache["slice-[rind_colour]"])
|
||||
var/image/I = image(icon,"fruit_slice")
|
||||
I.color = flesh_colour
|
||||
fruit_icon_cache["slice-[rind_colour]"] = I
|
||||
overlays |= fruit_icon_cache["slice-[rind_colour]"]
|
||||
add_overlay(fruit_icon_cache["slice-[rind_colour]"])
|
||||
|
||||
@@ -28,7 +28,7 @@ GLOBAL_LIST_BOILERPLATE(all_seed_packs, /obj/item/seeds)
|
||||
if(!seed) return
|
||||
|
||||
// Update icon.
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
var/is_seeds = ((seed.seed_noun in list("seeds","pits","nodes")) ? 1 : 0)
|
||||
var/image/seed_mask
|
||||
var/seed_base_key = "base-[is_seeds ? seed.get_trait(TRAIT_PLANT_COLOUR) : "spores"]"
|
||||
@@ -49,8 +49,8 @@ GLOBAL_LIST_BOILERPLATE(all_seed_packs, /obj/item/seeds)
|
||||
seed_overlay.color = seed.get_trait(TRAIT_PRODUCT_COLOUR)
|
||||
plant_seed_sprites[seed_overlay_key] = seed_overlay
|
||||
|
||||
overlays |= seed_mask
|
||||
overlays |= seed_overlay
|
||||
add_overlay(seed_mask)
|
||||
add_overlay(seed_overlay)
|
||||
|
||||
if(is_seeds)
|
||||
src.name = "packet of [seed.seed_name] [seed.seed_noun]"
|
||||
|
||||
@@ -405,9 +405,9 @@
|
||||
panel_open = !panel_open
|
||||
to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.")
|
||||
playsound(src, O.usesound, 50, 1)
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
if(panel_open)
|
||||
overlays += image(icon, "[initial(icon_state)]-panel")
|
||||
add_overlay("[initial(icon_state)]-panel")
|
||||
else if((O.is_wirecutter() || istype(O, /obj/item/device/multitool)) && panel_open)
|
||||
wires.Interact(user)
|
||||
|
||||
|
||||
@@ -100,14 +100,14 @@ a creative player the means to solve many problems. Circuits are held inside an
|
||||
data["power_draw_per_use"] = power_draw_per_use
|
||||
data["extended_desc"] = extended_desc
|
||||
|
||||
var/list/inputs = list()
|
||||
var/list/outputs = list()
|
||||
var/list/activators = list()
|
||||
var/list/inputs_list = list()
|
||||
var/list/outputs_list = list()
|
||||
var/list/activators_list = list()
|
||||
for(var/datum/integrated_io/io in inputs)
|
||||
inputs.Add(list(tgui_pin_data(io)))
|
||||
inputs_list.Add(list(tgui_pin_data(io)))
|
||||
|
||||
for(var/datum/integrated_io/io in outputs)
|
||||
outputs.Add(list(tgui_pin_data(io)))
|
||||
outputs_list.Add(list(tgui_pin_data(io)))
|
||||
|
||||
for(var/datum/integrated_io/io in activators)
|
||||
var/list/list/activator = list(
|
||||
@@ -124,11 +124,11 @@ a creative player the means to solve many problems. Circuits are held inside an
|
||||
"holder_name" = linked.holder.displayed_name,
|
||||
)))
|
||||
|
||||
activators.Add(list(activator))
|
||||
activators_list.Add(list(activator))
|
||||
|
||||
data["inputs"] = inputs
|
||||
data["outputs"] = outputs
|
||||
data["activators"] = activators
|
||||
data["inputs"] = inputs_list
|
||||
data["outputs"] = outputs_list
|
||||
data["activators"] = activators_list
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Internal atom that copies an appearance on to the blocker plane
|
||||
*
|
||||
* Copies an appearance vis render_target and render_source on to the emissive blocking plane.
|
||||
* This means that the atom in question will block any emissive sprites.
|
||||
* This should only be used internally. If you are directly creating more of these, you're
|
||||
* almost guaranteed to be doing something wrong.
|
||||
*/
|
||||
/atom/movable/emissive_blocker
|
||||
name = "emissive blocker"
|
||||
plane = PLANE_EMISSIVE
|
||||
layer = FLOAT_LAYER
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
//Why?
|
||||
//render_targets copy the transform of the target as well, but vis_contents also applies the transform
|
||||
//to what's in it. Applying RESET_TRANSFORM here makes vis_contents not apply the transform.
|
||||
//Since only render_target handles transform we don't get any applied transform "stacking"
|
||||
appearance_flags = RESET_TRANSFORM
|
||||
|
||||
/atom/movable/emissive_blocker/Initialize(mapload, source)
|
||||
. = ..()
|
||||
verbs.Cut() //Cargo culting from lighting object, this maybe affects memory usage?
|
||||
|
||||
render_source = source
|
||||
color = GLOB.em_block_color
|
||||
|
||||
|
||||
/atom/movable/emissive_blocker/ex_act(severity)
|
||||
return FALSE
|
||||
|
||||
/atom/movable/emissive_blocker/singularity_act()
|
||||
return
|
||||
|
||||
/atom/movable/emissive_blocker/singularity_pull()
|
||||
return
|
||||
|
||||
/atom/movable/emissive_blocker/blob_act()
|
||||
return
|
||||
|
||||
/atom/movable/emissive_blocker/onTransitZ()
|
||||
return
|
||||
|
||||
//Prevents people from moving these after creation, because they shouldn't be.
|
||||
/atom/movable/emissive_blocker/forceMove(atom/destination, no_tp=FALSE, harderforce = FALSE)
|
||||
if(harderforce)
|
||||
return ..()
|
||||
@@ -1,110 +1,218 @@
|
||||
/atom
|
||||
var/light_power = 1 // intensity of the light
|
||||
var/light_range = 0 // range in tiles of the light
|
||||
var/light_color // Hexadecimal RGB string representing the colour of the light
|
||||
///Light systems, both shouldn't be active at the same time.
|
||||
var/light_system = STATIC_LIGHT
|
||||
///Range of the light in tiles. Zero means no light.
|
||||
var/light_range = 0
|
||||
///Intensity of the light. The stronger, the less shadows you will see on the lit area.
|
||||
var/light_power = 1
|
||||
///Hexadecimal RGB string representing the colour of the light. White by default.
|
||||
var/light_color = COLOR_WHITE
|
||||
///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values.
|
||||
var/light_on = FALSE
|
||||
///Bitflags to determine lighting-related atom properties.
|
||||
var/light_flags = NONE
|
||||
///Our light source. Don't fuck with this directly unless you have a good reason!
|
||||
var/tmp/datum/light_source/light
|
||||
///Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list.
|
||||
var/tmp/list/light_sources
|
||||
|
||||
var/datum/light_source/light
|
||||
var/list/light_sources
|
||||
/atom/movable
|
||||
///Hint for directional light cone positioning. X is relevant when facing north/south (this setting is for south and inverted for north)
|
||||
var/light_cone_x_offset // When facing south, inverted when facing north
|
||||
///Hint for directional light cone positioning. Y is relevant when facing east/west (same value used for both east and west)
|
||||
var/light_cone_y_offset // When facing east/west, ignored for north/south (uses 16 in those cases)
|
||||
///Highest-intensity light affecting us, which determines our visibility.
|
||||
var/affecting_dynamic_lumi = 0
|
||||
///Lazylist to keep track on the sources of illumination.
|
||||
var/list/affected_dynamic_lights
|
||||
///Either FALSE, [EMISSIVE_BLOCK_GENERIC], or [EMISSIVE_BLOCK_UNIQUE]
|
||||
var/blocks_emissive = FALSE
|
||||
///Internal holder for emissive blocker object, do not use directly use blocks_emissive
|
||||
var/atom/movable/emissive_blocker/em_block
|
||||
|
||||
// Nonsensical value for l_color default, so we can detect if it gets set to null.
|
||||
// The proc you should always use to set the light of this atom.
|
||||
// Nonesensical value for l_color default, so we can detect if it gets set to null.
|
||||
#define NONSENSICAL_VALUE -99999
|
||||
/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE)
|
||||
. = 0 //make it less costly if nothing's changed
|
||||
/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE, l_on)
|
||||
if(l_range > 0 && l_range < MINIMUM_USEFUL_LIGHT_RANGE)
|
||||
l_range = MINIMUM_USEFUL_LIGHT_RANGE //Brings the range up to 1.4, which is just barely brighter than the soft lighting that surrounds players.
|
||||
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT, l_range, l_power, l_color, l_on) & COMPONENT_BLOCK_LIGHT_UPDATE)
|
||||
return
|
||||
|
||||
// Legacy behavior helper
|
||||
if(l_range == 0)
|
||||
l_on = FALSE
|
||||
else if(l_range > 0)
|
||||
l_on = TRUE
|
||||
|
||||
var/needs_update = FALSE
|
||||
if(!isnull(l_power) && l_power != light_power)
|
||||
if(!isnull(set_light_power(l_power)))
|
||||
needs_update = TRUE
|
||||
|
||||
if(!isnull(l_range) && l_range != light_range)
|
||||
if(!isnull(set_light_range(l_range)))
|
||||
needs_update = TRUE
|
||||
|
||||
if(l_power != null && l_power != light_power)
|
||||
light_power = l_power
|
||||
. = 1
|
||||
if(l_range != null && l_range != light_range)
|
||||
light_range = l_range
|
||||
. = 1
|
||||
if(l_color != NONSENSICAL_VALUE && l_color != light_color)
|
||||
light_color = l_color
|
||||
. = 1
|
||||
if(!isnull(set_light_color(l_color)))
|
||||
needs_update = TRUE
|
||||
|
||||
if(.) update_light()
|
||||
if(!isnull(l_on) && l_on != light_on)
|
||||
if(!isnull(set_light_on(l_on)))
|
||||
needs_update = TRUE
|
||||
|
||||
if(needs_update)
|
||||
update_light()
|
||||
|
||||
#undef NONSENSICAL_VALUE
|
||||
|
||||
// Will update the light (duh).
|
||||
// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf...
|
||||
/atom/proc/update_light()
|
||||
set waitfor = FALSE
|
||||
if (QDELETED(src))
|
||||
return
|
||||
|
||||
if(!light_power || !light_range)
|
||||
if(light)
|
||||
light.destroy()
|
||||
light = null
|
||||
if(light_system != STATIC_LIGHT)
|
||||
CRASH("update_light() for [src] with following light_system value: [light_system]")
|
||||
|
||||
if (!light_on || !light_power || !light_range) // We won't emit light anyways, destroy the light source.
|
||||
QDEL_NULL(light)
|
||||
else
|
||||
if(!istype(loc, /atom/movable))
|
||||
if (!ismovable(loc)) // We choose what atom should be the top atom of the light here.
|
||||
. = src
|
||||
else
|
||||
. = loc
|
||||
|
||||
if(light)
|
||||
if (light) // Update the light or create it if it does not exist.
|
||||
light.update(.)
|
||||
else
|
||||
light = new /datum/light_source(src, .)
|
||||
light = new/datum/light_source(src, .)
|
||||
|
||||
/atom/New()
|
||||
. = ..()
|
||||
|
||||
if(light_power && light_range)
|
||||
update_light()
|
||||
|
||||
if(opacity && isturf(loc))
|
||||
var/turf/T = loc
|
||||
T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guranteed to be on afterwards anyways.
|
||||
|
||||
/atom/Destroy()
|
||||
if(light)
|
||||
light.destroy()
|
||||
light = null
|
||||
return ..()
|
||||
|
||||
/atom/movable/Destroy()
|
||||
var/turf/T = loc
|
||||
if(opacity && istype(T))
|
||||
T.reconsider_lights()
|
||||
return ..()
|
||||
|
||||
/atom/movable/Moved(atom/old_loc, direction, forced = FALSE)
|
||||
. = ..()
|
||||
|
||||
for(var/datum/light_source/L in light_sources)
|
||||
L.source_atom.update_light()
|
||||
|
||||
var/turf/new_turf = loc
|
||||
var/turf/old_turf = old_loc
|
||||
if(istype(old_turf) && opacity)
|
||||
old_turf.reconsider_lights()
|
||||
|
||||
if(istype(new_turf) && opacity)
|
||||
new_turf.reconsider_lights()
|
||||
|
||||
/**
|
||||
* Updates the atom's opacity value.
|
||||
*
|
||||
* This exists to act as a hook for associated behavior.
|
||||
* It notifies (potentially) affected light sources so they can update (if needed).
|
||||
*/
|
||||
/atom/proc/set_opacity(new_opacity)
|
||||
if(new_opacity == opacity)
|
||||
return
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_SET_OPACITY, new_opacity)
|
||||
. = opacity
|
||||
opacity = new_opacity
|
||||
var/turf/T = isturf(src) ? src : loc
|
||||
if(!isturf(T))
|
||||
|
||||
|
||||
/atom/movable/set_opacity(new_opacity)
|
||||
. = ..()
|
||||
if(isnull(.) || !isturf(loc))
|
||||
return
|
||||
|
||||
if(new_opacity == TRUE)
|
||||
T.has_opaque_atom = TRUE
|
||||
T.reconsider_lights()
|
||||
if(opacity)
|
||||
AddElement(/datum/element/light_blocking)
|
||||
else
|
||||
var/old_has_opaque_atom = T.has_opaque_atom
|
||||
T.recalc_atom_opacity()
|
||||
if(old_has_opaque_atom != T.has_opaque_atom)
|
||||
T.reconsider_lights()
|
||||
RemoveElement(/datum/element/light_blocking)
|
||||
|
||||
/obj/item/equipped()
|
||||
. = ..()
|
||||
update_light()
|
||||
|
||||
/obj/item/pickup()
|
||||
/turf/set_opacity(new_opacity)
|
||||
. = ..()
|
||||
update_light()
|
||||
if(isnull(.))
|
||||
return
|
||||
recalculate_directional_opacity()
|
||||
|
||||
/obj/item/dropped()
|
||||
. = ..()
|
||||
update_light()
|
||||
/atom/proc/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION)
|
||||
return
|
||||
|
||||
|
||||
/turf/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION)
|
||||
if(!_duration)
|
||||
stack_trace("Lighting FX obj created on a turf without a duration")
|
||||
new /obj/effect/dummy/lighting_obj (src, _range, _power, _color, _duration)
|
||||
|
||||
|
||||
/obj/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION)
|
||||
if(!_duration)
|
||||
stack_trace("Lighting FX obj created on a obj without a duration")
|
||||
new /obj/effect/dummy/lighting_obj (get_turf(src), _range, _power, _color, _duration)
|
||||
|
||||
|
||||
/mob/living/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION)
|
||||
mob_light(_range, _power, _color, _duration)
|
||||
|
||||
|
||||
/mob/living/proc/mob_light(_range, _power, _color, _duration)
|
||||
var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new (src, _range, _power, _color, _duration)
|
||||
return mob_light_obj
|
||||
|
||||
/// Setter for the light power of this atom.
|
||||
/atom/proc/set_light_power(new_power)
|
||||
if(new_power == light_power)
|
||||
return
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_POWER, new_power) & COMPONENT_BLOCK_LIGHT_UPDATE)
|
||||
return
|
||||
. = light_power
|
||||
light_power = new_power
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_POWER, .)
|
||||
|
||||
/// Setter for the light range of this atom.
|
||||
/atom/proc/set_light_range(new_range)
|
||||
if(new_range == light_range)
|
||||
return
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_RANGE, new_range) & COMPONENT_BLOCK_LIGHT_UPDATE)
|
||||
return
|
||||
. = light_range
|
||||
light_range = new_range
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_RANGE, .)
|
||||
|
||||
/// Setter for the light color of this atom.
|
||||
/atom/proc/set_light_color(new_color)
|
||||
if(new_color == light_color)
|
||||
return
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_COLOR, new_color) & COMPONENT_BLOCK_LIGHT_UPDATE)
|
||||
return
|
||||
. = light_color
|
||||
light_color = new_color
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_COLOR, .)
|
||||
|
||||
/// Setter for whether or not this atom's light is on.
|
||||
/atom/proc/set_light_on(new_value)
|
||||
if(new_value == light_on)
|
||||
return
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ON, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE)
|
||||
return
|
||||
. = light_on
|
||||
light_on = new_value
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_ON, .)
|
||||
|
||||
/// Setter for the light flags of this atom.
|
||||
/atom/proc/set_light_flags(new_value)
|
||||
if(new_value == light_flags)
|
||||
return
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_FLAGS, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE)
|
||||
return
|
||||
. = light_flags
|
||||
light_flags = new_value
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_FLAGS, .)
|
||||
|
||||
///Keeps track of the sources of dynamic luminosity and updates our visibility with the highest.
|
||||
/atom/movable/proc/update_dynamic_luminosity()
|
||||
var/highest = 0
|
||||
for(var/i in affected_dynamic_lights)
|
||||
if(affected_dynamic_lights[i] <= highest)
|
||||
continue
|
||||
highest = affected_dynamic_lights[i]
|
||||
if(highest == affecting_dynamic_lumi)
|
||||
return
|
||||
luminosity -= affecting_dynamic_lumi
|
||||
affecting_dynamic_lumi = highest
|
||||
luminosity += affecting_dynamic_lumi
|
||||
|
||||
|
||||
///Helper to change several lighting overlay settings.
|
||||
/atom/movable/proc/set_light_range_power_color(range, power, color)
|
||||
set_light_range(range)
|
||||
set_light_power(power)
|
||||
set_light_color(color)
|
||||
|
||||
@@ -1,41 +1,37 @@
|
||||
/var/total_lighting_corners = 0
|
||||
/var/datum/lighting_corner/dummy/dummy_lighting_corner = new
|
||||
// Because we can control each corner of every lighting overlay.
|
||||
// Because we can control each corner of every lighting object.
|
||||
// And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't).
|
||||
// For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting.
|
||||
|
||||
// This list is what the code that assigns corners listens to, the order in this list is the order in which corners are added to the /turf/corners list.
|
||||
/var/list/LIGHTING_CORNER_DIAGONAL = list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST)
|
||||
|
||||
/datum/lighting_corner
|
||||
var/list/turf/masters = list()
|
||||
var/list/datum/light_source/affecting = list() // Light sources affecting us.
|
||||
var/active = FALSE // TRUE if one of our masters has dynamic lighting.
|
||||
var/list/datum/light_source/affecting // Light sources affecting us.
|
||||
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
|
||||
var/turf/master_NE
|
||||
var/turf/master_SE
|
||||
var/turf/master_SW
|
||||
var/turf/master_NW
|
||||
|
||||
//"raw" color values, changed by update_lumcount()
|
||||
var/lum_r = 0
|
||||
var/lum_g = 0
|
||||
var/lum_b = 0
|
||||
|
||||
//true color values, guaranteed to be between 0 and 1
|
||||
var/cache_r = LIGHTING_SOFT_THRESHOLD
|
||||
var/cache_g = LIGHTING_SOFT_THRESHOLD
|
||||
var/cache_b = LIGHTING_SOFT_THRESHOLD
|
||||
|
||||
///the maximum of lum_r, lum_g, and lum_b. if this is > 1 then the three cached color values are divided by this
|
||||
var/largest_color_luminosity = 0
|
||||
|
||||
///whether we are to be added to SSlighting's corners_queue list for an update
|
||||
var/needs_update = FALSE
|
||||
|
||||
var/cache_r = LIGHTING_SOFT_THRESHOLD
|
||||
var/cache_g = LIGHTING_SOFT_THRESHOLD
|
||||
var/cache_b = LIGHTING_SOFT_THRESHOLD
|
||||
var/cache_mx = 0
|
||||
|
||||
var/update_gen = 0
|
||||
|
||||
/datum/lighting_corner/New(var/turf/new_turf, var/diagonal)
|
||||
/datum/lighting_corner/New(turf/new_turf, diagonal)
|
||||
. = ..()
|
||||
|
||||
total_lighting_corners++
|
||||
|
||||
masters[new_turf] = turn(diagonal, 180)
|
||||
z = new_turf.z
|
||||
save_master(new_turf, turn(diagonal, 180))
|
||||
|
||||
var/vertical = diagonal & ~(diagonal - 1) // The horizontal directions (4 and 8) are bigger than the vertical ones (1 and 2), so we can reliably say the lsb is the horizontal direction.
|
||||
var/horizontal = diagonal & ~vertical // Now that we know the horizontal one we can get the vertical one.
|
||||
@@ -46,69 +42,75 @@
|
||||
// My initial plan was to make this loop through a list of all the dirs (horizontal, vertical, diagonal).
|
||||
// Issue being that the only way I could think of doing it was very messy, slow and honestly overengineered.
|
||||
// So we'll have this hardcode instead.
|
||||
var/turf/T
|
||||
var/i
|
||||
var/turf/new_master_turf
|
||||
|
||||
// Diagonal one is easy.
|
||||
T = get_step(new_turf, diagonal)
|
||||
if (T) // In case we're on the map's border.
|
||||
if (!T.corners)
|
||||
T.corners = list(null, null, null, null)
|
||||
|
||||
masters[T] = diagonal
|
||||
i = LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180))
|
||||
T.corners[i] = src
|
||||
new_master_turf = get_step(new_turf, diagonal)
|
||||
if (new_master_turf) // In case we're on the map's border.
|
||||
save_master(new_master_turf, diagonal)
|
||||
|
||||
// Now the horizontal one.
|
||||
T = get_step(new_turf, horizontal)
|
||||
if (T) // Ditto.
|
||||
if (!T.corners)
|
||||
T.corners = list(null, null, null, null)
|
||||
|
||||
masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
|
||||
i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
|
||||
T.corners[i] = src
|
||||
new_master_turf = get_step(new_turf, horizontal)
|
||||
if (new_master_turf) // Ditto.
|
||||
save_master(new_master_turf, ((new_master_turf.x > x) ? EAST : WEST) | ((new_master_turf.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates.
|
||||
|
||||
// And finally the vertical one.
|
||||
T = get_step(new_turf, vertical)
|
||||
if (T)
|
||||
if (!T.corners)
|
||||
T.corners = list(null, null, null, null)
|
||||
new_master_turf = get_step(new_turf, vertical)
|
||||
if (new_master_turf)
|
||||
save_master(new_master_turf, ((new_master_turf.x > x) ? EAST : WEST) | ((new_master_turf.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates.
|
||||
|
||||
masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
|
||||
i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
|
||||
T.corners[i] = src
|
||||
/datum/lighting_corner/proc/save_master(turf/master, dir)
|
||||
switch (dir)
|
||||
if (NORTHEAST)
|
||||
master_NE = master
|
||||
master.lighting_corner_SW = src
|
||||
if (SOUTHEAST)
|
||||
master_SE = master
|
||||
master.lighting_corner_NW = src
|
||||
if (SOUTHWEST)
|
||||
master_SW = master
|
||||
master.lighting_corner_NE = src
|
||||
if (NORTHWEST)
|
||||
master_NW = master
|
||||
master.lighting_corner_SE = src
|
||||
|
||||
update_active()
|
||||
/datum/lighting_corner/proc/self_destruct_if_idle()
|
||||
if (!LAZYLEN(affecting))
|
||||
qdel(src, force = TRUE)
|
||||
|
||||
/datum/lighting_corner/proc/update_active()
|
||||
active = FALSE
|
||||
for (var/turf/T in masters)
|
||||
if (T.lighting_overlay)
|
||||
active = TRUE
|
||||
/datum/lighting_corner/proc/vis_update()
|
||||
for (var/datum/light_source/light_source as anything in affecting)
|
||||
light_source.vis_update()
|
||||
|
||||
/datum/lighting_corner/proc/full_update()
|
||||
for (var/datum/light_source/light_source as anything in affecting)
|
||||
light_source.recalc_corner(src)
|
||||
|
||||
// God that was a mess, now to do the rest of the corner code! Hooray!
|
||||
/datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b)
|
||||
/datum/lighting_corner/proc/update_lumcount(delta_r, delta_g, delta_b)
|
||||
if (!(delta_r || delta_g || delta_b)) // 0 is falsey ok
|
||||
return
|
||||
|
||||
lum_r += delta_r
|
||||
lum_g += delta_g
|
||||
lum_b += delta_b
|
||||
|
||||
if (!needs_update)
|
||||
needs_update = TRUE
|
||||
lighting_update_corners += src
|
||||
SSlighting.corners_queue += src
|
||||
|
||||
/datum/lighting_corner/proc/update_overlays()
|
||||
// Cache these values a head of time so 4 individual lighting overlays don't all calculate them individually.
|
||||
var/lum_r = src.lum_r > 0 ? LIGHTING_MULT_FACTOR * sqrt(src.lum_r) : src.lum_r
|
||||
var/lum_g = src.lum_g > 0 ? LIGHTING_MULT_FACTOR * sqrt(src.lum_g) : src.lum_g
|
||||
var/lum_b = src.lum_b > 0 ? LIGHTING_MULT_FACTOR * sqrt(src.lum_b) : src.lum_b
|
||||
var/mx = max(lum_r, lum_g, lum_b) // Scale it so 1 is the strongest lum, if it is above 1.
|
||||
/datum/lighting_corner/proc/update_objects()
|
||||
// Cache these values ahead of time so 4 individual lighting objects don't all calculate them individually.
|
||||
var/lum_r = src.lum_r
|
||||
var/lum_g = src.lum_g
|
||||
var/lum_b = src.lum_b
|
||||
var/largest_color_luminosity = max(lum_r, lum_g, lum_b) // Scale it so one of them is the strongest lum, if it is above 1.
|
||||
. = 1 // factor
|
||||
if (mx > 1)
|
||||
. = 1 / mx
|
||||
if (largest_color_luminosity > 1)
|
||||
. = 1 / largest_color_luminosity
|
||||
|
||||
#if LIGHTING_SOFT_THRESHOLD != 0
|
||||
else if (mx < LIGHTING_SOFT_THRESHOLD)
|
||||
else if (largest_color_luminosity < LIGHTING_SOFT_THRESHOLD)
|
||||
. = 0 // 0 means soft lighting.
|
||||
|
||||
cache_r = round(lum_r * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
||||
@@ -119,21 +121,56 @@
|
||||
cache_g = round(lum_g * ., LIGHTING_ROUND_VALUE)
|
||||
cache_b = round(lum_b * ., LIGHTING_ROUND_VALUE)
|
||||
#endif
|
||||
cache_mx = round(mx, LIGHTING_ROUND_VALUE)
|
||||
|
||||
for (var/TT in masters)
|
||||
var/turf/T = TT
|
||||
if (T.lighting_overlay)
|
||||
if (!T.lighting_overlay.needs_update)
|
||||
T.lighting_overlay.needs_update = TRUE
|
||||
lighting_update_overlays += T.lighting_overlay
|
||||
src.largest_color_luminosity = round(largest_color_luminosity, LIGHTING_ROUND_VALUE)
|
||||
|
||||
var/datum/lighting_object/lighting_object = master_NE?.lighting_object
|
||||
if (lighting_object && !lighting_object.needs_update)
|
||||
lighting_object.needs_update = TRUE
|
||||
SSlighting.objects_queue += lighting_object
|
||||
|
||||
lighting_object = master_SE?.lighting_object
|
||||
if (lighting_object && !lighting_object.needs_update)
|
||||
lighting_object.needs_update = TRUE
|
||||
SSlighting.objects_queue += lighting_object
|
||||
|
||||
lighting_object = master_SW?.lighting_object
|
||||
if (lighting_object && !lighting_object.needs_update)
|
||||
lighting_object.needs_update = TRUE
|
||||
SSlighting.objects_queue += lighting_object
|
||||
|
||||
lighting_object = master_NW?.lighting_object
|
||||
if (lighting_object && !lighting_object.needs_update)
|
||||
lighting_object.needs_update = TRUE
|
||||
SSlighting.objects_queue += lighting_object
|
||||
|
||||
self_destruct_if_idle()
|
||||
|
||||
|
||||
/datum/lighting_corner/dummy/New()
|
||||
return
|
||||
|
||||
/datum/lighting_corner/Destroy(var/force)
|
||||
/datum/lighting_corner/Destroy(force)
|
||||
if (!force)
|
||||
return QDEL_HINT_LETMELIVE
|
||||
crash_with("Who decided to force qdel() a lighting corner? Why did you do this?")
|
||||
|
||||
for (var/datum/light_source/light_source as anything in affecting)
|
||||
LAZYREMOVE(light_source.effect_str, src)
|
||||
affecting = null
|
||||
|
||||
if (master_NE)
|
||||
master_NE.lighting_corner_SW = null
|
||||
master_NE.lighting_corners_initialised = FALSE
|
||||
if (master_SE)
|
||||
master_SE.lighting_corner_NW = null
|
||||
master_SE.lighting_corners_initialised = FALSE
|
||||
if (master_SW)
|
||||
master_SW.lighting_corner_NE = null
|
||||
master_SW.lighting_corners_initialised = FALSE
|
||||
if (master_NW)
|
||||
master_NW.lighting_corner_SE = null
|
||||
master_NW.lighting_corners_initialised = FALSE
|
||||
if(needs_update)
|
||||
SSlighting.corners_queue -= src
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
desc = "Deletes itself, but first updates all the lighting on outdoor turfs."
|
||||
icon = 'icons/effects/effects_vr.dmi'
|
||||
icon_state = "fakesun"
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
var/datum/light_source/sun/fake_sun
|
||||
|
||||
var/list/possible_light_setups = list(
|
||||
list(
|
||||
@@ -17,6 +19,22 @@
|
||||
"brightness" = 2.5,
|
||||
"color" = "#EE9AC6"
|
||||
),
|
||||
list(
|
||||
"brightness" = 1.5,
|
||||
"color" = "#F07AD8"
|
||||
),
|
||||
list(
|
||||
"brightness" = 1.5,
|
||||
"color" = "#61AEF3"
|
||||
),
|
||||
list(
|
||||
"brightness" = 1,
|
||||
"color" = "#f3932d"
|
||||
),
|
||||
list(
|
||||
"brightness" = 1,
|
||||
"color" = "#631E8A"
|
||||
),
|
||||
list(
|
||||
"brightness" = 1.0,
|
||||
"color" = "#A3A291"
|
||||
@@ -66,28 +84,97 @@
|
||||
|
||||
/obj/effect/fake_sun/LateInitialize()
|
||||
. = ..()
|
||||
var/list/choice = pick(possible_light_setups)
|
||||
if(choice["brightness"] <= LIGHTING_SOFT_THRESHOLD) // dark!
|
||||
return
|
||||
|
||||
var/list/our_choice = pick(possible_light_setups)
|
||||
fake_sun = new
|
||||
fake_sun.light_color = choice["color"]
|
||||
fake_sun.light_power = choice["brightness"]
|
||||
|
||||
var/list/zees = GetConnectedZlevels()
|
||||
var/min = z
|
||||
var/max = z
|
||||
for(var/zee in zees)
|
||||
if(zee < min)
|
||||
min = z
|
||||
if(zee > max)
|
||||
max = z
|
||||
|
||||
var/list/all_turfs = block(locate(1, 1, min), locate(world.maxx, world.maxy, max))
|
||||
var/list/turfs_to_use = list()
|
||||
for(var/turf/T as anything in all_turfs)
|
||||
if(T.outdoors)
|
||||
turfs_to_use += T
|
||||
|
||||
// Calculate new values to apply
|
||||
var/new_brightness = our_choice["brightness"]
|
||||
var/new_color = our_choice["color"]
|
||||
var/lum_r = new_brightness * GetRedPart (new_color) / 255
|
||||
var/lum_g = new_brightness * GetGreenPart(new_color) / 255
|
||||
var/lum_b = new_brightness * GetBluePart (new_color) / 255
|
||||
var/static/update_gen = -1 // Used to prevent double-processing corners. Otherwise would happen when looping over adjacent turfs.
|
||||
|
||||
var/list/turfs = block(locate(1,1,z),locate(world.maxx,world.maxy,z))
|
||||
|
||||
for(var/turf/simulated/T as anything in turfs)
|
||||
if(!T.lighting_overlay)
|
||||
T.lighting_build_overlay()
|
||||
if(!T.outdoors)
|
||||
continue
|
||||
for(var/C in T.get_corners())
|
||||
var/datum/lighting_corner/LC = C
|
||||
if(LC.update_gen != update_gen && LC.active)
|
||||
LC.update_gen = update_gen
|
||||
LC.update_lumcount(lum_r, lum_g, lum_b)
|
||||
update_gen--
|
||||
qdel(src)
|
||||
if(!turfs_to_use.len)
|
||||
warning("Fake sun placed on a level where it can't find any outdoor turfs to color at [x],[y],[z].")
|
||||
return
|
||||
|
||||
fake_sun.update_corners(turfs_to_use)
|
||||
|
||||
/obj/effect/fake_sun/warm
|
||||
name = "warm fake sun"
|
||||
desc = "Deletes itself, but first updates all the lighting on outdoor turfs to warm colors."
|
||||
|
||||
possible_light_setups = list(
|
||||
|
||||
list(
|
||||
"brightness" = 6.0,
|
||||
"color" = "#E9FFB8"
|
||||
),
|
||||
|
||||
list(
|
||||
"brightness" = 4.0,
|
||||
"color" = "#F4EA55"
|
||||
),
|
||||
list(
|
||||
"brightness" = 1.0,
|
||||
"color" = "#F07AD8"
|
||||
),
|
||||
list(
|
||||
"brightness" = 1.0,
|
||||
"color" = "#b4361f"
|
||||
),
|
||||
|
||||
list(
|
||||
"brightness" = 0.7,
|
||||
"color" = "#f3932d"
|
||||
),
|
||||
|
||||
list(
|
||||
"brightness" = 0.1,
|
||||
"color" = "#B92B00"
|
||||
)
|
||||
)
|
||||
|
||||
/obj/effect/fake_sun/cool
|
||||
name = "fake sun"
|
||||
desc = "Deletes itself, but first updates all the lighting on outdoor turfs to cool colors."
|
||||
possible_light_setups = list(
|
||||
|
||||
list(
|
||||
"brightness" = 6.0,
|
||||
"color" = "#abfff7"
|
||||
),
|
||||
list(
|
||||
"brightness" = 4.0,
|
||||
"color" = "#2e30c9"
|
||||
),
|
||||
list(
|
||||
"brightness" = 1.0,
|
||||
"color" = "#61AEF3"
|
||||
),
|
||||
list(
|
||||
"brightness" = 1.0,
|
||||
"color" = "#61ddf3"
|
||||
),
|
||||
list(
|
||||
"brightness" = 0.3,
|
||||
"color" = "#253682"
|
||||
),
|
||||
list(
|
||||
"brightness" = 0.1,
|
||||
"color" = "#27024B"
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
/var/total_lighting_overlays = 0
|
||||
/atom/movable/lighting_overlay
|
||||
name = ""
|
||||
mouse_opacity = 0
|
||||
simulated = 0
|
||||
anchored = 1
|
||||
icon = LIGHTING_ICON
|
||||
plane = PLANE_LIGHTING
|
||||
//invisibility = INVISIBILITY_LIGHTING
|
||||
color = LIGHTING_BASE_MATRIX
|
||||
icon_state = "light1"
|
||||
//auto_init = 0 // doesn't need special init
|
||||
blend_mode = BLEND_OVERLAY
|
||||
|
||||
var/lum_r = 0
|
||||
var/lum_g = 0
|
||||
var/lum_b = 0
|
||||
/datum/lighting_object
|
||||
///the underlay we are currently applying to our turf to apply light
|
||||
var/mutable_appearance/current_underlay
|
||||
|
||||
///whether we are already in the SSlighting.objects_queue list
|
||||
var/needs_update = FALSE
|
||||
|
||||
/atom/movable/lighting_overlay/Initialize()
|
||||
// doesn't need special init
|
||||
initialized = TRUE
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
///the turf that our light is applied to
|
||||
var/turf/affected_turf
|
||||
|
||||
/atom/movable/lighting_overlay/New(var/atom/loc, var/no_update = FALSE)
|
||||
. = ..()
|
||||
verbs.Cut()
|
||||
total_lighting_overlays++
|
||||
|
||||
var/turf/T = loc //If this runtimes atleast we'll know what's creating overlays outside of turfs.
|
||||
T.lighting_overlay = src
|
||||
T.luminosity = 0
|
||||
if(no_update)
|
||||
/datum/lighting_object/New(turf/source)
|
||||
if(!SSlighting.subsystem_initialized)
|
||||
stack_trace("lighting_object created before SSlighting up!")
|
||||
return
|
||||
update_overlay()
|
||||
|
||||
/atom/movable/lighting_overlay/proc/update_overlay()
|
||||
set waitfor = FALSE
|
||||
var/turf/T = loc
|
||||
|
||||
if(!istype(T))
|
||||
if(loc)
|
||||
log_debug("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : "null"]) in update_overlay() and got qdel'ed!")
|
||||
else
|
||||
log_debug("A lighting overlay realised it was in nullspace in update_overlay() and got pooled!")
|
||||
if(!isturf(source))
|
||||
qdel(src, force=TRUE)
|
||||
stack_trace("a lighting object was assigned to [source], a non turf! ")
|
||||
return
|
||||
. = ..()
|
||||
|
||||
current_underlay = mutable_appearance(LIGHTING_ICON, "transparent", source.z, PLANE_LIGHTING, 255, RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM)
|
||||
|
||||
affected_turf = source
|
||||
if (affected_turf.lighting_object)
|
||||
qdel(affected_turf.lighting_object, force = TRUE)
|
||||
stack_trace("a lighting object was assigned to a turf that already had a lighting object!")
|
||||
|
||||
affected_turf.lighting_object = src
|
||||
affected_turf.luminosity = 0
|
||||
|
||||
for(var/turf/space/space_tile in RANGE_TURFS(1, affected_turf))
|
||||
space_tile.update_starlight()
|
||||
|
||||
needs_update = TRUE
|
||||
SSlighting.objects_queue += src
|
||||
|
||||
/datum/lighting_object/Destroy(force)
|
||||
if (!force)
|
||||
return QDEL_HINT_LETMELIVE
|
||||
SSlighting.objects_queue -= src
|
||||
if (isturf(affected_turf))
|
||||
affected_turf.lighting_object = null
|
||||
affected_turf.luminosity = 1
|
||||
affected_turf.underlays -= current_underlay
|
||||
affected_turf = null
|
||||
return ..()
|
||||
|
||||
/datum/lighting_object/proc/update()
|
||||
|
||||
// To the future coder who sees this and thinks
|
||||
// "Why didn't he just use a loop?"
|
||||
@@ -55,50 +55,54 @@
|
||||
// Oh it's also shorter line wise.
|
||||
// Including with these comments.
|
||||
|
||||
// See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are.
|
||||
// No I seriously cannot think of a more efficient method, fuck off Comic.
|
||||
var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new
|
||||
|
||||
var/datum/lighting_corner/cr = LAZYACCESS(T.corners,3) || dummy_lighting_corner
|
||||
var/datum/lighting_corner/cg = LAZYACCESS(T.corners,2) || dummy_lighting_corner
|
||||
var/datum/lighting_corner/cb = LAZYACCESS(T.corners,4) || dummy_lighting_corner
|
||||
var/datum/lighting_corner/ca = LAZYACCESS(T.corners,1) || dummy_lighting_corner
|
||||
var/datum/lighting_corner/red_corner = affected_turf.lighting_corner_SW || dummy_lighting_corner
|
||||
var/datum/lighting_corner/green_corner = affected_turf.lighting_corner_SE || dummy_lighting_corner
|
||||
var/datum/lighting_corner/blue_corner = affected_turf.lighting_corner_NW || dummy_lighting_corner
|
||||
var/datum/lighting_corner/alpha_corner = affected_turf.lighting_corner_NE || dummy_lighting_corner
|
||||
|
||||
var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx)
|
||||
var/max = max(red_corner.largest_color_luminosity, green_corner.largest_color_luminosity, blue_corner.largest_color_luminosity, alpha_corner.largest_color_luminosity)
|
||||
|
||||
var/rr = cr.cache_r
|
||||
var/rg = cr.cache_g
|
||||
var/rb = cr.cache_b
|
||||
var/rr = red_corner.cache_r
|
||||
var/rg = red_corner.cache_g
|
||||
var/rb = red_corner.cache_b
|
||||
|
||||
var/gr = cg.cache_r
|
||||
var/gg = cg.cache_g
|
||||
var/gb = cg.cache_b
|
||||
var/gr = green_corner.cache_r
|
||||
var/gg = green_corner.cache_g
|
||||
var/gb = green_corner.cache_b
|
||||
|
||||
var/br = cb.cache_r
|
||||
var/bg = cb.cache_g
|
||||
var/bb = cb.cache_b
|
||||
var/br = blue_corner.cache_r
|
||||
var/bg = blue_corner.cache_g
|
||||
var/bb = blue_corner.cache_b
|
||||
|
||||
var/ar = ca.cache_r
|
||||
var/ag = ca.cache_g
|
||||
var/ab = ca.cache_b
|
||||
var/ar = alpha_corner.cache_r
|
||||
var/ag = alpha_corner.cache_g
|
||||
var/ab = alpha_corner.cache_b
|
||||
|
||||
#if LIGHTING_SOFT_THRESHOLD != 0
|
||||
var/set_luminosity = max > LIGHTING_SOFT_THRESHOLD
|
||||
#else
|
||||
// Because of floating points, it won't even be a flat 0.
|
||||
// Because of floating points™?, it won't even be a flat 0.
|
||||
// This number is mostly arbitrary.
|
||||
var/set_luminosity = max > 1e-6
|
||||
#endif
|
||||
|
||||
if((rr & gr & br & ar) && (rg + gg + bg + ag + rb + gb + bb + ab == 8))
|
||||
//anything that passes the first case is very likely to pass the second, and addition is a little faster in this case
|
||||
icon_state = "transparent"
|
||||
color = null
|
||||
//anything that passes the first case is very likely to pass the second, and addition is a little faster in this case
|
||||
affected_turf.underlays -= current_underlay
|
||||
current_underlay.icon_state = "transparent"
|
||||
current_underlay.color = null
|
||||
affected_turf.underlays += current_underlay
|
||||
else if(!set_luminosity)
|
||||
icon_state = LIGHTING_ICON_STATE_DARK
|
||||
color = null
|
||||
affected_turf.underlays -= current_underlay
|
||||
current_underlay.icon_state = "dark"
|
||||
current_underlay.color = null
|
||||
affected_turf.underlays += current_underlay
|
||||
else
|
||||
icon_state = null
|
||||
color = list(
|
||||
affected_turf.underlays -= current_underlay
|
||||
current_underlay.icon_state = "gradient"
|
||||
current_underlay.color = list(
|
||||
rr, rg, rb, 00,
|
||||
gr, gg, gb, 00,
|
||||
br, bg, bb, 00,
|
||||
@@ -106,38 +110,12 @@
|
||||
00, 00, 00, 01
|
||||
)
|
||||
|
||||
luminosity = set_luminosity
|
||||
affected_turf.underlays += current_underlay
|
||||
|
||||
// Variety of overrides so the overlays don't get affected by weird things.
|
||||
/atom/movable/lighting_overlay/ex_act()
|
||||
return
|
||||
affected_turf.luminosity = set_luminosity
|
||||
|
||||
/atom/movable/lighting_overlay/singularity_act()
|
||||
return
|
||||
/datum/lighting_object/proc/removefromturf()
|
||||
affected_turf.underlays -= current_underlay
|
||||
|
||||
/atom/movable/lighting_overlay/singularity_pull()
|
||||
return
|
||||
|
||||
/atom/movable/lighting_overlay/forceMove()
|
||||
return 0 //should never move
|
||||
|
||||
/atom/movable/lighting_overlay/Move()
|
||||
return 0
|
||||
|
||||
/atom/movable/lighting_overlay/throw_at()
|
||||
return 0
|
||||
|
||||
/atom/movable/lighting_overlay/Destroy(var/force)
|
||||
if (force)
|
||||
total_lighting_overlays--
|
||||
global.lighting_update_overlays -= src
|
||||
LAZYREMOVE(SSlighting.currentrun, src)
|
||||
|
||||
var/turf/T = loc
|
||||
if(istype(T))
|
||||
T.lighting_overlay = null
|
||||
T.luminosity = 1
|
||||
|
||||
return ..()
|
||||
else
|
||||
return QDEL_HINT_LETMELIVE
|
||||
/datum/lighting_object/proc/addtoturf()
|
||||
affected_turf.underlays += current_underlay
|
||||
|
||||
@@ -1,24 +1,6 @@
|
||||
// Create lighting overlays on all turfs with dynamic lighting in areas with dynamic lighting.
|
||||
/proc/create_all_lighting_overlays()
|
||||
for(var/area/A in world)
|
||||
if(!A.dynamic_lighting)
|
||||
continue
|
||||
for(var/turf/T in A)
|
||||
if(!T.dynamic_lighting)
|
||||
continue
|
||||
new /atom/movable/lighting_overlay(T, TRUE)
|
||||
CHECK_TICK
|
||||
/proc/create_all_lighting_objects()
|
||||
var/list/all_turfs = block(locate(1,1,1), locate(world.maxx, world.maxy, world.maxz))
|
||||
for(var/turf/T as anything in all_turfs)
|
||||
T.lighting_build_overlay()
|
||||
CHECK_TICK
|
||||
|
||||
/proc/create_lighting_overlays_zlevel(var/zlevel)
|
||||
ASSERT(zlevel)
|
||||
|
||||
for(var/turf/T in block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel)))
|
||||
if(!T.dynamic_lighting)
|
||||
continue
|
||||
|
||||
var/area/A = T.loc
|
||||
if(!A.dynamic_lighting)
|
||||
continue
|
||||
|
||||
new /atom/movable/lighting_overlay(T, TRUE)
|
||||
@@ -1,15 +1,22 @@
|
||||
/var/total_lighting_sources = 0
|
||||
// This is where the fun begins.
|
||||
// These are the main datums that emit light.
|
||||
|
||||
/datum/light_source
|
||||
var/atom/top_atom // The atom we're emitting light from(for example a mob if we're from a flashlight that's being held).
|
||||
var/atom/source_atom // The atom that we belong to.
|
||||
///The atom we're emitting light from (for example a mob if we're from a flashlight that's being held).
|
||||
var/atom/top_atom
|
||||
///The atom that we belong to.
|
||||
var/atom/source_atom
|
||||
|
||||
var/turf/source_turf // The turf under the above.
|
||||
var/light_power // Intensity of the emitter light.
|
||||
var/light_range // The range of the emitted light.
|
||||
var/light_color // The colour of the light, string, decomposed by parse_light_color()
|
||||
///The turf under the source atom.
|
||||
var/turf/source_turf
|
||||
///The turf the top_atom appears to over.
|
||||
var/turf/pixel_turf
|
||||
///Intensity of the emitter light.
|
||||
var/light_power
|
||||
/// The range of the emitted light.
|
||||
var/light_range
|
||||
/// The colour of the light, string, decomposed by parse_light_color()
|
||||
var/light_color
|
||||
|
||||
// Variables for keeping track of the colour.
|
||||
var/lum_r
|
||||
@@ -21,142 +28,83 @@
|
||||
var/tmp/applied_lum_g
|
||||
var/tmp/applied_lum_b
|
||||
|
||||
var/list/datum/lighting_corner/effect_str // List used to store how much we're affecting corners.
|
||||
var/list/turf/affecting_turfs
|
||||
/// List used to store how much we're affecting corners.
|
||||
var/list/datum/lighting_corner/effect_str
|
||||
|
||||
var/applied = FALSE // Whether we have applied our light yet or not.
|
||||
/// Whether we have applied our light yet or not.
|
||||
var/applied = FALSE
|
||||
|
||||
var/vis_update // Whether we should smartly recalculate visibility. and then only update tiles that became(in)visible to us.
|
||||
var/needs_update // Whether we are queued for an update.
|
||||
var/destroyed // Whether we are destroyed and need to stop emitting light.
|
||||
var/force_update
|
||||
/// whether we are to be added to SSlighting's sources_queue list for an update
|
||||
var/needs_update = LIGHTING_NO_UPDATE
|
||||
|
||||
/datum/light_source/New(var/atom/owner, var/atom/top)
|
||||
total_lighting_sources++
|
||||
|
||||
/datum/light_source/New(atom/owner, atom/top)
|
||||
source_atom = owner // Set our new owner.
|
||||
if(!source_atom.light_sources)
|
||||
source_atom.light_sources = list()
|
||||
|
||||
source_atom.light_sources += src // Add us to the lights of our owner.
|
||||
LAZYADD(source_atom.light_sources, src)
|
||||
top_atom = top
|
||||
if(top_atom != source_atom)
|
||||
if(!top.light_sources)
|
||||
top.light_sources = list()
|
||||
|
||||
top_atom.light_sources += src
|
||||
if (top_atom != source_atom)
|
||||
LAZYADD(top_atom.light_sources, src)
|
||||
|
||||
source_turf = top_atom
|
||||
pixel_turf = get_turf_pixel(top_atom) || source_turf
|
||||
|
||||
light_power = source_atom.light_power
|
||||
light_range = source_atom.light_range
|
||||
light_color = source_atom.light_color
|
||||
|
||||
parse_light_color()
|
||||
|
||||
effect_str = list()
|
||||
affecting_turfs = list()
|
||||
PARSE_LIGHT_COLOR(src)
|
||||
|
||||
update()
|
||||
|
||||
/datum/light_source/Destroy(force)
|
||||
remove_lum()
|
||||
if (source_atom)
|
||||
LAZYREMOVE(source_atom.light_sources, src)
|
||||
|
||||
if (top_atom)
|
||||
LAZYREMOVE(top_atom.light_sources, src)
|
||||
|
||||
if (needs_update)
|
||||
SSlighting.sources_queue -= src
|
||||
|
||||
top_atom = null
|
||||
source_atom = null
|
||||
source_turf = null
|
||||
pixel_turf = null
|
||||
|
||||
return ..()
|
||||
|
||||
// Kill ourselves.
|
||||
/datum/light_source/proc/destroy()
|
||||
total_lighting_sources--
|
||||
destroyed = TRUE
|
||||
force_update()
|
||||
if(source_atom)
|
||||
if(!source_atom.light_sources)
|
||||
log_runtime(EXCEPTION("Atom [source_atom] was a light source, but lacked a light source list!\n"), source_atom)
|
||||
else
|
||||
source_atom.light_sources -= src
|
||||
// Yes this doesn't align correctly on anything other than 4 width tabs.
|
||||
// If you want it to go switch everybody to elastic tab stops.
|
||||
// Actually that'd be great if you could!
|
||||
#define EFFECT_UPDATE(level) \
|
||||
if (needs_update == LIGHTING_NO_UPDATE) \
|
||||
SSlighting.sources_queue += src; \
|
||||
if (needs_update < level) \
|
||||
needs_update = level; \
|
||||
|
||||
if(top_atom)
|
||||
top_atom.light_sources -= src
|
||||
|
||||
// Call it dirty, I don't care.
|
||||
// This is here so there's no performance loss on non-instant updates from the fact that the engine can also do instant updates.
|
||||
// If you're wondering what's with the "BYOND" argument: BYOND won't let me have a() macro that has no arguments :|.
|
||||
#define effect_update(BYOND) \
|
||||
if(!needs_update) \
|
||||
{ \
|
||||
lighting_update_lights += src; \
|
||||
needs_update = TRUE; \
|
||||
}
|
||||
|
||||
// This proc will cause the light source to update the top atom, and add itself to the update queue.
|
||||
/datum/light_source/proc/update(var/atom/new_top_atom)
|
||||
/datum/light_source/proc/update(atom/new_top_atom)
|
||||
// This top atom is different.
|
||||
if(new_top_atom && new_top_atom != top_atom)
|
||||
if(top_atom != source_atom) // Remove ourselves from the light sources of that top atom.
|
||||
top_atom.light_sources -= src
|
||||
if (new_top_atom && new_top_atom != top_atom)
|
||||
if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom.
|
||||
LAZYREMOVE(top_atom.light_sources, src)
|
||||
|
||||
top_atom = new_top_atom
|
||||
|
||||
if(top_atom != source_atom)
|
||||
if(!top_atom.light_sources)
|
||||
top_atom.light_sources = list()
|
||||
if (top_atom != source_atom)
|
||||
LAZYADD(top_atom.light_sources, src) // Add ourselves to the light sources of our new top atom.
|
||||
|
||||
top_atom.light_sources += src // Add ourselves to the light sources of our new top atom.
|
||||
|
||||
effect_update(null)
|
||||
EFFECT_UPDATE(LIGHTING_CHECK_UPDATE)
|
||||
|
||||
// Will force an update without checking if it's actually needed.
|
||||
/datum/light_source/proc/force_update()
|
||||
force_update = 1
|
||||
|
||||
effect_update(null)
|
||||
EFFECT_UPDATE(LIGHTING_FORCE_UPDATE)
|
||||
|
||||
// Will cause the light source to recalculate turfs that were removed or added to visibility only.
|
||||
/datum/light_source/proc/vis_update()
|
||||
vis_update = 1
|
||||
|
||||
effect_update(null)
|
||||
|
||||
// Will check if we actually need to update, and update any variables that may need to be updated.
|
||||
/datum/light_source/proc/check()
|
||||
if(!source_atom || !light_range || !light_power)
|
||||
destroy()
|
||||
return 1
|
||||
|
||||
if(!top_atom)
|
||||
top_atom = source_atom
|
||||
. = 1
|
||||
|
||||
if(isturf(top_atom))
|
||||
if(source_turf != top_atom)
|
||||
source_turf = top_atom
|
||||
. = 1
|
||||
else if(top_atom.loc != source_turf)
|
||||
source_turf = top_atom.loc
|
||||
. = 1
|
||||
|
||||
if(source_atom.light_power != light_power)
|
||||
light_power = source_atom.light_power
|
||||
. = 1
|
||||
|
||||
if(source_atom.light_range != light_range)
|
||||
light_range = source_atom.light_range
|
||||
. = 1
|
||||
|
||||
if(light_range && light_power && !applied)
|
||||
. = 1
|
||||
|
||||
if(source_atom.light_color != light_color)
|
||||
light_color = source_atom.light_color
|
||||
parse_light_color()
|
||||
. = 1
|
||||
|
||||
// Decompile the hexadecimal colour into lumcounts of each perspective.
|
||||
/datum/light_source/proc/parse_light_color()
|
||||
if(light_color)
|
||||
lum_r = GetRedPart (light_color) / 255
|
||||
lum_g = GetGreenPart(light_color) / 255
|
||||
lum_b = GetBluePart (light_color) / 255
|
||||
else
|
||||
lum_r = 1
|
||||
lum_g = 1
|
||||
lum_b = 1
|
||||
EFFECT_UPDATE(LIGHTING_VIS_UPDATE)
|
||||
|
||||
// Macro that applies light to a new corner.
|
||||
// It is a macro in the interest of speed, yet not having to copy paste it.
|
||||
@@ -164,127 +112,264 @@
|
||||
// As such this all gets counted as a single line.
|
||||
// The braces and semicolons are there to be able to do this on a single line.
|
||||
|
||||
#define APPLY_CORNER(C) \
|
||||
. = LUM_FALLOFF(C, source_turf); \
|
||||
\
|
||||
. *= light_power; \
|
||||
\
|
||||
effect_str[C] = .; \
|
||||
\
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b \
|
||||
// /tg/ falloff alg
|
||||
#define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
|
||||
|
||||
// Bay/Polaris falloff alg
|
||||
//#define LUM_FALLOFF(C, T)(1 - CLAMP01(((C.x - T.x) ** 2 +(C.y - T.y) ** 2 + LIGHTING_HEIGHT) ** 0.6 / max(1, light_range)))
|
||||
|
||||
#define APPLY_CORNER(C) \
|
||||
. = LUM_FALLOFF(C, pixel_turf); \
|
||||
. *= light_power; \
|
||||
var/OLD = effect_str[C]; \
|
||||
\
|
||||
C.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
); \
|
||||
|
||||
#define REMOVE_CORNER(C) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b \
|
||||
);
|
||||
|
||||
// I don't need to explain what this does, do I?
|
||||
#define REMOVE_CORNER(C) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b \
|
||||
);
|
||||
#define APPLY_CORNER_SIMPLE(C) \
|
||||
. = light_power; \
|
||||
var/OLD = effect_str[C]; \
|
||||
\
|
||||
C.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
); \
|
||||
|
||||
// This is the define used to calculate falloff.
|
||||
#define LUM_FALLOFF(C, T)(1 - CLAMP01(((C.x - T.x) ** 2 +(C.y - T.y) ** 2 + LIGHTING_HEIGHT) ** 0.6 / max(1, light_range)))
|
||||
|
||||
/datum/light_source/proc/apply_lum()
|
||||
var/static/update_gen = 1
|
||||
applied = 1
|
||||
/datum/light_source/proc/remove_lum()
|
||||
applied = FALSE
|
||||
for (var/datum/lighting_corner/corner as anything in effect_str)
|
||||
REMOVE_CORNER(corner)
|
||||
LAZYREMOVE(corner.affecting, src)
|
||||
|
||||
effect_str = null
|
||||
|
||||
/datum/light_source/proc/recalc_corner(datum/lighting_corner/corner)
|
||||
LAZYINITLIST(effect_str)
|
||||
if (effect_str[corner]) // Already have one.
|
||||
REMOVE_CORNER(corner)
|
||||
effect_str[corner] = 0
|
||||
|
||||
APPLY_CORNER(corner)
|
||||
effect_str[corner] = .
|
||||
|
||||
/datum/light_source/proc/get_turfs_in_range()
|
||||
return view(CEILING(light_range, 1), source_turf)
|
||||
|
||||
/datum/light_source/proc/update_corners()
|
||||
var/update = FALSE
|
||||
var/atom/source_atom = src.source_atom
|
||||
|
||||
if (QDELETED(source_atom))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if (source_atom.light_power != light_power)
|
||||
light_power = source_atom.light_power
|
||||
update = TRUE
|
||||
|
||||
if (source_atom.light_range != light_range)
|
||||
light_range = source_atom.light_range
|
||||
update = TRUE
|
||||
|
||||
if (!top_atom)
|
||||
top_atom = source_atom
|
||||
update = TRUE
|
||||
|
||||
if (!light_range || !light_power)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if (isturf(top_atom))
|
||||
if (source_turf != top_atom)
|
||||
source_turf = top_atom
|
||||
pixel_turf = source_turf
|
||||
update = TRUE
|
||||
else if (top_atom.loc != source_turf)
|
||||
source_turf = top_atom.loc
|
||||
pixel_turf = get_turf_pixel(top_atom)
|
||||
update = TRUE
|
||||
else
|
||||
var/pixel_loc = get_turf_pixel(top_atom)
|
||||
if (pixel_loc != pixel_turf)
|
||||
pixel_turf = pixel_loc
|
||||
update = TRUE
|
||||
|
||||
if (!isturf(source_turf))
|
||||
if (applied)
|
||||
remove_lum()
|
||||
return
|
||||
|
||||
if (light_range && light_power && !applied)
|
||||
update = TRUE
|
||||
|
||||
if (source_atom.light_color != light_color)
|
||||
light_color = source_atom.light_color
|
||||
PARSE_LIGHT_COLOR(src)
|
||||
update = TRUE
|
||||
|
||||
else if (applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b)
|
||||
update = TRUE
|
||||
|
||||
if (update)
|
||||
needs_update = LIGHTING_CHECK_UPDATE
|
||||
applied = TRUE
|
||||
else if (needs_update == LIGHTING_CHECK_UPDATE)
|
||||
return //nothing's changed
|
||||
|
||||
var/list/datum/lighting_corner/corners = list()
|
||||
var/list/turf/turfs = list()
|
||||
|
||||
if (source_turf)
|
||||
var/oldlum = source_turf.luminosity
|
||||
source_turf.luminosity = CEILING(light_range, 1)
|
||||
for(var/turf/T in get_turfs_in_range())
|
||||
if(!IS_OPAQUE_TURF(T))
|
||||
if (!T.lighting_corners_initialised)
|
||||
T.generate_missing_corners()
|
||||
corners[T.lighting_corner_NE] = 0
|
||||
corners[T.lighting_corner_SE] = 0
|
||||
corners[T.lighting_corner_SW] = 0
|
||||
corners[T.lighting_corner_NW] = 0
|
||||
turfs += T
|
||||
source_turf.luminosity = oldlum
|
||||
|
||||
var/list/datum/lighting_corner/new_corners = (corners - effect_str)
|
||||
LAZYINITLIST(effect_str)
|
||||
if (needs_update == LIGHTING_VIS_UPDATE)
|
||||
for (var/datum/lighting_corner/corner as anything in new_corners)
|
||||
APPLY_CORNER(corner)
|
||||
if (. != 0)
|
||||
LAZYADD(corner.affecting, src)
|
||||
effect_str[corner] = .
|
||||
else
|
||||
for (var/datum/lighting_corner/corner as anything in new_corners)
|
||||
APPLY_CORNER(corner)
|
||||
if (. != 0)
|
||||
LAZYADD(corner.affecting, src)
|
||||
effect_str[corner] = .
|
||||
|
||||
for (var/datum/lighting_corner/corner as anything in corners - new_corners) // Existing corners
|
||||
APPLY_CORNER(corner)
|
||||
if (. != 0)
|
||||
effect_str[corner] = .
|
||||
else
|
||||
LAZYREMOVE(corner.affecting, src)
|
||||
effect_str -= corner
|
||||
|
||||
var/list/datum/lighting_corner/gone_corners = effect_str - corners
|
||||
for (var/datum/lighting_corner/corner as anything in gone_corners)
|
||||
REMOVE_CORNER(corner)
|
||||
LAZYREMOVE(corner.affecting, src)
|
||||
effect_str -= gone_corners
|
||||
|
||||
// Keep track of the last applied lum values so that the lighting can be reversed
|
||||
applied_lum_r = lum_r
|
||||
applied_lum_g = lum_g
|
||||
applied_lum_b = lum_b
|
||||
|
||||
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
|
||||
if(!T.lighting_corners_initialised)
|
||||
T.generate_missing_corners()
|
||||
UNSETEMPTY(effect_str)
|
||||
|
||||
for(var/datum/lighting_corner/C in T.get_corners())
|
||||
if(C.update_gen == update_gen)
|
||||
continue
|
||||
// For planets and fake suns
|
||||
/datum/light_source/sun
|
||||
light_range = 1
|
||||
light_color = "#FFFFFF"
|
||||
light_power = 2
|
||||
var/applied_power = 2
|
||||
|
||||
C.update_gen = update_gen
|
||||
C.affecting += src
|
||||
/datum/light_source/sun/New()
|
||||
return
|
||||
|
||||
if(!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
/datum/light_source/sun/force_update()
|
||||
return
|
||||
|
||||
APPLY_CORNER(C)
|
||||
/datum/light_source/sun/vis_update()
|
||||
return
|
||||
|
||||
if(!T.affecting_lights)
|
||||
T.affecting_lights = list()
|
||||
/datum/light_source/sun/update_corners(var/list/turfs_to_update)
|
||||
if(!LAZYLEN(turfs_to_update))
|
||||
stack_trace("Planet sun tried to update with no turfs given")
|
||||
return
|
||||
|
||||
T.affecting_lights += src
|
||||
affecting_turfs += T
|
||||
// Update lum_r/g/b from our light_color
|
||||
PARSE_LIGHT_COLOR(src)
|
||||
|
||||
// Noop update
|
||||
if(lum_r == applied_lum_r && lum_g == applied_lum_g && lum_b == applied_lum_b && light_power == applied_power)
|
||||
return
|
||||
|
||||
// No reason to unapply on the first run or if previous run was 0 power
|
||||
if(applied)
|
||||
remove_lum()
|
||||
|
||||
update_gen++
|
||||
// Entirely dark, just stop now that we've remove_lum()'d
|
||||
if(!light_power)
|
||||
applied = FALSE
|
||||
return
|
||||
|
||||
/datum/light_source/proc/remove_lum()
|
||||
applied = FALSE
|
||||
LAZYINITLIST(effect_str)
|
||||
|
||||
for(var/turf/T in affecting_turfs)
|
||||
if(!T.affecting_lights)
|
||||
T.affecting_lights = list()
|
||||
else
|
||||
T.affecting_lights -= src
|
||||
|
||||
affecting_turfs.Cut()
|
||||
|
||||
for(var/datum/lighting_corner/C in effect_str)
|
||||
REMOVE_CORNER(C)
|
||||
|
||||
C.affecting -= src
|
||||
|
||||
effect_str.Cut()
|
||||
|
||||
/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
|
||||
if(effect_str.Find(C)) // Already have one.
|
||||
REMOVE_CORNER(C)
|
||||
|
||||
APPLY_CORNER(C)
|
||||
|
||||
/datum/light_source/proc/smart_vis_update()
|
||||
var/list/datum/lighting_corner/corners = list()
|
||||
var/list/turf/turfs = list()
|
||||
FOR_DVIEW(var/turf/T, light_range, source_turf, 0)
|
||||
if(!T.lighting_corners_initialised)
|
||||
T.generate_missing_corners()
|
||||
corners |= T.get_corners()
|
||||
turfs += T
|
||||
for(var/turf/T as anything in turfs_to_update)
|
||||
if(!IS_OPAQUE_TURF(T))
|
||||
if(!T.lighting_corners_initialised)
|
||||
T.generate_missing_corners()
|
||||
|
||||
var/datum/lighting_corner/LC = T.lighting_corner_NE
|
||||
if(!corners[LC])
|
||||
corners[LC] = 1
|
||||
APPLY_CORNER_SIMPLE(LC)
|
||||
LAZYADD(LC.affecting, src)
|
||||
effect_str[LC] = .
|
||||
|
||||
LC = T.lighting_corner_SE
|
||||
if(!corners[LC])
|
||||
corners[LC] = 1
|
||||
APPLY_CORNER_SIMPLE(LC)
|
||||
LAZYADD(LC.affecting, src)
|
||||
effect_str[LC] = .
|
||||
|
||||
LC = T.lighting_corner_NW
|
||||
if(!corners[LC])
|
||||
corners[LC] = 1
|
||||
APPLY_CORNER_SIMPLE(LC)
|
||||
LAZYADD(LC.affecting, src)
|
||||
effect_str[LC] = .
|
||||
|
||||
LC = T.lighting_corner_SW
|
||||
if(!corners[LC])
|
||||
corners[LC] = 1
|
||||
APPLY_CORNER_SIMPLE(LC)
|
||||
LAZYADD(LC.affecting, src)
|
||||
effect_str[LC] = .
|
||||
|
||||
var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them.
|
||||
affecting_turfs += L
|
||||
for(var/turf/T in L)
|
||||
if(!T.affecting_lights)
|
||||
T.affecting_lights = list(src)
|
||||
else
|
||||
T.affecting_lights += src
|
||||
CHECK_TICK
|
||||
|
||||
L = affecting_turfs - turfs // Now-gone turfs, remove us from the affecting lights.
|
||||
affecting_turfs -= L
|
||||
for(var/turf/T in L)
|
||||
T.affecting_lights -= src
|
||||
applied_lum_r = lum_r
|
||||
applied_lum_g = lum_g
|
||||
applied_lum_b = lum_b
|
||||
applied_power = light_power
|
||||
applied = TRUE // remove_lum() now necessary in the future
|
||||
|
||||
for(var/datum/lighting_corner/C in corners - effect_str) // New corners
|
||||
C.affecting += src
|
||||
if(!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
UNSETEMPTY(effect_str)
|
||||
|
||||
APPLY_CORNER(C)
|
||||
|
||||
for(var/datum/lighting_corner/C in effect_str - corners) // Old, now gone, corners.
|
||||
REMOVE_CORNER(C)
|
||||
C.affecting -= src
|
||||
effect_str -= C
|
||||
|
||||
#undef effect_update
|
||||
#undef EFFECT_UPDATE
|
||||
#undef LUM_FALLOFF
|
||||
#undef REMOVE_CORNER
|
||||
#undef APPLY_CORNER
|
||||
#undef REMOVE_CORNER_SIMPLE
|
||||
#undef APPLY_CORNER_SIMPLE
|
||||
@@ -1,96 +1,142 @@
|
||||
/turf
|
||||
var/dynamic_lighting = TRUE // Does the turf use dynamic lighting?
|
||||
luminosity = 1
|
||||
///Lumcount added by sources other than lighting datum objects, such as the overlay lighting component.
|
||||
var/dynamic_lumcount = 0
|
||||
|
||||
var/dynamic_lighting = TRUE
|
||||
|
||||
var/tmp/lighting_corners_initialised = FALSE
|
||||
|
||||
var/tmp/list/datum/light_source/affecting_lights // List of light sources affecting this turf.
|
||||
var/tmp/atom/movable/lighting_overlay/lighting_overlay // Our lighting overlay.
|
||||
var/tmp/list/datum/lighting_corner/corners
|
||||
var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile.
|
||||
///Our lighting object.
|
||||
var/tmp/datum/lighting_object/lighting_object
|
||||
///Lighting Corner datums.
|
||||
var/tmp/datum/lighting_corner/lighting_corner_NE
|
||||
var/tmp/datum/lighting_corner/lighting_corner_SE
|
||||
var/tmp/datum/lighting_corner/lighting_corner_SW
|
||||
var/tmp/datum/lighting_corner/lighting_corner_NW
|
||||
|
||||
///Which directions does this turf block the vision of, taking into account both the turf's opacity and the movable opacity_sources.
|
||||
var/directional_opacity = NONE
|
||||
///Lazylist of movable atoms providing opacity sources.
|
||||
var/list/atom/movable/opacity_sources
|
||||
|
||||
// Causes any affecting light sources to be queued for a visibility update, for example a door got opened.
|
||||
/turf/proc/reconsider_lights()
|
||||
for(var/datum/light_source/L in affecting_lights)
|
||||
L.vis_update()
|
||||
lighting_corner_NE?.vis_update()
|
||||
lighting_corner_SE?.vis_update()
|
||||
lighting_corner_SW?.vis_update()
|
||||
lighting_corner_NW?.vis_update()
|
||||
|
||||
/turf/proc/lighting_clear_overlay()
|
||||
if(lighting_overlay)
|
||||
qdel(lighting_overlay, force = TRUE)
|
||||
if(lighting_object)
|
||||
qdel(lighting_object, force=TRUE)
|
||||
|
||||
for(var/datum/lighting_corner/C in corners)
|
||||
C.update_active()
|
||||
|
||||
// Builds a lighting overlay for us, but only if our area is dynamic.
|
||||
// Builds a lighting object for us, but only if our area is dynamic.
|
||||
/turf/proc/lighting_build_overlay()
|
||||
if(lighting_overlay)
|
||||
if(!has_dynamic_lighting())
|
||||
return
|
||||
|
||||
var/area/A = loc
|
||||
if(A.dynamic_lighting && dynamic_lighting)
|
||||
if(!lighting_corners_initialised)
|
||||
generate_missing_corners()
|
||||
|
||||
new /atom/movable/lighting_overlay(src)
|
||||
|
||||
for(var/datum/lighting_corner/C in corners)
|
||||
if(!C.active) // We would activate the corner, calculate the lighting for it.
|
||||
for(var/L in C.affecting)
|
||||
var/datum/light_source/S = L
|
||||
S.recalc_corner(C)
|
||||
|
||||
C.active = TRUE
|
||||
lighting_clear_overlay()
|
||||
new/datum/lighting_object(src)
|
||||
|
||||
// Used to get a scaled lumcount.
|
||||
/turf/proc/get_lumcount(var/minlum = 0, var/maxlum = 1)
|
||||
if(!lighting_overlay)
|
||||
/turf/proc/get_lumcount(minlum = 0, maxlum = 1)
|
||||
if (!lighting_object)
|
||||
return 1
|
||||
|
||||
var/totallums = 0
|
||||
for(var/datum/lighting_corner/L in corners)
|
||||
totallums += max(L.lum_r, L.lum_g, L.lum_b)
|
||||
var/datum/lighting_corner/L
|
||||
L = lighting_corner_NE
|
||||
if (L)
|
||||
totallums += L.lum_r + L.lum_b + L.lum_g
|
||||
L = lighting_corner_SE
|
||||
if (L)
|
||||
totallums += L.lum_r + L.lum_b + L.lum_g
|
||||
L = lighting_corner_SW
|
||||
if (L)
|
||||
totallums += L.lum_r + L.lum_b + L.lum_g
|
||||
L = lighting_corner_NW
|
||||
if (L)
|
||||
totallums += L.lum_r + L.lum_b + L.lum_g
|
||||
|
||||
totallums /= 4 // 4 corners, max channel selected, return the average
|
||||
|
||||
totallums =(totallums - minlum) /(maxlum - minlum)
|
||||
totallums /= 12 // 4 corners, each with 3 channels, get the average.
|
||||
|
||||
totallums = (totallums - minlum) / (maxlum - minlum)
|
||||
|
||||
totallums += dynamic_lumcount
|
||||
|
||||
return CLAMP01(totallums)
|
||||
|
||||
// Can't think of a good name, this proc will recalculate the has_opaque_atom variable.
|
||||
/turf/proc/recalc_atom_opacity()
|
||||
has_opaque_atom = FALSE
|
||||
for(var/atom/A in src.contents + src) // Loop through every movable atom on our tile PLUS ourselves (we matter too...)
|
||||
if(A.opacity)
|
||||
has_opaque_atom = TRUE
|
||||
// Returns a boolean whether the turf is on soft lighting.
|
||||
// Soft lighting being the threshold at which point the overlay considers
|
||||
// itself as too dark to allow sight and see_in_dark becomes useful.
|
||||
// So basically if this returns true the tile is unlit black.
|
||||
/turf/proc/is_softly_lit()
|
||||
if (!lighting_object)
|
||||
return FALSE
|
||||
|
||||
// If an opaque movable atom moves around we need to potentially update visibility.
|
||||
/turf/Entered(var/atom/movable/Obj, var/atom/OldLoc)
|
||||
. = ..()
|
||||
return !(luminosity || dynamic_lumcount)
|
||||
|
||||
if(Obj && Obj.opacity)
|
||||
has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case.
|
||||
reconsider_lights()
|
||||
|
||||
/turf/Exited(var/atom/movable/Obj, var/atom/newloc)
|
||||
. = ..()
|
||||
///Proc to add movable sources of opacity on the turf and let it handle lighting code.
|
||||
/turf/proc/add_opacity_source(atom/movable/new_source)
|
||||
LAZYADD(opacity_sources, new_source)
|
||||
if(opacity)
|
||||
return
|
||||
recalculate_directional_opacity()
|
||||
|
||||
if(Obj && Obj.opacity)
|
||||
recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates.
|
||||
reconsider_lights()
|
||||
|
||||
/turf/proc/get_corners()
|
||||
if(has_opaque_atom)
|
||||
return null // Since this proc gets used in a for loop, null won't be looped though.
|
||||
///Proc to remove movable sources of opacity on the turf and let it handle lighting code.
|
||||
/turf/proc/remove_opacity_source(atom/movable/old_source)
|
||||
LAZYREMOVE(opacity_sources, old_source)
|
||||
if(opacity) //Still opaque, no need to worry on updating.
|
||||
return
|
||||
recalculate_directional_opacity()
|
||||
|
||||
return corners
|
||||
|
||||
///Calculate on which directions this turfs block view.
|
||||
/turf/proc/recalculate_directional_opacity()
|
||||
. = directional_opacity
|
||||
if(opacity)
|
||||
directional_opacity = ALL_CARDINALS
|
||||
if(. != directional_opacity)
|
||||
reconsider_lights()
|
||||
return
|
||||
directional_opacity = NONE
|
||||
for(var/atom/movable/opacity_source as anything in opacity_sources)
|
||||
if(opacity_source.flags & ON_BORDER)
|
||||
directional_opacity |= opacity_source.dir
|
||||
else //If fulltile and opaque, then the whole tile blocks view, no need to continue checking.
|
||||
directional_opacity = ALL_CARDINALS
|
||||
break
|
||||
if(. != directional_opacity && (. == ALL_CARDINALS || directional_opacity == ALL_CARDINALS))
|
||||
reconsider_lights() //The lighting system only cares whether the tile is fully concealed from all directions or not.
|
||||
|
||||
|
||||
/turf/proc/change_area(area/old_area, area/new_area)
|
||||
if(SSlighting.subsystem_initialized)
|
||||
if (new_area.dynamic_lighting != old_area.dynamic_lighting)
|
||||
if (new_area.dynamic_lighting)
|
||||
lighting_build_overlay()
|
||||
else
|
||||
lighting_clear_overlay()
|
||||
|
||||
/turf/proc/has_dynamic_lighting()
|
||||
var/area/A = loc
|
||||
return (IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A))
|
||||
|
||||
/turf/proc/generate_missing_corners()
|
||||
|
||||
if (!lighting_corner_NE)
|
||||
lighting_corner_NE = new/datum/lighting_corner(src, NORTH|EAST)
|
||||
|
||||
if (!lighting_corner_SE)
|
||||
lighting_corner_SE = new/datum/lighting_corner(src, SOUTH|EAST)
|
||||
|
||||
if (!lighting_corner_SW)
|
||||
lighting_corner_SW = new/datum/lighting_corner(src, SOUTH|WEST)
|
||||
|
||||
if (!lighting_corner_NW)
|
||||
lighting_corner_NW = new/datum/lighting_corner(src, NORTH|WEST)
|
||||
|
||||
lighting_corners_initialised = TRUE
|
||||
if(!corners)
|
||||
corners = list(null, null, null, null)
|
||||
|
||||
for(var/i = 1 to 4)
|
||||
if(corners[i]) // Already have a corner on this direction.
|
||||
continue
|
||||
|
||||
corners[i] = new /datum/lighting_corner(src, LIGHTING_CORNER_DIAGONAL[i])
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#undef LIGHTING_FALLOFF
|
||||
#undef LIGHTING_LAMBERTIAN
|
||||
#undef LIGHTING_HEIGHT
|
||||
|
||||
#undef LIGHTING_ICON
|
||||
|
||||
#undef LIGHTING_BASE_MATRIX
|
||||
@@ -4,7 +4,7 @@
|
||||
for(var/turf/simulated/T in block(locate(1,1,z), locate(world.maxx, world.maxy, z)))
|
||||
T.update_air_properties()
|
||||
//We missed sslighting init!
|
||||
if(lighting_overlays_initialised)
|
||||
if(SSlighting.subsystem_initialized)
|
||||
for(var/Trf in block(locate(1,1,z), locate(world.maxx, world.maxy, z)))
|
||||
var/turf/T = Trf //faster than implicit istype with typed for loop
|
||||
T.lighting_build_overlay()
|
||||
|
||||
@@ -159,7 +159,6 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
|
||||
var/model_key = copytext(line, tpos, tpos + key_len)
|
||||
line_keys[++line_keys.len] = model_key
|
||||
#ifdef TESTING
|
||||
else
|
||||
++turfsSkipped
|
||||
#endif
|
||||
CHECK_TICK
|
||||
|
||||
@@ -49,6 +49,24 @@ var/list/name_to_material
|
||||
if(material)
|
||||
return material.name
|
||||
|
||||
|
||||
/**
|
||||
* Returns the material composition of the atom.
|
||||
*
|
||||
* Used when recycling items, specifically to turn alloys back into their component mats.
|
||||
*
|
||||
* Exists because I'd need to add a way to un-alloy alloys or otherwise deal
|
||||
* with people converting the entire stations material supply into alloys.
|
||||
*
|
||||
* Arguments:
|
||||
* - breakdown_flags: A set of flags determining how exactly the materials are broken down. (unused)
|
||||
*/
|
||||
/obj/proc/get_material_composition(breakdown_flags=NONE)
|
||||
. = list()
|
||||
for(var/mat in matter)
|
||||
var/datum/material/M = GET_MATERIAL_REF(mat)
|
||||
.[M] = matter[mat]
|
||||
|
||||
// Builds the datum list above.
|
||||
/proc/populate_material_list(force_remake=0)
|
||||
if(name_to_material && !force_remake) return // Already set up!
|
||||
@@ -72,6 +90,73 @@ var/list/name_to_material
|
||||
return material.display_name
|
||||
return null
|
||||
|
||||
/** Fetches a cached material singleton when passed sufficient arguments.
|
||||
*
|
||||
* Arguments:
|
||||
* - [arguments][/list]: The list of arguments used to fetch the material ref.
|
||||
* - The first element is a material datum, text string, or material type.
|
||||
* - [Material datums][/datum/material] are assumed to be references to the cached datum and are returned
|
||||
* - Text is assumed to be the text ID of a material and the corresponding material is fetched from the cache
|
||||
* - A material type is checked for bespokeness:
|
||||
* - If the material type is not bespoke the type is assumed to be the id for a material and the corresponding material is loaded from the cache.
|
||||
* - If the material type is bespoke a text ID is generated from the arguments list and used to load a material datum from the cache.
|
||||
* - The following elements are used to generate bespoke IDs
|
||||
*/
|
||||
/proc/_GetMaterialRef(list/arguments)
|
||||
if(!name_to_material)
|
||||
populate_material_list()
|
||||
|
||||
var/datum/material/key = arguments[1]
|
||||
if(istype(key))
|
||||
return key // we want to convert anything we're given to a material
|
||||
|
||||
if(istext(key)) // text ID
|
||||
. = name_to_material[key]
|
||||
if(!.)
|
||||
warning("Attempted to fetch material ref with invalid text id '[key]'")
|
||||
return
|
||||
|
||||
if(!ispath(key, /datum/material))
|
||||
CRASH("Attempted to fetch material ref with invalid key [key]")
|
||||
|
||||
key = GetIdFromArguments(arguments)
|
||||
. = name_to_material[key]
|
||||
if(!.)
|
||||
warning("Attempted to fetch nonexistent material with key [key]")
|
||||
|
||||
/** I'm not going to lie, this was swiped from [SSdcs][/datum/controller/subsystem/processing/dcs].
|
||||
* Credit does to ninjanomnom
|
||||
*
|
||||
* Generates an id for bespoke ~~elements~~ materials when given the argument list
|
||||
* Generating the id here is a bit complex because we need to support named arguments
|
||||
* Named arguments can appear in any order and we need them to appear after ordered arguments
|
||||
* We assume that no one will pass in a named argument with a value of null
|
||||
**/
|
||||
/proc/GetIdFromArguments(list/arguments)
|
||||
var/datum/material/mattype = arguments[1]
|
||||
var/list/fullid = list("[initial(mattype.name) || mattype]")
|
||||
var/list/named_arguments = list()
|
||||
for(var/i in 2 to length(arguments))
|
||||
var/key = arguments[i]
|
||||
var/value
|
||||
if(istext(key))
|
||||
value = arguments[key]
|
||||
if(!(istext(key) || isnum(key)))
|
||||
key = REF(key)
|
||||
key = "[key]" // Key is stringified so numbers dont break things
|
||||
if(!isnull(value))
|
||||
if(!(istext(value) || isnum(value)))
|
||||
value = REF(value)
|
||||
named_arguments["[key]"] = value
|
||||
else
|
||||
fullid += "[key]"
|
||||
|
||||
if(length(named_arguments))
|
||||
named_arguments = sortList(named_arguments)
|
||||
fullid += named_arguments
|
||||
return replacetext(list2params(fullid), "+", " ")
|
||||
|
||||
|
||||
// Material definition and procs follow.
|
||||
/datum/material
|
||||
var/name // Unique name for use in indexing the list.
|
||||
@@ -131,7 +216,7 @@ var/list/name_to_material
|
||||
var/tableslam_noise = 'sound/weapons/tablehit1.ogg'
|
||||
// Noise made when a simple door made of this material opens or closes.
|
||||
var/dooropen_noise = 'sound/effects/stonedoor_openclose.ogg'
|
||||
// Path to resulting stacktype. Todo remove need for this.
|
||||
// Path to resulting stacktype.
|
||||
var/stack_type
|
||||
// Wallrot crumble message.
|
||||
var/rotting_touch_message = "crumbles under your touch"
|
||||
|
||||
@@ -27,14 +27,12 @@
|
||||
. += "\The [drying] is [drying.get_dryness_text()]."
|
||||
|
||||
/obj/structure/tanning_rack/update_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
if(drying)
|
||||
var/image/I
|
||||
if(drying.wetness)
|
||||
I = image(icon, "leather_wet")
|
||||
add_overlay("leather_wet")
|
||||
else
|
||||
I = image(icon, "leather_dry")
|
||||
add_overlay(I)
|
||||
add_overlay("leather_dry")
|
||||
|
||||
/obj/structure/tanning_rack/attackby(var/atom/A, var/mob/user)
|
||||
if(istype(A, /obj/item/stack/wetleather))
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
name = "lantern"
|
||||
icon_state = "lantern"
|
||||
desc = "A mining lantern."
|
||||
brightness_on = 6 // luminosity when on
|
||||
light_range = 6 // luminosity when on
|
||||
light_color = "FF9933" // A slight yellow/orange color.
|
||||
|
||||
/*****************************Pickaxe********************************/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
/obj/structure/outcrop/Initialize()
|
||||
. = ..()
|
||||
if(prob(1))
|
||||
overlays += image(icon, "[initial(icon_state)]-egg")
|
||||
add_overlay("[initial(icon_state)]-egg")
|
||||
|
||||
/obj/structure/outcrop/diamond
|
||||
name = "shiny outcrop"
|
||||
|
||||
@@ -125,7 +125,7 @@ turf/simulated/mineral/floor/light_corner
|
||||
|
||||
/turf/simulated/mineral/proc/update_general()
|
||||
update_icon(1)
|
||||
recalc_atom_opacity()
|
||||
recalculate_directional_opacity()
|
||||
if(ticker && ticker.current_state == GAME_STATE_PLAYING)
|
||||
reconsider_lights()
|
||||
if(air_master)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user