This commit is contained in:
izac112
2020-08-02 23:52:01 +02:00
181 changed files with 1441 additions and 516 deletions

View File

@@ -138,6 +138,8 @@ What is the naming convention for planes or layers?
#define PLANE_MESONS 30 //Stuff seen with mesons, like open ceilings. This is 30 for downstreams.
#define PLANE_STATUS 31 //Status Indicators that show over mobs' heads when certain things like stuns affect them.
#define PLANE_ADMIN2 33 //Purely for shenanigans (above lighting)
#define PLANE_BUILDMODE 39 //Things that only show up when you have buildmode on

View File

@@ -399,7 +399,9 @@
#define VIS_CLOAKED 23
#define VIS_COUNT 23 //Must be highest number from above.
#define VIS_STATUS 24
#define VIS_COUNT 24 //Must be highest number from above.
//Some mob icon layering defines
#define BODY_LAYER -100

View File

@@ -124,8 +124,7 @@
'sound/ambience/maintenance/maintenance2.ogg',\
'sound/ambience/maintenance/maintenance3.ogg',\
'sound/ambience/maintenance/maintenance4.ogg',\
'sound/ambience/maintenance/maintenance5.ogg',\
'sound/ambience/maintenance/maintenance6.ogg'\
'sound/ambience/maintenance/maintenance5.ogg'\
)
// Life support machinery at work, keeping everyone breathing.
@@ -155,7 +154,11 @@
// Concerning sounds, for when one discovers something horrible happened in a PoI.
#define AMBIENCE_FOREBODING list(\
'sound/ambience/foreboding/foreboding1.ogg',\
'sound/ambience/foreboding/foreboding2.ogg'\
'sound/ambience/foreboding/foreboding2.ogg',\
'sound/ambience/foreboding/foreboding3.ogg',\
'sound/ambience/foreboding/foreboding4.ogg',\
'sound/ambience/foreboding/foreboding5.ogg',\
'sound/ambience/foreboding/foreboding6.ogg'\
)
// Ambience heard when aboveground on Sif and not in a Point of Interest.

View File

@@ -281,3 +281,103 @@
return strtype
return copytext(strtype, delim_pos)
// Concatenates a list of strings into a single string. A seperator may optionally be provided.
/proc/list2text(list/ls, sep)
if (ls.len <= 1) // Early-out code for empty or singleton lists.
return ls.len ? ls[1] : ""
var/l = ls.len // Made local for sanic speed.
var/i = 0 // Incremented every time a list index is accessed.
if (sep != null)
// Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc...
#define S1 sep, ls[++i]
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
// Having the small concatenations come before the large ones boosted speed by an average of at least 5%.
if (l-1 & 0x01) // 'i' will always be 1 here.
. = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2.
if (l-i & 0x02)
. = text("[][][][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
if (l-i & 0x04)
. = text("[][][][][][][][][]", ., S4) // And so on....
if (l-i & 0x08)
. = text("[][][][][][][][][][][][][][][][][]", ., S4, S4)
if (l-i & 0x10)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16)
if (l-i & 0x20)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
if (l-i & 0x40)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
while (l > i) // Chomp through the rest of the list, 128 elements at a time.
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
#undef S1
else
// Macros expand to long argument lists like so: ls[++i], ls[++i], ls[++i], etc...
#define S1 ls[++i]
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
if (l-1 & 0x01) // 'i' will always be 1 here.
. += S1 // Append 1 element if the remaining elements are not a multiple of 2.
if (l-i & 0x02)
. = text("[][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
if (l-i & 0x04)
. = text("[][][][][]", ., S4) // And so on...
if (l-i & 0x08)
. = text("[][][][][][][][][]", ., S4, S4)
if (l-i & 0x10)
. = text("[][][][][][][][][][][][][][][][][]", ., S16)
if (l-i & 0x20)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
if (l-i & 0x40)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
while (l > i) // Chomp through the rest of the list, 128 elements at a time.
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
#undef S1
// Converts a string into a list by splitting the string at each delimiter found. (discarding the seperator)
/proc/text2list(text, delimiter="\n")
var/delim_len = length(delimiter)
if (delim_len < 1)
return list(text)
. = list()
var/last_found = 1
var/found
do
found = findtext(text, delimiter, last_found, 0)
. += copytext(text, last_found, found)
last_found = found + delim_len
while (found)

View File

@@ -1,107 +0,0 @@
/*
// Contains VOREStation type2type functions
// list2text - takes delimiter and returns text
// text2list - takes delimiter, and creates list
//
*/
// Concatenates a list of strings into a single string. A seperator may optionally be provided.
/proc/list2text(list/ls, sep)
if (ls.len <= 1) // Early-out code for empty or singleton lists.
return ls.len ? ls[1] : ""
var/l = ls.len // Made local for sanic speed.
var/i = 0 // Incremented every time a list index is accessed.
if (sep <> null)
// Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc...
#define S1 sep, ls[++i]
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
// Having the small concatenations come before the large ones boosted speed by an average of at least 5%.
if (l-1 & 0x01) // 'i' will always be 1 here.
. = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2.
if (l-i & 0x02)
. = text("[][][][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
if (l-i & 0x04)
. = text("[][][][][][][][][]", ., S4) // And so on....
if (l-i & 0x08)
. = text("[][][][][][][][][][][][][][][][][]", ., S4, S4)
if (l-i & 0x10)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16)
if (l-i & 0x20)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
if (l-i & 0x40)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
while (l > i) // Chomp through the rest of the list, 128 elements at a time.
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
#undef S1
else
// Macros expand to long argument lists like so: ls[++i], ls[++i], ls[++i], etc...
#define S1 ls[++i]
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
if (l-1 & 0x01) // 'i' will always be 1 here.
. += S1 // Append 1 element if the remaining elements are not a multiple of 2.
if (l-i & 0x02)
. = text("[][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
if (l-i & 0x04)
. = text("[][][][][]", ., S4) // And so on...
if (l-i & 0x08)
. = text("[][][][][][][][][]", ., S4, S4)
if (l-i & 0x10)
. = text("[][][][][][][][][][][][][][][][][]", ., S16)
if (l-i & 0x20)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
if (l-i & 0x40)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
while (l > i) // Chomp through the rest of the list, 128 elements at a time.
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
#undef S1
// Converts a string into a list by splitting the string at each delimiter found. (discarding the seperator)
/proc/text2list(text, delimiter="\n")
var/delim_len = length(delimiter)
if (delim_len < 1)
return list(text)
. = list()
var/last_found = 1
var/found
do
found = findtext(text, delimiter, last_found, 0)
. += copytext(text, last_found, found)
last_found = found + delim_len
while (found)

View File

@@ -0,0 +1,36 @@
// These involve BYOND's built in filters that do visual effects, and not stuff that distinguishes between things.
// All of this ported from TG.
/atom/movable
var/list/filter_data // For handling persistent filters
/proc/cmp_filter_data_priority(list/A, list/B)
return A["priority"] - B["priority"]
/atom/movable/proc/add_filter(filter_name, priority, list/params)
LAZYINITLIST(filter_data)
var/list/p = params.Copy()
p["priority"] = priority
filter_data[filter_name] = p
update_filters()
/atom/movable/proc/update_filters()
filters = null
filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE)
for(var/f in filter_data)
var/list/data = filter_data[f]
var/list/arguments = data.Copy()
arguments -= "priority"
filters += filter(arglist(arguments))
/atom/movable/proc/get_filter(filter_name)
if(filter_data && filter_data[filter_name])
return filters[filter_data.Find(filter_name)]
// Polaris Extensions
/atom/movable/proc/remove_filter(filter_name)
var/thing = get_filter(filter_name)
if(thing)
LAZYREMOVE(filter_data, filter_name)
filters -= thing
update_filters()

View File

@@ -261,6 +261,8 @@ var/global/datum/controller/subsystem/ticker/ticker
to_world("<span class='notice'><b>An admin has delayed the round end.</b></span>")
end_game_state = END_GAME_DELAYED
else if(restart_timeleft <= 0)
to_world("<span class='warning'><b>Restarting world!</b></span>")
sleep(5)
world.Reboot()
else if (world.time - last_restart_notify >= 1 MINUTE)
to_world("<span class='notice'><b>Restarting in [round(restart_timeleft/600, 1)] minute\s.</b></span>")

View File

@@ -54,6 +54,10 @@
name = "jar"
path =/obj/item/glass_jar
/datum/category_item/autolathe/general/fishtank
name = "fish tank"
path =/obj/item/glass_jar
/datum/category_item/autolathe/general/radio_headset
name = "radio headset"
path =/obj/item/device/radio/headset

View File

@@ -202,7 +202,9 @@
var/obj/belly/destination_belly = destination.loc
var/mob/living/telenommer = destination_belly.owner
if(istype(telenommer))
if(!isliving(teleatom))
if(istype(teleatom, /obj/machinery) || istype(teleatom, /obj/structure))
return 0
else if(!isliving(teleatom))
return 1
else
var/mob/living/telemob = teleatom

View File

@@ -49,6 +49,7 @@
var/sound_env = STANDARD_STATION
var/turf/base_turf //The base turf type of the area, which can be used to override the z-level's base turf
var/forbid_events = FALSE // If true, random events will not start inside this area.
var/no_spoilers = FALSE // If true, makes it much more difficult to see what is inside an area with things like mesons.
/area/Initialize()
. = ..()
@@ -64,6 +65,8 @@
power_equip = 0
power_environ = 0
power_change() // all machines set to current power level, also updates lighting icon
if(no_spoilers)
set_spoiler_obfuscation(TRUE)
return INITIALIZE_HINT_LATELOAD
// Changes the area of T to A. Do not do this manually.
@@ -367,7 +370,10 @@ var/list/mob/living/forced_ambiance_list = new
L.update_floating( L.Check_Dense_Object() )
L.lastarea = newarea
L.lastareachange = world.time
play_ambience(L)
if(no_spoilers)
L.disable_spoiler_vision()
/area/proc/play_ambience(var/mob/living/L)
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
@@ -500,4 +506,16 @@ var/list/ghostteleportlocs = list()
/area/proc/get_name()
if(secret_name)
return "Unknown Area"
return name
return name
GLOBAL_DATUM(spoiler_obfuscation_image, /image)
/area/proc/set_spoiler_obfuscation(should_obfuscate)
if(!GLOB.spoiler_obfuscation_image)
GLOB.spoiler_obfuscation_image = image(icon = 'icons/misc/static.dmi')
GLOB.spoiler_obfuscation_image.plane = PLANE_MESONS
if(should_obfuscate)
add_overlay(GLOB.spoiler_obfuscation_image)
else
cut_overlay(GLOB.spoiler_obfuscation_image)

View File

@@ -19,6 +19,8 @@
var/icon_scale_x = 1 // Used to scale icons up or down horizonally in update_transform().
var/icon_scale_y = 1 // Used to scale icons up or down vertically in update_transform().
var/icon_rotation = 0 // Used to rotate icons in update_transform()
var/icon_expected_height = 32
var/icon_expected_width = 32
var/old_x = 0
var/old_y = 0
var/datum/riding/riding_datum = null
@@ -561,6 +563,14 @@
return null
return text2num(pickweight(candidates))
// Returns the current scaling of the sprite.
// Note this DOES NOT measure the height or width of the icon, but returns what number is being multiplied with to scale the icons, if any.
/atom/movable/proc/get_icon_scale_x()
return icon_scale_x
/atom/movable/proc/get_icon_scale_y()
return icon_scale_y
/atom/movable/proc/update_transform()
var/matrix/M = matrix()
M.Scale(icon_scale_x, icon_scale_y)

View File

@@ -83,7 +83,7 @@
for(var/mob/living/carbon/M in ohearers(6, T))
if(M.get_ear_protection() >= 2)
continue
M.sleeping = 0
M.SetSleeping(0)
M.stuttering += 20
M.ear_deaf += 30
M.Weaken(3)

View File

@@ -162,6 +162,11 @@
else
return
/obj/machinery/bodyscanner/tgui_host(mob/user)
if(user == occupant)
return src
return console ? console : src
/obj/machinery/bodyscanner/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)

View File

@@ -788,3 +788,14 @@
..()
spawn(rand(0,15))
update_icon()
// VOREStation Edit Start
/obj/machinery/alarm/freezer
target_temperature = T0C - 13.15 // Chilly freezer room
/obj/machinery/alarm/freezer/first_run()
. = ..()
TLV["temperature"] = list(T0C - 40, T0C - 20, T0C + 40, T0C + 66) // K, Lower Temperature for Freezer Air Alarms (This is because TLV is hardcoded to be generated on first_run, and therefore the only way to modify this without changing TLV generation)
// VOREStation Edit End

View File

@@ -85,7 +85,10 @@
return
if(!occupier)
restoring = FALSE
if(action)
playsound(src, "terminal_type", 50, 1)
switch(action)
if("PRG_beginReconstruction")
if(occupier?.health < 100)

View File

@@ -156,6 +156,7 @@
blocked = 1
var/attackamt = rand(2,6)
temp = "You attack for [attackamt] damage!"
playsound(src, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 10)
if(turtle > 0)
turtle--
@@ -168,6 +169,7 @@
var/pointamt = rand(1,3)
var/healamt = rand(6,8)
temp = "You use [pointamt] magic to heal for [healamt] damage!"
playsound(src, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 10)
turtle++
sleep(10)
@@ -180,6 +182,7 @@
blocked = 1
var/chargeamt = rand(4,7)
temp = "You regain [chargeamt] points"
playsound(src, 'sound/arcade/mana.ogg', 50, 1, extrarange = -3, falloff = 10)
player_mp += chargeamt
if(turtle > 0)
turtle--
@@ -210,6 +213,7 @@
if(!gameover)
gameover = 1
temp = "[enemy_name] has fallen! Rejoice!"
playsound(src, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10)
if(emagged)
feedback_inc("arcade_win_emagged")
@@ -230,11 +234,13 @@
else if (emagged && (turtle >= 4))
var/boomamt = rand(5,10)
enemy_action = "[enemy_name] throws a bomb, exploding you for [boomamt] damage!"
playsound(src, 'sound/arcade/boom.ogg', 50, 1, extrarange = -3, falloff = 10)
player_hp -= boomamt
else if ((enemy_mp <= 5) && (prob(70)))
var/stealamt = rand(2,3)
enemy_action = "[enemy_name] steals [stealamt] of your power!"
playsound(src, 'sound/arcade/steal.ogg', 50, 1, extrarange = -3, falloff = 10)
player_mp -= stealamt
if (player_mp <= 0)
@@ -249,17 +255,20 @@
else if ((enemy_hp <= 10) && (enemy_mp > 4))
enemy_action = "[enemy_name] heals for 4 health!"
playsound(src, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 10)
enemy_hp += 4
enemy_mp -= 4
else
var/attackamt = rand(3,6)
enemy_action = "[enemy_name] attacks for [attackamt] damage!"
playsound(src, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 10)
player_hp -= attackamt
if ((player_mp <= 0) || (player_hp <= 0))
gameover = 1
temp = "You have been crushed! GAME OVER"
playsound(src, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10)
if(emagged)
feedback_inc("arcade_loss_hp_emagged")
usr.gib()
@@ -393,6 +402,7 @@
user.set_machine(src)
var/dat = ""
if(gameStatus == ORION_STATUS_GAMEOVER)
playsound(src, 'sound/arcade/Ori_fail.ogg', 50, 1, extrarange = -3, falloff = 10)
dat = "<center><h1>Game Over</h1></center>"
dat += "Like many before you, your crew never made it to Orion, lost to space... <br><b>forever</b>."
if(settlers.len == 0)
@@ -527,6 +537,7 @@
else if(href_list["newgame"]) //Reset everything
if(gameStatus == ORION_STATUS_START)
playsound(src, 'sound/arcade/Ori_begin.ogg', 50, 1, extrarange = -3, falloff = 10)
newgame()
else if(href_list["menu"]) //back to the main menu
if(gameStatus == ORION_STATUS_GAMEOVER)
@@ -598,6 +609,7 @@
else if(href_list["killcrew"]) //shoot a crewmember
if(gameStatus == ORION_STATUS_NORMAL || event == ORION_TRAIL_MUTINY)
playsound(src, 'sound/arcade/kill_crew.ogg', 50, 1, extrarange = -3, falloff = 10)
var/sheriff = remove_crewmember() //I shot the sheriff
var/mob/living/L = usr
if(!istype(L))
@@ -623,6 +635,7 @@
else if(href_list["buycrew"]) //buy a crewmember
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided && food >= 10 && fuel >= 10)
playsound(src, 'sound/arcade/get_fuel.ogg', 50, 1, extrarange = -3, falloff = 10)
var/bought = add_crewmember()
last_spaceport_action = "You hired [bought] as a new crewmember."
fuel -= 10
@@ -632,6 +645,7 @@
else if(href_list["sellcrew"]) //sell a crewmember
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided && settlers.len > 1)
playsound(src, 'sound/arcade/lose_fuel.ogg', 50, 1, extrarange = -3, falloff = 10)
var/sold = remove_crewmember()
last_spaceport_action = "You sold your crewmember, [sold]!"
fuel += 7
@@ -649,6 +663,7 @@
else if(href_list["raid_spaceport"])
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided)
playsound(src, 'sound/arcade/raid.ogg', 50, 1, extrarange = -3, falloff = 10)
var/success = min(15 * alive,100) //default crew (4) have a 60% chance
spaceport_raided = 1
@@ -687,6 +702,7 @@
else if(href_list["buyparts"])
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided && fuel > 5)
playsound(src, 'sound/arcade/get_fuel.ogg', 50, 1, extrarange = -3, falloff = 10)
switch(text2num(href_list["buyparts"]))
if(1) //Engine Parts
engine++
@@ -703,6 +719,7 @@
else if(href_list["trade"])
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided)
playsound(src, 'sound/arcade/get_fuel.ogg', 50, 1, extrarange = -3, falloff = 10)
switch(text2num(href_list["trade"]))
if(1) //Fuel
if(fuel > 5)
@@ -745,6 +762,7 @@
canContinueEvent = 1
if(ORION_TRAIL_FLUX)
playsound(src, 'sound/arcade/explo.ogg', 50, 1, extrarange = -3, falloff = 10)
eventdat += "This region of space is highly turbulent. <br>If we go slowly we may avoid more damage, but if we keep our speed we won't waste supplies."
eventdat += "<br>What will you do?"
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];slow=1'>Slow Down</a> <a href='byond://?src=\ref[src];keepspeed=1'>Continue</a></P>"
@@ -759,6 +777,7 @@
canContinueEvent = 1
if(ORION_TRAIL_BREAKDOWN)
playsound(src, 'sound/arcade/explo.ogg', 50, 1, extrarange = -3, falloff = 10)
eventdat += "Oh no! The engine has broken down!"
eventdat += "<br>You can repair it with an engine part, or you can make repairs for 3 days."
if(engine >= 1)
@@ -777,6 +796,7 @@
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];close=1'>Close</a></P>"
if(ORION_TRAIL_COLLISION)
playsound(src, 'sound/arcade/explo.ogg', 50, 1, extrarange = -3, falloff = 10)
eventdat += "Something hit us! Looks like there's some hull damage."
if(prob(25))
var/sfood = rand(5,15)
@@ -992,6 +1012,7 @@
/obj/machinery/computer/arcade/orion_trail/proc/win()
gameStatus = ORION_STATUS_START
src.visible_message("\The [src] plays a triumpant tune, stating 'CONGRATULATIONS, YOU HAVE MADE IT TO ORION.'")
playsound(src, 'sound/arcade/Ori_win.ogg', 50, 1, extrarange = -3, falloff = 10)
if(emagged)
new /obj/item/weapon/orion_ship(src.loc)
message_admins("[key_name_admin(usr)] made it to Orion on an emagged machine and got an explosive toy ship.")

View File

@@ -70,11 +70,13 @@
set_light(0)
if(icon_keyboard)
add_overlay("[icon_keyboard]_off")
playsound(src, 'sound/machines/terminal_off.ogg', 50, 1)
// Yes power
else
if(icon_keyboard)
add_overlay(icon_keyboard)
set_light(light_range_on, light_power_on)
playsound(src, 'sound/machines/terminal_on.ogg', 50, 1)
// Broken
if(stat & BROKEN)

View File

@@ -216,7 +216,7 @@
occupant.set_stat(UNCONSCIOUS)
occupant.dir = SOUTH
if(occupant.bodytemperature < T0C)
occupant.sleeping = max(5, (1/occupant.bodytemperature)*2000)
occupant.Sleeping(max(5, (1/occupant.bodytemperature)*2000))
occupant.Paralyse(max(5, (1/occupant.bodytemperature)*3000))
if(air_contents.gas["oxygen"] > 2)
if(occupant.getOxyLoss()) occupant.adjustOxyLoss(-1)

View File

@@ -22,6 +22,8 @@
var/icon_state_opening = null
var/icon_state_closed = null
var/icon_state_closing = null
var/open_sound = 'sound/machines/blastdooropen.ogg'
var/close_sound = 'sound/machines/blastdoorclose.ogg'
closed_layer = ON_WINDOW_LAYER // Above airlocks when closed
var/id = 1.0
@@ -72,6 +74,7 @@
// Description: Opens the door. No checks are done inside this proc.
/obj/machinery/door/blast/proc/force_open()
src.operating = 1
playsound(src, open_sound, 100, 1)
flick(icon_state_opening, src)
src.density = 0
update_nearby_tiles()
@@ -86,6 +89,7 @@
// Description: Closes the door. No checks are done inside this proc.
/obj/machinery/door/blast/proc/force_close()
src.operating = 1
playsound(src, close_sound, 100, 1)
src.layer = closed_layer
flick(icon_state_closing, src)
src.density = 1

View File

@@ -128,7 +128,7 @@
return
// If the human is losing too much blood, beep.
if(((T.vessel.get_reagent_amount("blood")/T.species.blood_volume)*100) < BLOOD_VOLUME_SAFE)
if(T.vessel.get_reagent_amount("blood") < T.species.blood_volume*T.species.blood_level_safe)
visible_message("\The [src] beeps loudly.")
var/datum/reagent/B = T.take_blood(beaker,amount)

View File

@@ -221,7 +221,7 @@
for(var/mob/living/carbon/M in ohearers(6, src))
if(M.get_ear_protection() >= 2)
continue
M.sleeping = 0
M.SetSleeping(0)
M.stuttering += 20
M.ear_deaf += 30
M.Weaken(3)

View File

@@ -822,6 +822,7 @@
var/atom/flick_holder = new /atom/movable/porta_turret_cover(loc)
flick_holder.layer = layer + 0.1
flick("popup_[turret_type]", flick_holder)
playsound(src, 'sound/machines/turrets/turret_deploy.ogg', 100, 1)
sleep(10)
qdel(flick_holder)
@@ -843,6 +844,7 @@
var/atom/flick_holder = new /atom/movable/porta_turret_cover(loc)
flick_holder.layer = layer + 0.1
flick("popdown_[turret_type]", flick_holder)
playsound(src, 'sound/machines/turrets/turret_retract.ogg', 100, 1)
sleep(10)
qdel(flick_holder)
@@ -863,6 +865,7 @@
spawn()
popUp() //pop the turret up if it's not already up.
set_dir(get_dir(src, target)) //even if you can't shoot, follow the target
playsound(src, 'sound/machines/turrets/turret_rotate.ogg', 100, 1) // Play rotating sound
spawn()
shootAt(target)
return 1

View File

@@ -558,11 +558,13 @@
/obj/item/weapon/storage/box/wormcan = 4,
/obj/item/weapon/storage/box/wormcan/sickly = 10,
/obj/item/weapon/material/fishing_net = 2,
/obj/item/glass_jar/fish = 4,
/obj/item/stack/cable_coil/random = 6)
prices = list(/obj/item/weapon/material/fishing_rod/modern/cheap = 50,
/obj/item/weapon/storage/box/wormcan = 12,
/obj/item/weapon/storage/box/wormcan/sickly = 6,
/obj/item/weapon/material/fishing_net = 40,
/obj/item/glass_jar/fish = 10,
/obj/item/stack/cable_coil/random = 4)
premium = list(/obj/item/weapon/storage/box/wormcan/deluxe = 1)
contraband = list(/obj/item/weapon/storage/box/wormcan/deluxe = 1)

View File

@@ -26,7 +26,7 @@
return
to_chat(M, "<span class='warning'>Your ears feel like they're bleeding!</span>")
playsound(M, 'sound/effects/bang.ogg', 70, 1, 30)
M.sleeping = 0
M.SetSleeping(0)
M.ear_deaf += 30
M.ear_damage += rand(5, 20)
M.Weaken(3)

View File

@@ -44,7 +44,7 @@
)
var/damage_minimum = 10 //Incoming damage lower than this won't actually deal damage. Scrapes shouldn't be a real thing.
var/minimum_penetration = 20 //Incoming damage won't be fully applied if you don't have at least 20. Almost all AP clears this.
var/minimum_penetration = 15 //Incoming damage won't be fully applied if you don't have at least 20. Almost all AP clears this.
var/fail_penetration_value = 0.66 //By how much failing to penetrate reduces your shit. 66% by default.
var/obj/item/weapon/cell/cell
@@ -75,8 +75,9 @@
var/obj/item/device/radio/radio = null
var/max_temperature = 25000
var/internal_damage_threshold = 50 //health percentage below which internal damage is possible
var/max_temperature = 25000 //Kelvin values.
var/internal_damage_threshold = 33 //health percentage below which internal damage is possible
var/internal_damage_minimum = 15 //At least this much damage to trigger some real bad hurt.
var/internal_damage = 0 //contains bitflags
var/list/operation_req_access = list()//required access level for mecha operation
@@ -583,6 +584,15 @@
last_message = world.time
return 0
/*
//A first draft of a check to stop mechs from moving fully. TBD when all thrusters modules are unified.
if(!thrusters && !src.pr_inertial_movement.active() && isspace(src.loc))//No thrsters, not drifting, in space
src.occupant_message("Error 543")//debug
return 0
*/
if(!thrusters && src.pr_inertial_movement.active()) //I think this mean 'if you try to move in space without thruster, u no move'
return 0
@@ -721,18 +731,21 @@
//////// Internal damage ////////
///////////////////////////////////
//ATM, the ignore_threshold is literally only used for the pulse rifles beams used mostly by deathsquads.
/obj/mecha/proc/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null)
if(!islist(possible_int_damage) || isemptylist(possible_int_damage)) return
if(prob(20))
if(ignore_threshold || src.health*100/initial(src.health)<src.internal_damage_threshold)
if(prob(30))
if(ignore_threshold || src.health*100/initial(src.health) < src.internal_damage_threshold)
for(var/T in possible_int_damage)
if(internal_damage & T)
possible_int_damage -= T
var/int_dam_flag = safepick(possible_int_damage)
if(int_dam_flag)
setInternalDamage(int_dam_flag)
if(prob(5))
if(ignore_threshold || src.health*100/initial(src.health)<src.internal_damage_threshold)
return //It already hurts to get some, lets not get both.
if(prob(10))
if(ignore_threshold || src.health*100/initial(src.health) < src.internal_damage_threshold)
var/obj/item/mecha_parts/mecha_equipment/destr = safepick(equipment)
if(destr)
destr.destroy()
@@ -786,7 +799,8 @@
/obj/mecha/airlock_crush(var/crush_damage)
..()
take_damage(crush_damage)
check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
if(prob(50)) //Try to avoid that.
check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return 1
/obj/mecha/proc/update_health()
@@ -808,8 +822,9 @@
var/mob/living/carbon/human/H = user
if(H.species.can_shred(user))
if(!prob(src.deflect_chance))
src.take_damage(15)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
src.take_damage(15) //The take_damage() proc handles armor values
if(prob(25)) //Why would they get free internal damage. At least make it a bit RNG.
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
to_chat(user, "<span class='danger'>You slash at the armored suit!</span>")
visible_message("<span class='danger'>\The [user] slashes at [src.name]'s armor!</span>")
@@ -824,8 +839,9 @@
src.log_append_to_last("Armor saved.")
return
else if ((HULK in user.mutations) && !prob(src.deflect_chance))
src.take_damage(15)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
src.take_damage(15) //The take_damage() proc handles armor values
if(prob(25)) //Hulks punch hard but lets not give them consistent internal damage.
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
user.visible_message("<font color='red'><b>[user] hits [src.name], doing some damage.</b></font>", "<font color='red'><b>You hit [src.name] with all your might. The metal creaks and bends.</b></font>")
else
user.visible_message("<font color='red'><b>[user] hits [src.name]. Nothing happens.</b></font>","<font color='red'><b>You hit [src.name] with no visible effect.</b></font>")
@@ -877,8 +893,9 @@
pass_damage = ME.handle_ranged_contact(A, pass_damage)
pass_damage = (pass_damage*pass_damage_reduc_mod)//Applying damage reduction
src.take_damage(pass_damage)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
src.take_damage(pass_damage) //The take_damage() proc handles armor values
if(pass_damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return
@@ -905,7 +922,7 @@
if(!(Proj.nodamage))
var/ignore_threshold
if(istype(Proj, /obj/item/projectile/beam/pulse))
if(istype(Proj, /obj/item/projectile/beam/pulse)) //ATM, this is literally only for the pulse rifles used mostly by deathsquads.
ignore_threshold = 1
var/pass_damage = Proj.damage
@@ -922,15 +939,18 @@
src.occupant_message("<span class='notice'>\The [Proj] struggles to pierce \the [src] armor.</span>")
src.visible_message("\The [Proj] struggles to pierce \the [src] armor")
pass_damage_reduc_mod = fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
else
else //You go through completely because you use AP. Nice.
src.occupant_message("<span class='notice'>\The [Proj] manages to pierce \the [src] armor.</span>")
src.visible_message("\The [Proj] manages to pierce \the [src] armor")
pass_damage_reduc_mod = 1
pass_damage = (pass_damage_reduc_mod*pass_damage)//Apply damage reduction before usage.
src.take_damage(pass_damage, Proj.check_armour)
if(prob(25)) spark_system.start()
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold)
src.take_damage(pass_damage, Proj.check_armour) //The take_damage() proc handles armor values
if(prob(25))
spark_system.start()
if(pass_damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold)
//AP projectiles have a chance to cause additional damage
if(Proj.penetrating)
@@ -941,7 +961,8 @@
Proj.attack_mob(src.occupant, distance)
hit_occupant = 0
else
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT), 1)
if(pass_damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT), 1)
Proj.penetrating--
@@ -964,13 +985,13 @@
if (prob(30))
qdel(src)
else
src.take_damage(initial(src.health)/2)
src.take_damage(initial(src.health)/2) //The take_damage() proc handles armor values
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
if(3.0)
if (prob(5))
qdel(src)
else
src.take_damage(initial(src.health)/5)
src.take_damage(initial(src.health)/5) //The take_damage() proc handles armor values
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
return
@@ -1001,13 +1022,14 @@
use_power((cell.charge/2)/severity)
take_damage(50 / severity,"energy")
src.log_message("EMP detected",1)
check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
if(prob(80))
check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
return
/obj/mecha/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature>src.max_temperature)
src.log_message("Exposed to dangerous temperature.",1)
src.take_damage(5,"fire")
src.take_damage(5,"fire") //The take_damage() proc handles armor values
src.check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL))
return
@@ -1037,11 +1059,12 @@
user.visible_message("<font color='red'><b>[user] hits [src] with [W].</b></font>", "<font color='red'><b>You hit [src] with [W].</b></font>")
var/pass_damage = W.force
pass_damage = (pass_damage*pass_damage_reduc_mod) //Apply the reduction of damage from not having enough armor penetration.
pass_damage = (pass_damage*pass_damage_reduc_mod) //Apply the reduction of damage from not having enough armor penetration. This is not regular armor values at play.
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
pass_damage = ME.handle_projectile_contact(W, pass_damage)
src.take_damage(pass_damage,W.damtype)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
pass_damage = ME.handle_projectile_contact(W, user, pass_damage)
src.take_damage(pass_damage,W.damtype) //The take_damage() proc handles armor values
if(pass_damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return
//////////////////////
@@ -2290,8 +2313,6 @@
src.log_message("Attacked. Attacker - [user].",1)
user.do_attack_animation(src)
//var/pass_damage //See the comment in the larger greyed out block below.
//var/pass_damage_reduc_mod
if(prob(src.deflect_chance))//Deflected
src.log_append_to_last("Armor saved.")
src.occupant_message("<span class='notice'>\The [user]'s attack is stopped by the armor.</span>")
@@ -2306,17 +2327,10 @@
playsound(src, 'sound/effects/Glasshit.ogg', 50, 1)
return
/*//Commented out for not playing well with penetration questions.
else if(user.mob.attack_armor_pen < minimum_penetration)//Not enough armor penetration
src.occupant_message("<span class='notice'>\The [user] struggles to pierce \the [src] armor.</span>")
src.visible_message("\The [user] struggles to pierce \the [src] armor")
pass_damage_reduc_mod = fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default.
*/
else
//pass_damage = (pass_damage_reduc_mod*damage)
src.take_damage(damage)//apply damage
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
src.take_damage(damage) //Apply damage - The take_damage() proc handles armor values
if(damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
visible_message("<span class='danger'>[user] [attack_message] [src]!</span>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>attacked [src.name]</font>")
@@ -2399,7 +2413,7 @@
if(mecha.cabin_air && mecha.cabin_air.volume>0)
mecha.cabin_air.temperature = min(6000+T0C, mecha.cabin_air.temperature+rand(10,15))
if(mecha.cabin_air.temperature>mecha.max_temperature/2)
mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.temperature,0.1),"fire")
mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.temperature,0.1),"fire") //The take_damage() proc handles armor values
if(mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL)) //stop the mecha_preserve_temp loop datum
mecha.pr_int_temp_processor.stop()
if(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH)) //remove some air from internal tank

View File

@@ -5,6 +5,8 @@
plane = DIRTY_PLANE
anchored = 1
var/amount = 1
generic_filth = TRUE
persistent = FALSE
/obj/effect/decal/cleanable/liquid_fuel/New(turf/newLoc,amt=1,nologs=1)
if(!nologs)

View File

@@ -338,14 +338,14 @@
if(!heart)
return TRUE
var/blood_volume = round((H.vessel.get_reagent_amount("blood")/H.species.blood_volume)*100)
var/blood_volume = H.vessel.get_reagent_amount("blood")
if(!heart || heart.is_broken())
blood_volume *= 0.3
else if(heart.is_bruised())
blood_volume *= 0.7
else if(heart.damage > 1)
blood_volume *= 0.8
return blood_volume < BLOOD_VOLUME_SURVIVE
return blood_volume < H.species.blood_volume*H.species.blood_level_fatal
/obj/item/weapon/shockpaddles/proc/check_charge(var/charge_amt)
return 0

View File

@@ -138,7 +138,7 @@
for(var/mob/living/carbon/M in oviewers(4, T))
if(M.get_ear_protection() >= 2)
continue
M.sleeping = 0
M.SetSleeping(0)
M.stuttering += 20
M.ear_deaf += 30
M.Weaken(3)

View File

@@ -272,9 +272,11 @@ HALOGEN COUNTER - Radcount on mobs
var/blood_volume = H.vessel.get_reagent_amount("blood")
var/blood_percent = round((blood_volume / H.species.blood_volume)*100)
var/blood_type = H.dna.b_type
if(blood_percent <= BLOOD_VOLUME_BAD)
if(blood_volume <= H.species.blood_volume*H.species.blood_level_danger)
dat += "<span class='danger'><i>Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl. Type: [blood_type]</i></span><br>"
else if(blood_percent <= BLOOD_VOLUME_SAFE)
else if(blood_volume <= H.species.blood_volume*H.species.blood_level_warning)
dat += "<span class='danger'><i>Warning: Blood Level VERY LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]</i></span><br>"
else if(blood_volume <= H.species.blood_volume*H.species.blood_level_safe)
dat += "<span class='danger'>Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]</span><br>"
else
dat += "<span class='notice'>Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]</span><br>"

View File

@@ -1,3 +1,9 @@
#define JAR_NOTHING 0
#define JAR_MONEY 1
#define JAR_ANIMAL 2
#define JAR_SPIDER 3
/obj/item/glass_jar
name = "glass jar"
desc = "A small empty jar."
@@ -27,7 +33,7 @@
var/mob/L = A
user.visible_message("<span class='notice'>[user] scoops [L] into \the [src].</span>", "<span class='notice'>You scoop [L] into \the [src].</span>")
L.loc = src
contains = 2
contains = JAR_ANIMAL
update_icon()
return
else if(istype(A, /obj/effect/spider/spiderling))
@@ -35,40 +41,40 @@
user.visible_message("<span class='notice'>[user] scoops [S] into \the [src].</span>", "<span class='notice'>You scoop [S] into \the [src].</span>")
S.loc = src
STOP_PROCESSING(SSobj, S) // No growing inside jars
contains = 3
contains = JAR_SPIDER
update_icon()
return
/obj/item/glass_jar/attack_self(var/mob/user)
switch(contains)
if(1)
if(JAR_MONEY)
for(var/obj/O in src)
O.loc = user.loc
to_chat(user, "<span class='notice'>You take money out of \the [src].</span>")
contains = 0
contains = JAR_NOTHING
update_icon()
return
if(2)
if(JAR_ANIMAL)
for(var/mob/M in src)
M.loc = user.loc
user.visible_message("<span class='notice'>[user] releases [M] from \the [src].</span>", "<span class='notice'>You release [M] from \the [src].</span>")
contains = 0
contains = JAR_NOTHING
update_icon()
return
if(3)
if(JAR_SPIDER)
for(var/obj/effect/spider/spiderling/S in src)
S.loc = user.loc
user.visible_message("<span class='notice'>[user] releases [S] from \the [src].</span>", "<span class='notice'>You release [S] from \the [src].</span>")
START_PROCESSING(SSobj, S) // They can grow after being let out though
contains = 0
contains = JAR_NOTHING
update_icon()
return
/obj/item/glass_jar/attackby(var/obj/item/W, var/mob/user)
if(istype(W, /obj/item/weapon/spacecash))
if(contains == 0)
contains = 1
if(contains != 1)
if(contains == JAR_NOTHING)
contains = JAR_MONEY
if(contains != JAR_MONEY)
return
var/obj/item/weapon/spacecash/S = W
user.visible_message("<span class='notice'>[user] puts [S.worth] [S.worth > 1 ? "thalers" : "thaler"] into \the [src].</span>")
@@ -80,10 +86,10 @@
underlays.Cut()
overlays.Cut()
switch(contains)
if(0)
if(JAR_NOTHING)
name = initial(name)
desc = initial(desc)
if(1)
if(JAR_MONEY)
name = "tip jar"
desc = "A small jar with money inside."
for(var/obj/item/weapon/spacecash/S in src)
@@ -92,7 +98,7 @@
money.pixel_y = rand(-6, 6)
money.transform *= 0.6
underlays += money
if(2)
if(JAR_ANIMAL)
for(var/mob/M in src)
var/image/victim = image(M.icon, M.icon_state)
victim.pixel_y = 6
@@ -105,10 +111,109 @@
underlays += victim
name = "glass jar with [M]"
desc = "A small jar with [M] inside."
if(3)
if(JAR_SPIDER)
for(var/obj/effect/spider/spiderling/S in src)
var/image/victim = image(S.icon, S.icon_state)
underlays += victim
name = "glass jar with [S]"
desc = "A small jar with [S] inside."
return
return
/obj/item/glass_jar/fish
name = "glass tank"
desc = "A large glass tank."
var/filled = FALSE
w_class = ITEMSIZE_NORMAL
accept_mobs = list(/mob/living/simple_mob/animal/passive/lizard, /mob/living/simple_mob/animal/passive/mouse, /mob/living/simple_mob/animal/sif/leech, /mob/living/simple_mob/animal/sif/frostfly, /mob/living/simple_mob/animal/sif/glitterfly, /mob/living/simple_mob/animal/passive/fish)
/obj/item/glass_jar/fish/plastic
name = "plastic tank"
desc = "A large plastic tank."
matter = list("plastic" = 4000)
/obj/item/glass_jar/fish/update_icon() // Also updates name and desc
underlays.Cut()
overlays.Cut()
if(filled)
underlays += image(icon, "[icon_state]_water")
switch(contains)
if(JAR_NOTHING)
name = initial(name)
desc = initial(desc)
if(JAR_MONEY)
name = "tip tank"
desc = "A large [name] with money inside."
for(var/obj/item/weapon/spacecash/S in src)
var/image/money = image(S.icon, S.icon_state)
money.pixel_x = rand(-2, 3)
money.pixel_y = rand(-6, 6)
money.transform *= 0.6
underlays += money
if(JAR_ANIMAL)
for(var/mob/M in src)
var/image/victim = image(M.icon, M.icon_state)
var/initial_x_scale = M.icon_scale_x
var/initial_y_scale = M.icon_scale_y
M.adjust_scale(0.7)
victim.appearance = M.appearance
M.adjust_scale(initial_x_scale, initial_y_scale)
victim.pixel_y = 4
underlays += victim
name = "[name] with [M]"
desc = "A large [name] with [M] inside."
if(JAR_SPIDER)
for(var/obj/effect/spider/spiderling/S in src)
var/image/victim = image(S.icon, S.icon_state)
underlays += victim
name = "[name] with [S]"
desc = "A large tank with [S] inside."
if(filled)
desc = "[desc] It contains water."
return
/obj/item/glass_jar/fish/afterattack(var/atom/A, var/mob/user, var/proximity)
if(!filled)
if(istype(A, /obj/structure/sink) || istype(A, /turf/simulated/floor/water))
if(contains && user.a_intent == "help")
to_chat(user, "<span class='warning'>That probably isn't the best idea.</span>")
return
to_chat(user, "<span class='notice'>You fill \the [src] with water!</span>")
filled = TRUE
update_icon()
return
return ..()
/obj/item/glass_jar/fish/attack_self(var/mob/user)
if(filled)
if(contains == JAR_ANIMAL)
if(user.a_intent == "help")
to_chat(user, "<span class='notice'>Maybe you shouldn't empty the water...</span>")
return
else
filled = FALSE
user.visible_message("<span class='warning'>[user] dumps out \the [src]'s water!</span>")
update_icon()
return
else
user.visible_message("<span class='notice'>[user] dumps \the [src]'s water.</span>")
filled = FALSE
update_icon()
return
return ..()
#undef JAR_NOTHING
#undef JAR_MONEY
#undef JAR_ANIMAL
#undef JAR_SPIDER

View File

@@ -25,7 +25,9 @@
user.visible_message("<span class='notice'>[user] presses a button on [src]!</span>")
desc = desc + " This one seems to be used-up."
spent = TRUE
user.visible_message("<span class='notice'>A small bluespace rift opens just above your head and spits out a pizza box!</span>")
user.visible_message("<span class='notice'>A small bluespace rift opens just above [user]'s head and spits out a pizza box!</span>",
"<span class='notice'>A small bluespace rift opens just above your head and spits out a pizza box!</span>",
"<span class='notice'>You hear a fwoosh followed by a thump.</span>")
if(special_delivery)
command_announcement.Announce("SPECIAL DELIVERY PIZZA ORDER #[rand(1000,9999)]-[rand(100,999)] HAS BEEN RECIEVED. SHIPMENT DISPATCHED VIA EXTRA-POWERFUL BALLISTIC LAUNCHERS FOR IMMEDIATE DELIVERY! THANK YOU AND ENJOY YOUR PIZZA!", "WE ALWAYS DELIVER!")
new /obj/effect/falling_effect/pizza_delivery/special(user.loc)
@@ -59,4 +61,4 @@
return INITIALIZE_HINT_LATELOAD
/obj/effect/falling_effect/pizza_delivery/special
crushing = TRUE
crushing = TRUE

View File

@@ -14,6 +14,14 @@
drop_sound = 'sound/voice/weh.ogg'
attack_verb = list("raided", "kobolded", "weh'd")
/obj/item/toy/plushie/lizardplushie/resh
name = "security unathi plushie"
desc = "An adorable stuffed toy that resembles an unathi wearing a head of security uniform. Perfect example of a monitor lizard."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "marketable_resh"
pokephrase = "Halt! Sssecurity!" //"Butts!" would be too obvious
attack_verb = list("valided", "justiced", "batoned")
/obj/item/toy/plushie/slimeplushie
name = "slime plushie"
desc = "An adorable stuffed toy that resembles a slime. It is practically just a hacky sack."

View File

@@ -473,6 +473,7 @@
//VOREStation Add Start
/obj/item/toy/plushie/lizardplushie,
/obj/item/toy/plushie/lizardplushie/kobold,
/obj/item/toy/plushie/lizardplushie/resh,
/obj/item/toy/plushie/slimeplushie,
/obj/item/toy/plushie/box,
/obj/item/toy/plushie/borgplushie,

View File

@@ -7,6 +7,7 @@
var/icon_closed = "egg"
var/icon_opened = "egg_open"
var/icon_locked = "egg"
closet_appearance = null
open_sound = 'sound/vore/schlorp.ogg'
close_sound = 'sound/vore/schlorp.ogg'
opened = 0

View File

@@ -1,7 +1,7 @@
/obj/structure/largecrate
name = "large crate"
desc = "A hefty wooden crate."
icon = 'icons/obj/storage_vr.dmi' //VOREStation Edit
icon = 'icons/obj/storage.dmi'
icon_state = "densecrate"
density = 1
var/list/starts_with

View File

@@ -423,7 +423,7 @@
return
// If the human is losing too much blood, beep.
if(((H.vessel.get_reagent_amount("blood")/H.species.blood_volume)*100) < BLOOD_VOLUME_SAFE)
if(H.vessel.get_reagent_amount("blood") < H.species.blood_volume*H.species.blood_level_safe)
visible_message("\The [src] beeps loudly.")
var/datum/reagent/B = H.take_blood(beaker,amount)

View File

@@ -317,6 +317,7 @@
name = "tiles"
icon_state = "freezer"
initial_flooring = /decl/flooring/tiling/freezer
temperature = T0C - 5 // VOREStation Edit: Chillier Freezer Tiles on-start
/turf/simulated/floor/lino
name = "lino"

View File

@@ -1468,12 +1468,12 @@ var/datum/announcement/minor/admin_min_announcer = new
if(check_rights(R_ADMIN|R_MOD|R_EVENT))
if (H.paralysis == 0)
H.paralysis = 8000
H.SetParalysis(8000)
msg = "has paralyzed [key_name(H)]."
log_and_message_admins(msg)
else
if(alert(src, "[key_name(H)] is paralyzed, would you like to unparalyze them?",,"Yes","No") == "Yes")
H.paralysis = 0
H.SetParalysis(0)
msg = "has unparalyzed [key_name(H)]."
log_and_message_admins(msg)

View File

@@ -266,6 +266,18 @@ var/list/_client_preferences_by_type
enabled_description = "Enabled"
disabled_description = "Disabled"
/datum/client_preference/status_indicators
description = "Status Indicators"
key = "SHOW_STATUS"
enabled_description = "Show"
disabled_description = "Hide"
/datum/client_preference/status_indicators/toggled(mob/preference_mob, enabled)
. = ..()
if(preference_mob && preference_mob.plane_holder)
var/datum/plane_holder/PH = preference_mob.plane_holder
PH.set_vis(VIS_STATUS, enabled)
/********************
* Staff Preferences *
********************/

View File

@@ -279,3 +279,7 @@
/datum/gear/accessory/cowledvest
display_name = "cowled vest"
path = /obj/item/clothing/accessory/cowledvest
/datum/gear/accessory/asymovercoat
display_name = "orange asymmetrical overcoat"
path = /obj/item/clothing/accessory/asymovercoat

View File

@@ -366,4 +366,20 @@
/datum/gear/head/jingasa
display_name = "jingasa"
path = /obj/item/clothing/head/jingasa
path = /obj/item/clothing/head/jingasa
/datum/gear/head/sunflower_crown
display_name = "sunflower crown"
path = /obj/item/clothing/head/sunflower_crown
/datum/gear/head/lavender_crown
display_name = "lavender crown"
path = /obj/item/clothing/head/lavender_crown
/datum/gear/head/poppy_crown
display_name = "poppy crown"
path = /obj/item/clothing/head/poppy_crown
/datum/gear/head/rose_crown
display_name = "rose crown"
path = /obj/item/clothing/head/rose_crown

View File

@@ -580,4 +580,12 @@
/datum/gear/uniform/yellowswoop
display_name = "yellow swooped dress"
path = /obj/item/clothing/under/dress/yellowswoop
path = /obj/item/clothing/under/dress/yellowswoop
/datum/gear/uniform/greenasym
display_name = "green asymmetrical jumpsuit"
path = /obj/item/clothing/under/greenasym
/datum/gear/uniform/cyberpunkharness
display_name = "cyberpunk strapped harness"
path = /obj/item/clothing/under/cyberpunkharness

View File

@@ -334,6 +334,19 @@
You will have to reload VChat and/or reconnect to the server for these changes to take place. \
VChat message persistence is not guaranteed if you change this again before the start of the next round.")
/client/verb/toggle_status_indicators()
set name = "Toggle Status Indicators"
set category = "Preferences"
set desc = "Enable/Disable seeing status indicators over peoples' heads."
var/pref_path = /datum/client_preference/status_indicators
toggle_preference(pref_path)
SScharacter_setup.queue_preferences_save(prefs)
to_chat(src, "You will now [(is_preference_enabled(/datum/client_preference/status_indicators)) ? "see" : "not see"] status indicators.")
feedback_add_details("admin_verb","TStatusIndicators")
// Not attached to a pref datum because those are strict binary toggles
/client/verb/toggle_examine_mode()

View File

@@ -41,28 +41,49 @@ BLIND // can't see anything
var/mob/M = src.loc
M.update_inv_glasses()
/obj/item/clothing/glasses/proc/can_toggle(mob/living/user)
if(!toggleable)
return FALSE
// Prevent people from just turning their goggles back on.
if(!active && (vision_flags & (SEE_TURFS|SEE_OBJS)))
var/area/A = get_area(src)
if(A.no_spoilers)
return FALSE
return TRUE
/obj/item/clothing/glasses/proc/toggle_active(mob/living/user)
if(active)
active = FALSE
icon_state = off_state
user.update_inv_glasses()
flash_protection = FLASH_PROTECTION_NONE
tint = TINT_NONE
away_planes = enables_planes
enables_planes = null
else
active = TRUE
icon_state = initial(icon_state)
user.update_inv_glasses()
flash_protection = initial(flash_protection)
tint = initial(tint)
enables_planes = away_planes
away_planes = null
user.update_action_buttons()
user.recalculate_vis()
/obj/item/clothing/glasses/attack_self(mob/user)
if(toggleable)
if(active)
active = 0
icon_state = off_state
user.update_inv_glasses()
flash_protection = FLASH_PROTECTION_NONE
tint = TINT_NONE
away_planes = enables_planes
enables_planes = null
to_chat(usr, "You deactivate the optical matrix on the [src].")
if(!can_toggle(user))
to_chat(user, span("warning", "You don't seem to be able to toggle \the [src] here."))
else
active = 1
icon_state = initial(icon_state)
user.update_inv_glasses()
flash_protection = initial(flash_protection)
tint = initial(tint)
enables_planes = away_planes
away_planes = null
to_chat(usr, "You activate the optical matrix on the [src].")
user.update_action_buttons()
user.recalculate_vis()
toggle_active(user)
if(active)
to_chat(user, span("notice", "You activate the optical matrix on the [src]."))
else
to_chat(user, span("notice", "You deactivate the optical matrix on the [src]."))
..()
/obj/item/clothing/glasses/meson

View File

@@ -44,6 +44,18 @@
..()
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"
icon_state = "ertsuit_j"
item_state = "ertsuit_j"
armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 20, bio = 100, rad = 100) //awful armor
slowdown = 0 //light armor means no slowdown
item_flags = NOSLIP //INBUILT NANOGALOSHES
/obj/item/clothing/suit/space/void/responseteam/janitor/Initialize()
..()
helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/janitor //autoinstall the helmet
/obj/item/clothing/suit/space/void/responseteam
sprite_sheets = list(
SPECIES_HUMAN = 'icons/mob/spacesuit_vr.dmi',
@@ -137,6 +149,11 @@
icon_state = "erthelmet_s"
item_state = "erthelmet_s"
/obj/item/clothing/head/helmet/space/void/responseteam/janitor
name = "Mark VII-J Emergency Cleanup Response Helmet"
icon_state = "erthelmet_j"
item_state = "erthelmet_j"
/obj/item/clothing/head/helmet/space/void/responseteam
sprite_sheets = list(
SPECIES_HUMAN = 'icons/mob/head_vr.dmi',

View File

@@ -398,3 +398,8 @@
name = "green asymmetrical jacket"
desc = "Insultingly avant-garde in aqua."
icon_state = "asym_green"
/obj/item/clothing/accessory/asymovercoat
name = "orange asymmetrical overcoat"
desc = "An asymmetrical orange overcoat in a 2560's fashion."
icon_state = "asymovercoat"

View File

@@ -804,6 +804,18 @@ Uniforms and such
icon_state = "rippedpunk"
index = 1
/obj/item/clothing/under/greenasym
name = "green asymmetrical jumpsuit"
desc = "A green futuristic uniform with asymmetrical pants. Trendy!"
icon_state = "greenasym"
index = 1
/obj/item/clothing/under/cyberpunkharness
name = "cyberpunk strapped harness"
desc = "A cyberpunk styled harness and pants. Perfect for your dystopian future."
icon_state = "cyberhell"
index = 1
/*
* swimsuit
*/

View File

@@ -109,29 +109,37 @@
T.clean(src, user) //VOREStation Edit End
/obj/item/weapon/reagent_containers/glass/rag/attack(atom/target as obj|turf|area, mob/user as mob , flag)
if(isliving(target))
if(isliving(target)) //Leaving this as isliving.
var/mob/living/M = target
if(on_fire)
if(on_fire) //Check if rag is on fire, if so igniting them and stopping.
user.visible_message("<span class='danger'>\The [user] hits [target] with [src]!</span>",)
user.do_attack_animation(src)
M.IgniteMob()
else if(reagents.total_volume)
if(user.zone_sel.selecting == O_MOUTH)
user.do_attack_animation(src)
user.visible_message(
"<span class='danger'>\The [user] smothers [target] with [src]!</span>",
"<span class='warning'>You smother [target] with [src]!</span>",
"You hear some struggling and muffled cries of surprise"
)
//it's inhaled, so... maybe CHEM_BLOOD doesn't make a whole lot of sense but it's the best we can do for now
reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_BLOOD)
update_name()
else if(user.zone_sel.selecting == O_MOUTH) //Check player target location, provided the rag is not on fire. Then check if mouth is exposed.
if(ishuman(target)) //Added this since player species process reagents in majority of cases.
var/mob/living/carbon/human/H = target
if(H.head && (H.head.body_parts_covered & FACE)) //Check human head coverage.
to_chat(user, "<span class='warning'>Remove their [H.head] first.</span>")
return
else if(reagents.total_volume) //Final check. If the rag is not on fire and their face is uncovered, smother target.
user.do_attack_animation(src)
user.visible_message(
"<span class='danger'>\The [user] smothers [target] with [src]!</span>",
"<span class='warning'>You smother [target] with [src]!</span>",
"You hear some struggling and muffled cries of surprise"
)
//it's inhaled, so... maybe CHEM_BLOOD doesn't make a whole lot of sense but it's the best we can do for now
reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_BLOOD)
update_name()
else
to_chat(user, "<span class='warning'>You can't smother this creature.</span>")
else
wipe_down(target, user)
return
return ..()
to_chat(user, "<span class='warning'>You can't smother this creature.</span>")
else
wipe_down(target, user)
else
wipe_down(target, user)
return
/obj/item/weapon/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user as mob, proximity)
if(!proximity)

View File

@@ -139,7 +139,7 @@
set category = "Object"
set src in view(1)
to_world("usr is [usr]")
//to_world("usr is [usr]") //why was this a thing? -KK.
display_data(usr)
/obj/item/device/detective_scanner/proc/display_data(var/mob/user)

View File

@@ -168,12 +168,12 @@ mob/living/carbon/proc/handle_hallucinations()
if(71 to 72)
//Fake death
// src.sleeping_willingly = 1
src.sleeping = 20
SetSleeping(20)
hal_crit = 1
hal_screwyhud = 1
spawn(rand(50,100))
// src.sleeping_willingly = 0
src.sleeping = 0
SetSleeping(0)
hal_crit = 0
hal_screwyhud = 0
handling_hal = 0

View File

@@ -157,7 +157,7 @@
. = ..()
if(Adjacent(user))
if(coating)
to_chat(user, "<span class='notice'>It's coated in [coating.name]!</span>")
. += "<span class='notice'>It's coated in [coating.name]!</span>"
if(bitecount==0)
return .
else if (bitecount==1)
@@ -4528,12 +4528,14 @@
filling_color = "#DB0000"
center_of_mass = list("x"=16, "y"=16)
do_coating_prefix = 0
New()
. = ..()
reagents.add_reagent("protein", 6)
reagents.add_reagent("batter", 1.7)
reagents.add_reagent("oil", 1.5)
bitesize = 2
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/sausage/battered/Initialize()
. = ..()
reagents.add_reagent("protein", 6)
reagents.add_reagent("batter", 1.7)
reagents.add_reagent("oil", 1.5)
/obj/item/weapon/reagent_containers/food/snacks/jalapeno_poppers
name = "jalapeno popper"
@@ -4558,10 +4560,11 @@
icon = 'icons/obj/food_syn.dmi'
icon_state = "ratburger"
center_of_mass = list("x"=16, "y"=11)
New()
. = ..()
reagents.add_reagent("protein", 4)
bitesize = 2
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/mouseburger/Initialize()
. = ..()
reagents.add_reagent("protein", 4)
/obj/item/weapon/reagent_containers/food/snacks/chickenkatsu
name = "chicken katsu"
@@ -4637,13 +4640,13 @@
nutriment_amt = 25
nutriment_desc = list("fried pizza" = 25)
center_of_mass = list("x"=16, "y"=11)
bitesize = 2
New()
. = ..()
reagents.add_reagent("batter", 6.5)
coating = reagents.get_reagent("batter")
reagents.add_reagent("oil", 4)
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/crunch/Initialize()
. = ..()
reagents.add_reagent("batter", 6.5)
coating = reagents.get_reagent("batter")
reagents.add_reagent("oil", 4)
/obj/item/weapon/reagent_containers/food/snacks/pizzacrunchslice
name = "pizza crunch"
@@ -6032,4 +6035,16 @@
/obj/item/weapon/reagent_containers/food/snacks/cosmicbrowniesslice/filled/Initialize()
. = ..()
reagents.add_reagent("protein", 1)
reagents.add_reagent("protein", 1)
/obj/item/weapon/reagent_containers/food/snacks/lasagna
name = "lasagna"
desc = "Meaty, tomato-y, and ready to eat-y. Favorite of cats."
icon = 'icons/obj/food.dmi'
icon_state = "lasagna"
nutriment_amt = 5
nutriment_desc = list("tomato" = 4, "meat" = 2)
/obj/item/weapon/reagent_containers/food/snacks/lasagna/Initialize()
..()
reagents.add_reagent("protein", 2) //For meaty things.

View File

@@ -42,20 +42,6 @@
/obj/item/weapon/reagent_containers/food/snacks/slice/sushi/filled/filled
filled = TRUE
/obj/item/weapon/reagent_containers/food/snacks/lasagna
name = "lasagna"
desc = "Meaty, tomato-y, and ready to eat-y. Favorite of cats."
icon = 'icons/obj/food_vr.dmi'
icon_state = "lasagna"
nutriment_amt = 5
nutriment_desc = list("tomato" = 4, "meat" = 2)
/obj/item/weapon/reagent_containers/food/snacks/lasagna/Initialize()
..()
reagents.add_reagent("protein", 2) //For meaty things.
/obj/item/weapon/reagent_containers/food/snacks/goulash
name = "goulash"
desc = "Paprika put to good use, finally, in a soup of meat and vegetables."

View File

@@ -53,12 +53,10 @@
if (!available_recipes)
available_recipes = new
for (var/type in subtypesof(/datum/recipe))
var/datum/recipe/test = new type
if ((appliancetype & test.appliance))
available_recipes += test
else
qdel(test)
for(var/type in subtypesof(/datum/recipe))
var/datum/recipe/test = type
if((appliancetype & initial(test.appliance)))
available_recipes += new test
/obj/machinery/appliance/Destroy()
for (var/a in cooking_objs)
@@ -79,7 +77,7 @@
for (var/a in cooking_objs)
var/datum/cooking_item/CI = a
string += "-\a [CI.container.label(null, CI.combine_target)], [report_progress(CI)]</br>"
to_chat(user, string)
return string
else
to_chat(user, "<span class='notice>'It is empty.</span>")
@@ -125,14 +123,14 @@
return
if (!user.IsAdvancedToolUser())
to_chat(user, "You lack the dexterity to do that!")
to_chat(user, "<span class='warning'>You lack the dexterity to do that!</span>")
return
if (user.stat || user.restrained() || user.incapacitated())
return
if (!Adjacent(user) && !issilicon(user))
to_chat(user, "You can't reach [src] from here.")
to_chat(user, "<span class='warning'>You can't reach [src] from here!</span>")
return
if (stat & POWEROFF)//Its turned off
@@ -234,10 +232,10 @@
//This function is overridden by cookers that do stuff with containers
/obj/machinery/appliance/proc/has_space(var/obj/item/I)
if (cooking_objs.len >= max_contents)
if(cooking_objs.len >= max_contents)
return FALSE
else return TRUE
return TRUE
/obj/machinery/appliance/attackby(var/obj/item/I, var/mob/user)
if(!cook_type || (stat & (BROKEN)))
@@ -246,12 +244,9 @@
var/result = can_insert(I, user)
if(!result)
if(default_deconstruction_screwdriver(user, I))
return
else if(default_part_replacement(user, I))
return
else
return
if(!(default_deconstruction_screwdriver(user, I)))
default_part_replacement(user, I)
return
if(result == 2)
var/obj/item/weapon/grab/G = I
@@ -572,17 +567,17 @@
var/datum/cooking_item/CI = menuoptions[selection]
eject(CI, user)
update_icon()
return 1
return 0
return TRUE
return FALSE
/obj/machinery/appliance/proc/can_remove_items(var/mob/user)
if (!Adjacent(user))
return 0
return FALSE
if (isanimal(user))
return 0
return FALSE
return 1
return TRUE
/obj/machinery/appliance/proc/eject(var/datum/cooking_item/CI, var/mob/user = null)
var/obj/item/thing

View File

@@ -19,12 +19,12 @@
if(.) //no need to duplicate adjacency check
if(!stat)
if (temperature < min_temp)
to_chat(user, "<span class='warning'>\The [src] is still heating up and is too cold to cook anything yet.</span>")
. += "<span class='warning'>\The [src] is still heating up and is too cold to cook anything yet.</span>"
else
to_chat(user, "<span class='notice'>It is running at [round(get_efficiency(), 0.1)]% efficiency!</span>")
to_chat(user, "Temperature: [round(temperature - T0C, 0.1)]C / [round(optimal_temp - T0C, 0.1)]C")
. += "<span class='notice'>It is running at [round(get_efficiency(), 0.1)]% efficiency!</span>"
. += "Temperature: [round(temperature - T0C, 0.1)]C / [round(optimal_temp - T0C, 0.1)]C"
else
to_chat(user, "<span class='warning'>It is switched off.</span>")
. += "<span class='warning'>It is switched off.</span>"
/obj/machinery/appliance/cooker/list_contents(var/mob/user)
if (cooking_objs.len)

View File

@@ -17,7 +17,7 @@ fundamental differences
/obj/machinery/appliance/mixer/examine(var/mob/user)
. = ..()
if(Adjacent(user))
to_chat(user, "<span class='notice'>It is currently set to make a [selected_option]</span>")
. += "<span class='notice'>It is currently set to make a [selected_option]</span>"
/obj/machinery/appliance/mixer/Initialize()
. = ..()
@@ -27,7 +27,7 @@ fundamental differences
//Mixers cannot-not do combining mode. So the default option is removed from this. A combine target must be chosen
/obj/machinery/appliance/mixer/choose_output()
set src in oview(1)
set src in view(1)
set name = "Choose output"
set category = "Object"
@@ -91,7 +91,7 @@ fundamental differences
/obj/machinery/appliance/mixer/toggle_power()
set src in view()
set src in view(1)
set name = "Toggle Power"
set category = "Object"

View File

@@ -14,6 +14,8 @@
active_power_usage = 12 KILOWATTS
heating_power = 12000
light_y = 15
min_temp = 140 + T0C // Same as above, increasing this to just under 2x to make the % increase on efficiency not quite so painful as it would be at 80.
optimal_temp = 400 + T0C // Increasing this to be 2x Oven to allow for a much higher/realistic frying temperatures. Doesn't really do anything but make heating the fryer take a bit longer.
optimal_power = 0.95 // .35 higher than the default to give fryers faster cooking speed.
@@ -55,6 +57,19 @@
if(Adjacent(user))
to_chat(user, "Oil Level: [oil.total_volume]/[optimal_oil]")
/obj/machinery/appliance/cooker/fryer/update_icon() // We add our own version of the proc to use the special fryer double-lights.
cut_overlays()
var/image/light
if(use_power == 1 && !stat)
light = image(icon, "fryer_light_idle")
else if(use_power == 2 && !stat)
light = image(icon, "fryer_light_preheating")
else
light = image(icon, "fryer_light_off")
light.pixel_x = light_x
light.pixel_y = light_y
add_overlay(light)
/obj/machinery/appliance/cooker/fryer/heat_up()
if (..())
//Set temperature of oil reagent

View File

@@ -17,7 +17,8 @@
//uses ~30% power to stay warm
optimal_power = 0.8 // Oven cooks .2 faster than the default speed.
light_x = 2
light_x = 3
light_y = 4
max_contents = 5
container_type = /obj/item/weapon/reagent_containers/cooking_container/oven

View File

@@ -71,31 +71,31 @@
// This is a bitfield, more than one type can be used
// Grill is presently unused and not listed
/datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents)
/datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents, var/exact = FALSE)
if(!reagents || !reagents.len)
return 1
return TRUE
if(!avail_reagents)
return 0
return FALSE
. = 1
. = TRUE
for(var/r_r in reagents)
var/aval_r_amnt = avail_reagents.get_reagent_amount(r_r)
if(aval_r_amnt - reagents[r_r] >= 0)
if(aval_r_amnt>reagents[r_r])
. = 0
if(aval_r_amnt>(reagents[r_r] && exact))
. = FALSE
else
return -1
return FALSE
if((reagents?(reagents.len):(0)) < avail_reagents.reagent_list.len)
return 0
return FALSE
return .
/datum/recipe/proc/check_fruit(var/obj/container)
/datum/recipe/proc/check_fruit(var/obj/container, var/exact = FALSE)
if (!fruit || !fruit.len)
return 1
return TRUE
. = 1
. = TRUE
if(fruit && fruit.len)
var/list/checklist = list()
// You should trust Copy().
@@ -107,18 +107,18 @@
checklist[G.seed.kitchen_tag]--
for(var/ktag in checklist)
if(!isnull(checklist[ktag]))
if(checklist[ktag] < 0)
. = 0
if(checklist[ktag] < 0 && exact)
. = FALSE
else if(checklist[ktag] > 0)
. = -1
. = FALSE
break
return .
/datum/recipe/proc/check_items(var/obj/container as obj)
/datum/recipe/proc/check_items(var/obj/container as obj, var/exact = FALSE)
if(!items || !items.len)
return 1
return TRUE
. = 1
. = TRUE
if(items && items.len)
var/list/checklist = list()
checklist = items.Copy() // You should really trust Copy
@@ -127,50 +127,50 @@
for(var/obj/O in ((machine.contents - machine.component_parts) - machine.circuit))
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown))
continue // Fruit is handled in check_fruit().
var/found = 0
var/found = FALSE
for(var/i = 1; i < checklist.len+1; i++)
var/item_type = checklist[i]
if (istype(O,item_type))
checklist.Cut(i, i+1)
found = 1
found = TRUE
break
if(!found)
. = 0
if(!found && exact)
return FALSE
else
for(var/obj/O in container.contents)
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown))
continue // Fruit is handled in check_fruit().
var/found = 0
var/found = FALSE
for(var/i = 1; i < checklist.len+1; i++)
var/item_type = checklist[i]
if (istype(O,item_type))
if(check_coating(O))
checklist.Cut(i, i+1)
found = 1
found = TRUE
break
if (!found)
. = 0
if (!found && exact)
return FALSE
if(checklist.len)
. = -1
return FALSE
return .
//This is called on individual items within the container.
/datum/recipe/proc/check_coating(var/obj/O)
/datum/recipe/proc/check_coating(var/obj/O, var/exact = FALSE)
if(!istype(O,/obj/item/weapon/reagent_containers/food/snacks))
return 1//Only snacks can be battered
return TRUE //Only snacks can be battered
if (coating == -1)
return 1 //-1 value doesnt care
return TRUE //-1 value doesnt care
var/obj/item/weapon/reagent_containers/food/snacks/S = O
if (!S.coating)
if (!coating)
return 1
return 0
return TRUE
return FALSE
else if (S.coating.type == coating)
return 1
return TRUE
return 0
return FALSE
//general version
/datum/recipe/proc/make(var/obj/container as obj)
@@ -308,7 +308,7 @@
/proc/select_recipe(var/list/datum/recipe/available_recipes, var/obj/obj as obj, var/exact)
var/list/datum/recipe/possible_recipes = list()
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))
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)

View File

@@ -6,6 +6,7 @@
result = /obj/item/weapon/reagent_containers/food/snacks/fries
/datum/recipe/cheesyfries
appliance = FRYER
items = list(
/obj/item/weapon/reagent_containers/food/snacks/fries,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
@@ -100,13 +101,11 @@
)
result = /obj/item/weapon/reagent_containers/food/snacks/donut/poisonberry
/datum/recipe/jellydonut/slime
appliance = FRYER
/datum/recipe/jellydonut/slime // Subtypes of jellydonut, appliance inheritance applies.
reagents = list("slimejelly" = 5, "sugar" = 5)
result = /obj/item/weapon/reagent_containers/food/snacks/donut/slimejelly
/datum/recipe/jellydonut/cherry
appliance = FRYER
/datum/recipe/jellydonut/cherry // Subtypes of jellydonut, appliance inheritance applies.
reagents = list("cherryjelly" = 5, "sugar" = 5)
result = /obj/item/weapon/reagent_containers/food/snacks/donut/cherryjelly
@@ -177,4 +176,4 @@
/obj/item/weapon/reagent_containers/food/snacks/meat,
/obj/item/weapon/reagent_containers/food/snacks/meat
)
result = /obj/item/weapon/storage/box/wings //This is kinda like the donut box.
result = /obj/item/weapon/storage/box/wings //This is kinda like the donut box.

View File

@@ -208,10 +208,11 @@ I said no!
/datum/recipe/amanitajelly
reagents = list("water" = 5, "vodka" = 5, "amatoxin" = 5)
result = /obj/item/weapon/reagent_containers/food/snacks/amanitajelly
make_food(var/obj/container as obj)
. = ..(container)
for(var/obj/item/weapon/reagent_containers/food/snacks/amanitajelly/being_cooked in .)
being_cooked.reagents.del_reagent("amatoxin")
/datum/recipe/amanitajelly/make_food(var/obj/container as obj)
. = ..(container)
for(var/obj/item/weapon/reagent_containers/food/snacks/amanitajelly/being_cooked in .)
being_cooked.reagents.del_reagent("amatoxin")
/datum/recipe/meatballsoup
fruit = list("carrot" = 1, "potato" = 1)
@@ -531,11 +532,11 @@ I said no!
fruit = list("potato" = 1, "ambrosia" = 3)
items = list(/obj/item/weapon/reagent_containers/food/snacks/meatball)
result = /obj/item/weapon/reagent_containers/food/snacks/validsalad
make_food(var/obj/container as obj)
. = ..(container)
for (var/obj/item/weapon/reagent_containers/food/snacks/validsalad/being_cooked in .)
being_cooked.reagents.del_reagent("toxin")
/datum/recipe/validsalad/make_food(var/obj/container as obj)
. = ..(container)
for (var/obj/item/weapon/reagent_containers/food/snacks/validsalad/being_cooked in .)
being_cooked.reagents.del_reagent("toxin")
/datum/recipe/stuffing
reagents = list("water" = 5, "sodiumchloride" = 1, "blackpepper" = 1)
@@ -1028,7 +1029,6 @@ I said no!
)
result = /obj/item/weapon/reagent_containers/food/snacks/sashimi
/datum/recipe/nugget
reagents = list("flour" = 5)
items = list(

View File

@@ -83,6 +83,7 @@
result = /obj/item/weapon/reagent_containers/food/snacks/flatbread
/datum/recipe/tortilla
appliance = OVEN
reagents = list("flour" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough

View File

@@ -138,6 +138,7 @@
recipes += new/datum/stack_recipe("water-cooler", /obj/structure/reagent_dispensers/water_cooler, 4, time = 10, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("lampshade", /obj/item/weapon/lampshade, 1, time = 1, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("plastic net", /obj/item/weapon/material/fishing_net, 25, time = 1 MINUTE, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("plastic fishtank", /obj/item/glass_jar/fish/plastic, 2, time = 30 SECONDS)
/material/wood/generate_recipes()
..()

View File

@@ -20,7 +20,10 @@
var/light_intensity = null // Ditto. Not implemented yet.
var/mob_overlay_state = null // Icon_state for an overlay to apply to a (human) mob while this exists. This is actually implemented.
var/client_color = null // If set, the client will have the world be shown in this color, from their perspective.
var/wire_colors_replace = null // If set, the client will have wires replaced by the given replacement list. For colorblindness.
var/wire_colors_replace = null // If set, the client will have wires replaced by the given replacement list. For colorblindness. //VOREStation Add
var/list/filter_parameters = null // If set, will add a filter to the holder with the parameters in this var. Must be a list.
var/filter_priority = 1 // Used to make filters be applied in a specific order, if that is important.
var/filter_instance = null // Instance of a filter created with the `filter_parameters` list. This exists to make `animate()` calls easier. Don't set manually.
// Now for all the different effects.
// Percentage modifiers are expressed as a multipler. (e.g. +25% damage should be written as 1.25)
@@ -83,6 +86,8 @@
holder.update_transform()
if(client_color)
holder.update_client_color()
if(LAZYLEN(filter_parameters))
holder.remove_filter(REF(src))
qdel(src)
// Override this for special effects when it gets added to the mob.
@@ -151,6 +156,9 @@
update_transform()
if(mod.client_color)
update_client_color()
if(LAZYLEN(mod.filter_parameters))
add_filter(REF(mod), mod.filter_priority, mod.filter_parameters)
mod.filter_instance = get_filter(REF(mod))
return mod

View File

@@ -388,3 +388,13 @@ the artifact triggers the rage.
if(holder.stat != DEAD)
holder.visible_message("<span class='alien'>\The [holder] collapses, the life draining from their body.</span>")
holder.death()
/datum/modifier/outline_test
name = "Outline Test"
desc = "This only exists to prove filter effects work and gives an example of how to animate() the resulting filter object."
filter_parameters = list(type = "outline", size = 1, color = "#FFFFFF", flags = OUTLINE_SHARP)
/datum/modifier/outline_test/tick()
animate(filter_instance, size = 3, time = 0.25 SECONDS)
animate(size = 1, 0.25 SECONDS)

View File

@@ -68,9 +68,9 @@
if(health <= 0)
death()
return
weakened = 0
stunned = 0
paralysis = 0
SetWeakened(0)
SetStunned(0)
SetParalysis(0)
if(on && !client && !busy)
spawn(0)

View File

@@ -59,7 +59,7 @@
adjustHalLoss(-3)
if (mind)
if(mind.active && client != null)
sleeping = max(sleeping-1, 0)
AdjustSleeping(-1)
blinded = 1
set_stat(UNCONSCIOUS)
else if(resting)

View File

@@ -1,3 +1,3 @@
/mob/living/carbon/brain/Login()
..()
sleeping = 0
SetSleeping(0)

View File

@@ -136,7 +136,7 @@
to_chat(src, "<span class='danger'>Oh god, everything's spinning!</span>")
Confuse(max(0,confuse_dur))
if(species.emp_sensitivity & EMP_WEAKEN)
if(weaken_dur >= 1)
if(weaken_dur >= 1)
to_chat(src, "<span class='danger'>Your limbs go slack!</span>")
Weaken(max(0,weaken_dur))
//physical damage block, deals (minor-4) 5-15, 10-20, 15-25, 20-30 (extreme-1) of *each* type
@@ -287,7 +287,7 @@
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [T.him] up!</span>", \
"<span class='notice'>You shake [src], but [T.he] [T.does] not respond... Maybe [T.he] [T.has] S.S.D?</span>")
else if(lying || src.sleeping)
src.sleeping = max(0,src.sleeping-5)
AdjustSleeping(-5)
if(src.sleeping == 0)
src.resting = 0
if(H) H.in_stasis = 0 //VOREStation Add - Just In Case
@@ -403,7 +403,7 @@
to_chat(usr, "<font color='red'>You are already sleeping</font>")
return
if(alert(src,"You sure you want to sleep for a while?","Sleep","Yes","No") == "Yes")
usr.sleeping = 20 //Short nap
usr.AdjustSleeping(20)
/mob/living/carbon/Bump(atom/A)
if(now_pushing)

View File

@@ -240,7 +240,7 @@
message = "faints."
if(sleeping)
return //Can't faint while asleep
sleeping += 10 //Short-short nap
Sleeping(10)
m_type = 1
if("cough", "coughs")

View File

@@ -1676,8 +1676,8 @@
if(species?.flags & NO_BLOOD)
bloodtrail = 0
else
var/blood_volume = round((vessel.get_reagent_amount("blood")/species.blood_volume)*100)
if(blood_volume < BLOOD_VOLUME_SURVIVE)
var/blood_volume = vessel.get_reagent_amount("blood")
if(blood_volume < species?.blood_volume*species?.blood_level_fatal)
bloodtrail = 0 //Most of it's gone already, just leave it be
else
vessel.remove_reagent("blood", 1)
@@ -1687,6 +1687,26 @@
T.add_blood(src)
. = ..()
// Tries to turn off item-based things that let you see through walls, like mesons.
// Certain stuff like genetic xray vision is allowed to be kept on.
/mob/living/carbon/human/disable_spoiler_vision()
// Glasses.
if(istype(glasses, /obj/item/clothing/glasses))
var/obj/item/clothing/glasses/goggles = glasses
if(goggles.active && (goggles.vision_flags & (SEE_TURFS|SEE_OBJS)))
goggles.toggle_active(src)
to_chat(src, span("warning", "Your [goggles.name] have suddenly turned off!"))
// RIGs.
var/obj/item/weapon/rig/rig = get_rig()
if(istype(rig) && rig.visor?.active && rig.visor.vision?.glasses)
var/obj/item/clothing/glasses/rig_goggles = rig.visor.vision.glasses
if(rig_goggles.vision_flags & (SEE_TURFS|SEE_OBJS))
rig.visor.deactivate()
to_chat(src, span("warning", "\The [rig]'s visor has shuddenly deactivated!"))
..()
/mob/living/carbon/human/reduce_cuff_time()
if(istype(gloves, /obj/item/clothing/gloves/gauntlets/rig))
return 2

View File

@@ -1103,7 +1103,7 @@
drowsyness = max(0, drowsyness - 1)
eye_blurry = max(2, eye_blurry)
if (prob(5))
sleeping += 1
Sleeping(1)
Paralyse(5)
// If you're dirty, your gloves will become dirty, too.
@@ -1258,7 +1258,14 @@
if(blinded)
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
throw_alert("blind", /obj/screen/alert/blind)
else
clear_fullscreens()
clear_alert("blind")
if(blinded)
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
else if(!machine)
clear_fullscreens()
clear_alert("blind")
@@ -1321,6 +1328,11 @@
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : see_invisible_default
// Do this early so certain stuff gets turned off before vision is assigned.
var/area/A = get_area(src)
if(A?.no_spoilers)
disable_spoiler_vision()
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
@@ -1591,7 +1603,7 @@
if(Pump)
temp += Pump.standard_pulse_level - PULSE_NORM
if(round(vessel.get_reagent_amount("blood")) <= BLOOD_VOLUME_BAD) //how much blood do we have
if(round(vessel.get_reagent_amount("blood")) <= species.blood_volume*species.blood_level_danger) //how much blood do we have
temp = temp + 3 //not enough :(
if(status_flags & FAKEDEATH)

View File

@@ -1,3 +1,4 @@
/datum/species/vox
default_language = LANGUAGE_GALCOM
secondary_langs = list(LANGUAGE_VOX)
speech_sounds = list() // Remove obnoxious noises on every single 'say'. Should really only be a thing for event-exclusive species like benos.

View File

@@ -43,6 +43,10 @@
var/short_sighted // Permanent weldervision.
var/blood_volume = 560 // Initial blood volume.
var/bloodloss_rate = 1 // Multiplier for how fast a species bleeds out. Higher = Faster
var/blood_level_safe = 0.85 //"Safe" blood level; above this, you're OK
var/blood_level_warning = 0.75 //"Warning" blood level; above this, you're a bit woozy and will have low-level oxydamage (no more than 20, or 15 with inap)
var/blood_level_danger = 0.6 //"Danger" blood level; above this, you'll rapidly take up to 50 oxyloss, and it will then steadily accumulate at a lower rate
var/blood_level_fatal = 0.4 //"Fatal" blood level; below this, you take extremely high oxydamage
var/hunger_factor = 0.05 // Multiplier for hunger.
var/active_regen_mult = 1 // Multiplier for 'Regenerate' power speed, in human_powers.dm

View File

@@ -93,6 +93,8 @@
//Set up a mob
H.species = new_copy
H.maxHealth = new_copy.total_health
H.hunger_rate = new_copy.hunger_factor
if(new_copy.holder_type)
H.holder_type = new_copy.holder_type

View File

@@ -298,6 +298,12 @@
return
..()
var/global/list/disallowed_protean_accessories = list(
/obj/item/clothing/accessory/holster,
/obj/item/clothing/accessory/storage,
/obj/item/clothing/accessory/armor
)
// Helpers - Unsafe, WILL perform change.
/mob/living/carbon/human/proc/nano_intoblob()
var/panel_was_up = FALSE
@@ -343,7 +349,8 @@
var/obj/item/clothing/uniform = w_uniform
if(LAZYLEN(uniform.accessories))
for(var/obj/item/clothing/accessory/A in uniform.accessories)
uniform.remove_accessory(null,A) //First param is user, but adds fingerprints and messages
if(is_type_in_list(A, disallowed_protean_accessories))
uniform.remove_accessory(null,A) //First param is user, but adds fingerprints and messages
//Size update
blob.transform = matrix()*size_multiplier

View File

@@ -68,16 +68,16 @@
/* YW Commented out will be moved to Positive/Negative for map balance
/datum/trait/coldadapt
name = "Cold-Adapted"
desc = "You are able to withstand much colder temperatures than other species, and can even be comfortable in extremely cold environments. You are also more vulnerable to hot environments as a consequence of these adaptations."
desc = "You are able to withstand much colder temperatures than other species, and can even be comfortable in extremely cold environments. You are also more vulnerable to hot environments, and have a lower body temperature as a consequence of these adaptations."
cost = 0
var_changes = list("cold_level_1" = 200, "cold_level_2" = 150, "cold_level_3" = 90, "breath_cold_level_1" = 180, "breath_cold_level_2" = 100, "breath_cold_level_3" = 60, "cold_discomfort_level" = 210, "heat_level_1" = 305, "heat_level_2" = 360, "heat_level_3" = 700, "breath_heat_level_1" = 345, "breath_heat_level_2" = 380, "breath_heat_level_3" = 780, "heat_discomfort_level" = 295)
var_changes = list("cold_level_1" = 200, "cold_level_2" = 150, "cold_level_3" = 90, "breath_cold_level_1" = 180, "breath_cold_level_2" = 100, "breath_cold_level_3" = 60, "cold_discomfort_level" = 210, "heat_level_1" = 305, "heat_level_2" = 360, "heat_level_3" = 700, "breath_heat_level_1" = 345, "breath_heat_level_2" = 380, "breath_heat_level_3" = 780, "heat_discomfort_level" = 295, "body_temperature" = 290)
excludes = list(/datum/trait/hotadapt)
/datum/trait/hotadapt
name = "Heat-Adapted"
desc = "You are able to withstand much hotter temperatures than other species, and can even be comfortable in extremely hot environments. You are also more vulnerable to cold environments as a consequence of these adaptations."
desc = "You are able to withstand much hotter temperatures than other species, and can even be comfortable in extremely hot environments. You are also more vulnerable to cold environments, and have a higher body temperature as a consequence of these adaptations."
cost = 0
var_changes = list("heat_level_1" = 420, "heat_level_2" = 460, "heat_level_3" = 1100, "breath_heat_level_1" = 440, "breath_heat_level_2" = 510, "breath_heat_level_3" = 1500, "heat_discomfort_level" = 390, "cold_level_1" = 280, "cold_level_2" = 220, "cold_level_3" = 140, "breath_cold_level_1" = 260, "breath_cold_level_2" = 240, "breath_cold_level_3" = 120, "cold_discomfort_level" = 280)
var_changes = list("heat_level_1" = 420, "heat_level_2" = 460, "heat_level_3" = 1100, "breath_heat_level_1" = 440, "breath_heat_level_2" = 510, "breath_heat_level_3" = 1500, "heat_discomfort_level" = 390, "cold_level_1" = 280, "cold_level_2" = 220, "cold_level_3" = 140, "breath_cold_level_1" = 260, "breath_cold_level_2" = 240, "breath_cold_level_3" = 120, "cold_discomfort_level" = 280, "body_temperature" = 330)
excludes = list(/datum/trait/coldadapt)
YW change end */

View File

@@ -45,7 +45,10 @@
//Check if we're on fire
handle_fire()
// Handle re-running ambience to mobs if they've remained in an area.
handle_ambience()
//stuff in the stomach
//handle_stomach() //VOREStation Code
@@ -89,6 +92,12 @@
/mob/living/proc/handle_stomach()
return
/mob/living/proc/handle_ambience() // If you're in an ambient area and have not moved out of it for x time, we're going to play ambience again to you, to help break up the silence.
if(world.time >= (lastareachange + 30 SECONDS)) // Every 30 seconds, we're going to run a 35% chance to play ambience.
var/area/A = get_area(src)
if(A)
A.play_ambience(src)
/mob/living/proc/update_pulling()
if(pulling)
if(incapacitated())
@@ -126,7 +135,7 @@
/mob/living/proc/handle_weakened()
if(weakened)
weakened = max(weakened-1,0)
AdjustWeakened(-1)
throw_alert("weakened", /obj/screen/alert/weakened)
else
clear_alert("weakened")
@@ -181,7 +190,7 @@
throw_alert("blind", /obj/screen/alert/blind)
else
clear_alert("blind")
if(eye_blurry) //blurry eyes heal slowly
eye_blurry = max(eye_blurry-1, 0)

View File

@@ -491,6 +491,15 @@ default behaviour is:
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(stunned > 0)
add_status_indicator("stunned")
/mob/living/SetStunned(amount)
..()
if(stunned <= 0)
remove_status_indicator("stunned")
else
add_status_indicator("stunned")
/mob/living/AdjustStunned(amount)
if(amount > 0)
@@ -498,12 +507,25 @@ default behaviour is:
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(stunned <= 0)
remove_status_indicator("stunned")
else
add_status_indicator("stunned")
/mob/living/Weaken(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(weakened > 0)
add_status_indicator("weakened")
/mob/living/SetWeakened(amount)
..()
if(weakened <= 0)
remove_status_indicator("weakened")
else
add_status_indicator("weakened")
/mob/living/AdjustWeakened(amount)
if(amount > 0)
@@ -511,12 +533,25 @@ default behaviour is:
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(weakened <= 0)
remove_status_indicator("weakened")
else
add_status_indicator("weakened")
/mob/living/Paralyse(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(paralysis > 0)
add_status_indicator("paralysis")
/mob/living/SetParalysis(amount)
..()
if(paralysis <= 0)
remove_status_indicator("paralysis")
else
add_status_indicator("paralysis")
/mob/living/AdjustParalysis(amount)
if(amount > 0)
@@ -524,12 +559,25 @@ default behaviour is:
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(paralysis <= 0)
remove_status_indicator("paralysis")
else
add_status_indicator("paralysis")
/mob/living/Sleeping(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(sleeping > 0)
add_status_indicator("sleeping")
/mob/living/SetSleeping(amount)
..()
if(sleeping <= 0)
remove_status_indicator("sleeping")
else
add_status_indicator("sleeping")
/mob/living/AdjustSleeping(amount)
if(amount > 0)
@@ -537,12 +585,25 @@ default behaviour is:
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(sleeping <= 0)
remove_status_indicator("sleeping")
else
add_status_indicator("sleeping")
/mob/living/Confuse(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(confused > 0)
add_status_indicator("confused")
/mob/living/SetConfused(amount)
..()
if(confused <= 0)
remove_status_indicator("confused")
else
add_status_indicator("confused")
/mob/living/AdjustConfused(amount)
if(amount > 0)
@@ -550,12 +611,25 @@ default behaviour is:
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(confused <= 0)
remove_status_indicator("confused")
else
add_status_indicator("confused")
/mob/living/Blind(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(eye_blind > 0)
add_status_indicator("blinded")
/mob/living/SetBlinded(amount)
..()
if(eye_blind <= 0)
remove_status_indicator("blinded")
else
add_status_indicator("blinded")
/mob/living/AdjustBlinded(amount)
if(amount > 0)
@@ -563,6 +637,10 @@ default behaviour is:
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
if(eye_blind <= 0)
remove_status_indicator("blinded")
else
add_status_indicator("blinded")
// ++++ROCKDTBEN++++ MOB PROCS //END
@@ -827,10 +905,10 @@ default behaviour is:
if(pulling) // we were pulling a thing and didn't lose it during our move.
var/pull_dir = get_dir(src, pulling)
if(pulling.anchored || !isturf(pulling.loc))
stop_pulling()
else if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir))) // puller and pullee more than one tile away or in diagonal position
// If it is too far away or across z-levels from old location, stop pulling.
if(get_dist(pulling.loc, oldloc) > 1 || pulling.loc.z != oldloc?.z)
@@ -846,7 +924,7 @@ default behaviour is:
stop_pulling()
if(!isturf(loc))
return
return
else if(lastarea?.has_gravity == 0)
inertial_drift()
//VOREStation Edit Start
@@ -863,7 +941,7 @@ default behaviour is:
if(Process_Spacemove(1))
inertia_dir = 0
return
var/locthen = loc
spawn(5)
if(!anchored && !pulledby && loc == locthen)
@@ -1145,22 +1223,29 @@ default behaviour is:
/mob/living/proc/is_sentient()
return TRUE
/mob/living/get_icon_scale_x()
. = ..()
for(var/datum/modifier/M in modifiers)
if(!isnull(M.icon_scale_x_percent))
. *= M.icon_scale_x_percent
/mob/living/get_icon_scale_y()
. = ..()
for(var/datum/modifier/M in modifiers)
if(!isnull(M.icon_scale_y_percent))
. *= M.icon_scale_y_percent
/mob/living/update_transform()
// First, get the correct size.
var/desired_scale_x = size_multiplier //VOREStation edit
var/desired_scale_y = size_multiplier //VOREStation edit
for(var/datum/modifier/M in modifiers)
if(!isnull(M.icon_scale_x_percent))
desired_scale_x *= M.icon_scale_x_percent
if(!isnull(M.icon_scale_y_percent))
desired_scale_y *= M.icon_scale_y_percent
// Now for the regular stuff.
var/matrix/M = matrix()
M.Scale(desired_scale_x, desired_scale_y)
M.Translate(0, (vis_height/2)*(desired_scale_y-1)) //VOREStation edit
src.transform = M //VOREStation edit
handle_status_indicators()
// This handles setting the client's color variable, which makes everything look a specific color.
// This proc is here so it can be called without needing to check if the client exists, or if the client relogs.
@@ -1350,3 +1435,8 @@ default behaviour is:
clear_alert("weightless")
else
throw_alert("weightless", /obj/screen/alert/weightless)
// Tries to turn off things that let you see through walls, like mesons.
// Each mob does vision a bit differently so this is just for inheritence and also so overrided procs can make the vision apply instantly if they call `..()`.
/mob/living/proc/disable_spoiler_vision()
handle_vision()

View File

@@ -1,3 +1,3 @@
/mob/living/silicon/Login()
sleeping = 0
SetSleeping(0)
..()

View File

@@ -11,7 +11,7 @@ GLOBAL_LIST_EMPTY(robot_custom_icons)
GLOB.robot_custom_icons = list()
for(var/line in lines)
//split entry into ckey and real_name
var/list/split_idx = splittext(line, "-") //this works if ckeys and borg names cannot contain dashes, and splittext starts from the beginning ~Mech
var/list/split_idx = splittext(line, "|") //this was set to a - before, even though a good 30% of the borgs I see have a - in their name, set it to | instead
if(!split_idx || !split_idx.len)
continue //bad entry
@@ -32,3 +32,9 @@ GLOBAL_LIST_EMPTY(robot_custom_icons)
icon = CUSTOM_ITEM_SYNTH
if(icon_state == "robot")
icon_state = "[ckey]-[sprite_name]-Standard" //Compliant with robot.dm line 236 ~Mech
// To summarize, if you want to add a whitelisted borg sprite, you have to
// 1. Add ckey and character name to config/custom_sprites, separated by a |
// 2. Add your custom sprite to custom_synthetic.dmi under icon/mob/custom_synthetic.dmi
// 3. Name the sprite, and all of its components, as ckey-charname-module
// Note that, due to the last couple lines of code, your sprite may appear invisible until you select a module.
// You can fix this by adding a 'standard' configuration, or you could probably just ignore it if you're lazy.

View File

@@ -213,6 +213,7 @@
user.visible_message("[user] begins to lap up water from [target.name].", "<span class='notice'>You begin to lap up water from [target.name].</span>")
if(do_after (user, 50))
water.add_charge(50)
to_chat(src, "You refill some of your water reserves.")
else if(water.energy < 5)
to_chat(user, "<span class='notice'>Your mouth feels dry. You should drink up some water .</span>")
return

View File

@@ -39,6 +39,7 @@
var/digest_brute = 2
var/digest_burn = 3
var/recycles = FALSE
var/medsensor = TRUE //Does belly sprite come with patient ok/dead light?
/obj/item/device/dogborg/sleeper/New()
..()
@@ -426,21 +427,25 @@
//Well, we HAD one, what happened to them?
if(patient in contents)
if(patient_laststat != patient.stat)
if(cleaning)
hound.sleeper_r = TRUE
hound.sleeper_g = FALSE
patient_laststat = patient.stat
else if(patient.stat & DEAD)
hound.sleeper_r = TRUE
hound.sleeper_g = FALSE
patient_laststat = patient.stat
else
hound.sleeper_r = FALSE
hound.sleeper_g = TRUE
patient_laststat = patient.stat
//Update icon
hound.updateicon()
if(medsensor)
if(patient_laststat != patient.stat)
if(cleaning)
hound.sleeper_r = TRUE
hound.sleeper_g = FALSE
patient_laststat = patient.stat
else if(patient.stat & DEAD)
hound.sleeper_r = TRUE
hound.sleeper_g = FALSE
patient_laststat = patient.stat
else
hound.sleeper_r = FALSE
hound.sleeper_g = TRUE
patient_laststat = patient.stat
else
hound.sleeper_r = TRUE
patient_laststat = patient.stat
//Update icon
hound.updateicon()
//Return original patient
return(patient)
@@ -448,17 +453,21 @@
else
for(var/mob/living/carbon/human/C in contents)
patient = C
if(cleaning)
hound.sleeper_r = TRUE
hound.sleeper_g = FALSE
patient_laststat = patient.stat
else if(patient.stat & DEAD)
hound.sleeper_r = TRUE
hound.sleeper_g = FALSE
patient_laststat = patient.stat
if(medsensor)
if(cleaning)
hound.sleeper_r = TRUE
hound.sleeper_g = FALSE
patient_laststat = patient.stat
else if(patient.stat & DEAD)
hound.sleeper_r = TRUE
hound.sleeper_g = FALSE
patient_laststat = patient.stat
else
hound.sleeper_r = FALSE
hound.sleeper_g = TRUE
patient_laststat = patient.stat
else
hound.sleeper_r = FALSE
hound.sleeper_g = TRUE
hound.sleeper_r = TRUE
patient_laststat = patient.stat
//Update icon and return new patient
hound.updateicon()
@@ -659,6 +668,7 @@
desc = "Equipment for a K9 unit. A mounted portable-brig that holds criminals."
icon_state = "sleeperb"
injection_chems = null //So they don't have all the same chems as the medihound!
medsensor = FALSE
/obj/item/device/dogborg/sleeper/compactor //Janihound gut.
name = "Garbage Processor"
@@ -668,6 +678,7 @@
compactor = TRUE
recycles = TRUE
max_item_count = 25
medsensor = FALSE
/obj/item/device/dogborg/sleeper/compactor/analyzer //sci-borg gut.
name = "Digestive Analyzer"

View File

@@ -32,7 +32,7 @@
// SetStunned(min(stunned, 30))
SetParalysis(min(paralysis, 30))
// SetWeakened(min(weakened, 20))
sleeping = 0
SetSleeping(0)
adjustBruteLoss(0)
adjustToxLoss(0)
adjustOxyLoss(0)
@@ -78,7 +78,7 @@
if(src.sleeping)
Paralyse(3)
src.sleeping--
AdjustSleeping(-1)
//if(src.resting) // VOREStation edit. Our borgos would rather not.
// Weaken(5)
@@ -153,7 +153,13 @@
/mob/living/silicon/robot/handle_regular_hud_updates()
var/fullbright = FALSE
var/seemeson = FALSE
if (src.stat == 2 || (XRAY in mutations) || (src.sight_mode & BORGXRAY))
var/area/A = get_area(src)
if(A?.no_spoilers)
disable_spoiler_vision()
if (src.stat == DEAD || (XRAY in mutations) || (src.sight_mode & BORGXRAY))
src.sight |= SEE_TURFS
src.sight |= SEE_MOBS
src.sight |= SEE_OBJS
@@ -187,13 +193,14 @@
src.sight &= ~SEE_OBJS
src.see_in_dark = 8
src.see_invisible = SEE_INVISIBLE_NOLIGHTING
else if (src.stat != 2)
else if (src.stat != DEAD)
src.sight &= ~SEE_MOBS
src.sight &= ~SEE_TURFS
src.sight &= ~SEE_OBJS
src.see_in_dark = 8 // see_in_dark means you can FAINTLY see in the dark, humans have a range of 3 or so, tajaran have it at 8
src.see_invisible = SEE_INVISIBLE_LIVING // This is normal vision (25), setting it lower for normal vision means you don't "see" things like darkness since darkness
// has a "invisible" value of 15
plane_holder.set_vis(VIS_FULLBRIGHT,fullbright)
plane_holder.set_vis(VIS_MESONS,seemeson)
..()

View File

@@ -1142,3 +1142,19 @@
if(module_active && istype(module_active,/obj/item/weapon/gripper))
var/obj/item/weapon/gripper/G = module_active
G.drop_item_nm()
/mob/living/silicon/robot/disable_spoiler_vision()
if(sight_mode & (BORGMESON|BORGMATERIAL|BORGXRAY)) // Whyyyyyyyy have seperate defines.
var/i = 0
// Borg inventory code is very . . interesting and as such, unequiping a specific item requires jumping through some (for) loops.
var/current_selection_index = get_selected_module() // Will be 0 if nothing is selected.
for(var/thing in list(module_state_1, module_state_2, module_state_3))
i++
if(istype(thing, /obj/item/borg/sight))
var/obj/item/borg/sight/S = thing
if(S.sight_mode & (BORGMESON|BORGMATERIAL|BORGXRAY))
select_module(i)
uneq_active()
if(current_selection_index) // Select what the player had before if possible.
select_module(current_selection_index)

View File

@@ -167,7 +167,8 @@
"K9 hound" = "k9",
"K9 Alternative" = "k92",
"Secborg model V-2" = "secborg",
"Borgi" = "borgi-sec"
"Borgi" = "borgi-sec",
"Otieborg" = "oties"
)
channels = list("Security" = 1)
networks = list(NETWORK_SECURITY)
@@ -261,7 +262,7 @@
var/datum/matter_synth/medicine = new /datum/matter_synth/medicine(2000)
synths += medicine
var/obj/item/stack/medical/advanced/clotting/C = new (src)
C.uses_charge = 1
C.charge_costs = list(1000)
@@ -376,8 +377,8 @@
name = "Custodial Hound module"
sprites = list(
"Custodial Hound" = "scrubpup",
"Custodial Doggo" = "J9",
"Borgi" = "borgi-jani"
"Borgi" = "borgi-jani",
"Otieborg" = "otiej"
)
channels = list("Service" = 1)
pto_type = PTO_CIVILIAN

View File

@@ -115,25 +115,7 @@
/mob/living/silicon/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0)
return 0//The only effect that can hit them atm is flashes and they still directly edit so this works for now
/*
if(!effect || (blocked >= 2)) return 0
switch(effecttype)
if(STUN)
stunned = max(stunned,(effect/(blocked+1)))
if(WEAKEN)
weakened = max(weakened,(effect/(blocked+1)))
if(PARALYZE)
paralysis = max(paralysis,(effect/(blocked+1)))
if(IRRADIATE)
radiation += min((effect - (effect*getarmor(null, "rad"))), 0)//Rads auto check armor
if(STUTTER)
stuttering = max(stuttering,(effect/(blocked+1)))
if(EYE_BLUR)
eye_blurry = max(eye_blurry,(effect/(blocked+1)))
if(DROWSY)
drowsyness = max(drowsyness,(effect/(blocked+1)))
updatehealth()
return 1*/
/proc/islinked(var/mob/living/silicon/robot/bot, var/mob/living/silicon/ai/ai)
if(!istype(bot) || !istype(ai))

View File

@@ -143,7 +143,7 @@
if(do_after(src, reload_time))
if(reload_sound)
playsound(src, reload_sound, 50, 1)
playsound(src, reload_sound, 70, 1)
reload_count = 0
. = TRUE
else

View File

@@ -92,7 +92,7 @@
var/needs_reload = FALSE // If TRUE, mob needs to reload occasionally
var/reload_max = 1 // How many shots the mob gets before it has to reload, will not be used if needs_reload is FALSE
var/reload_count = 0 // A counter to keep track of how many shots the mob has fired so far. Reloads when it hits reload_max.
var/reload_time = 1 SECONDS // How long it takes for a mob to reload. This is to buy a player a bit of time to run or fight.
var/reload_time = 4 SECONDS // How long it takes for a mob to reload. This is to buy a player a bit of time to run or fight.
var/reload_sound = 'sound/weapons/flipblade.ogg' // What sound gets played when the mob successfully reloads. Defaults to the same sound as reloading guns. Can be null.
//Mob melee settings

View File

@@ -31,6 +31,17 @@
/turf/simulated/floor/water
)
var/randomize_location = TRUE
/mob/living/simple_mob/animal/passive/fish/Initialize()
..()
if(!default_pixel_x && randomize_location)
default_pixel_x = rand(-12, 12)
if(!default_pixel_y && randomize_location)
default_pixel_y = rand(-6, 10)
// Makes the AI unable to willingly go on land.
/mob/living/simple_mob/animal/passive/fish/IMove(newloc)
if(is_type_in_list(newloc, suitable_turf_types))
@@ -39,6 +50,11 @@
// Take damage if we are not in water
/mob/living/simple_mob/animal/passive/fish/handle_breathing()
if(istype(loc, /obj/item/glass_jar/fish))
var/obj/item/glass_jar/fish/F = loc
if(F.filled)
return
var/turf/T = get_turf(src)
if(T && !is_type_in_list(T, suitable_turf_types))
if(prob(50))
@@ -178,8 +194,8 @@
dorsal_image.color = dorsal_color
belly_image.color = belly_color
overlays += dorsal_image
overlays += belly_image
add_overlay(dorsal_image)
add_overlay(belly_image)
/datum/category_item/catalogue/fauna/rockfish
name = "Sivian Fauna - Rock Puffer"
@@ -234,6 +250,7 @@
/mob/living/simple_mob/animal/passive/fish/rockfish/Initialize()
..()
head_color = rgb(rand(min_red,max_red), rand(min_green,max_green), rand(min_blue,max_blue))
update_icon()
/mob/living/simple_mob/animal/passive/fish/rockfish/update_icon()
overlays.Cut()
@@ -245,7 +262,7 @@
head_image.color = head_color
overlays += head_image
add_overlay(head_image)
/datum/category_item/catalogue/fauna/solarfish
name = "Sivian Fauna - Solar Fin"

View File

@@ -64,6 +64,8 @@
pixel_x = -16
old_x = -16
icon_expected_width = 64
icon_expected_height = 64
meat_amount = 5
/mob/living/simple_mob/animal/space/alien/queen
@@ -95,6 +97,8 @@
pixel_x = -16
old_x = -16
icon_expected_width = 64
icon_expected_height = 64
/mob/living/simple_mob/animal/space/alien/queen/empress/mother
name = "alien mother"
@@ -111,6 +115,8 @@
pixel_x = -32
old_x = -32
icon_expected_width = 96
icon_expected_height = 96
/mob/living/simple_mob/animal/space/alien/death()
..()

View File

@@ -87,6 +87,8 @@
pixel_x = -16
default_pixel_x = -16
icon_expected_width = 64
icon_expected_height = 32
meat_amount = 3
@@ -108,6 +110,8 @@
pixel_y = -16
default_pixel_y = -16
icon_expected_width = 64
icon_expected_height = 64
meat_amount = 10

View File

@@ -45,7 +45,7 @@
"rad" = 100)
/mob/living/simple_mob/construct/juggernaut/Life()
weakened = 0
SetWeakened(0)
..()
/mob/living/simple_mob/construct/juggernaut/bullet_act(var/obj/item/projectile/P)

View File

@@ -0,0 +1,88 @@
#define STATUS_INDICATOR_Y_OFFSET 2 // Offset from the edge of the icon sprite, so 32 pixels plus whatever number is here.
#define STATUS_INDICATOR_ICON_X_SIZE 16 // Don't need to care about the Y size due to the origin being on the bottom side.
#define STATUS_INDICATOR_ICON_MARGIN 2 // The space between two status indicators.
// 'Status indicators' are icons that display over a mob's head, that visually indicate that the mob is suffering
// from some kind of effect, such as being stunned, blinded, confused, asleep, etc.
// The icons are managed automatically by the mob itself, so that their positions will shift if another indicator is added,
// and it will try to always be above the mob sprite, even for larger sprites like xenos.
/mob/living
var/list/status_indicators = null // Will become a list as needed.
// Adds an icon_state, or image overlay, to the list of indicators to be managed automatically.
// Also initializes the list if one doesn't exist.
/mob/living/proc/add_status_indicator(image/thing)
if(get_status_indicator(thing)) // No duplicates, please.
return
if(!istype(thing, /image))
thing = image(icon = 'icons/mob/status_indicators.dmi', icon_state = thing)
LAZYADD(status_indicators, thing)
handle_status_indicators()
// Similar to above but removes it instead, and nulls the list if it becomes empty as a result.
/mob/living/proc/remove_status_indicator(image/thing)
thing = get_status_indicator(thing)
cut_overlay(thing)
LAZYREMOVE(status_indicators, thing)
handle_status_indicators()
/mob/living/proc/get_status_indicator(image/thing)
if(!istype(thing, /image))
for(var/image/I in status_indicators)
if(I.icon_state == thing)
return I
return LAZYACCESS(status_indicators, LAZYFIND(status_indicators, thing))
// Refreshes the indicators over a mob's head. Should only be called when adding or removing a status indicator with the above procs,
// or when the mob changes size visually for some reason.
/mob/living/proc/handle_status_indicators()
// First, get rid of all the overlays.
for(var/thing in status_indicators)
cut_overlay(thing)
if(!LAZYLEN(status_indicators))
return
if(stat == DEAD)
return
// Now put them back on in the right spot.
var/our_sprite_x = icon_expected_width * get_icon_scale_x()
var/our_sprite_y = icon_expected_height * get_icon_scale_y()
var/x_offset = our_sprite_x // Add your own offset here later if you want.
var/y_offset = our_sprite_y + STATUS_INDICATOR_Y_OFFSET
// Calculates how 'long' the row of indicators and the margin between them should be.
// The goal is to have the center of that row be horizontally aligned with the sprite's center.
var/expected_status_indicator_length = (STATUS_INDICATOR_ICON_X_SIZE * status_indicators.len) + (STATUS_INDICATOR_ICON_MARGIN * max(status_indicators.len - 1, 0))
var/current_x_position = (x_offset / 2) - (expected_status_indicator_length / 2)
// In /mob/living's `update_transform()`, the sprite is horizontally shifted when scaled up, so that the center of the sprite doesn't move to the right.
// Because of that, this adjustment needs to happen with the future indicator row as well, or it will look bad.
current_x_position -= (icon_expected_width / 2) * (get_icon_scale_y() - 1)
// Now the indicator row can actually be built.
for(var/thing in status_indicators)
var/image/I = thing
// This is a semi-HUD element, in a similar manner as medHUDs, in that they're 'above' everything else in the world,
// but don't pierce obfuscation layers such as blindness or darkness, unlike actual HUD elements like inventory slots.
I.plane = PLANE_STATUS
I.layer = HUD_LAYER
I.appearance_flags = PIXEL_SCALE|TILE_BOUND|NO_CLIENT_COLOR|RESET_COLOR|RESET_ALPHA|RESET_TRANSFORM|KEEP_APART
I.pixel_y = y_offset
I.pixel_x = current_x_position
add_overlay(I)
// Adding the margin space every time saves a conditional check on the last iteration,
// and it won't cause any issues since no more icons will be added, and the var is not used for anything else.
current_x_position += STATUS_INDICATOR_ICON_X_SIZE + STATUS_INDICATOR_ICON_MARGIN
#undef STATUS_INDICATOR_Y_OFFSET
#undef STATUS_INDICATOR_ICON_X_SIZE
#undef STATUS_INDICATOR_ICON_MARGIN

View File

@@ -66,6 +66,10 @@
plane_holder.set_ao(VIS_OBJS, ao_enabled)
plane_holder.set_ao(VIS_MOBS, ao_enabled)
// Status indicators
var/status_enabled = client.is_preference_enabled(/datum/client_preference/status_indicators)
plane_holder.set_vis(VIS_STATUS, status_enabled)
//set macro to normal incase it was overriden (like cyborg currently does)
client.set_hotkeys_macro("macro", "hotkeymode")

View File

@@ -181,6 +181,7 @@
var/status_flags = CANSTUN|CANWEAKEN|CANPARALYSE|CANPUSH //bitflags defining which status effects can be inflicted (replaces canweaken, canstun, etc)
var/area/lastarea = null
var/lastareachange = null
var/digitalcamo = 0 // Can they be tracked by the AI?

View File

@@ -197,7 +197,7 @@
return result
// Can't control ourselves when drifting
if(isspace(loc) || my_mob.lastarea?.has_gravity == 0)
if((isspace(loc) || my_mob.lastarea?.has_gravity == 0) && !my_mob.in_enclosed_vehicle) //If(In space or last area had no gravity) or(you in vehicle)
if(!my_mob.Process_Spacemove(0))
return 0
@@ -295,7 +295,7 @@
// It's just us and another person
if(grablist.len == 1)
var/mob/M = grablist[1]
if(!my_mob.Adjacent(M)) //Oh no, we moved away
if(M && !my_mob.Adjacent(M)) //Oh no, we moved away
M.Move(pre_move_loc, get_dir(M, pre_move_loc), total_delay) //Have them step towards where we were
// It's a grab chain

View File

@@ -11,6 +11,7 @@
my_mob = this_guy
//It'd be nice to lazy init these but some of them are important to just EXIST. Like without ghost planemaster, you can see ghosts. Go figure.
//Note, if you're adding a new plane master, please update code\modules\tgui\modules\camera.dm.
// 'Utility' planes
plane_masters[VIS_FULLBRIGHT] = new /obj/screen/plane_master/fullbright //Lighting system (lighting_overlay objects)
@@ -29,6 +30,8 @@
plane_masters[VIS_CH_SPECIAL] = new /obj/screen/plane_master{plane = PLANE_CH_SPECIAL} //"Special" role stuff
plane_masters[VIS_CH_STATUS_OOC]= new /obj/screen/plane_master{plane = PLANE_CH_STATUS_OOC} //OOC status HUD
plane_masters[VIS_STATUS] = new /obj/screen/plane_master{plane = PLANE_STATUS} //Status indicators that show over mob heads.
plane_masters[VIS_ADMIN1] = new /obj/screen/plane_master{plane = PLANE_ADMIN1} //For admin use
plane_masters[VIS_ADMIN2] = new /obj/screen/plane_master{plane = PLANE_ADMIN2} //For admin use
plane_masters[VIS_ADMIN3] = new /obj/screen/plane_master{plane = PLANE_ADMIN3} //For admin use

View File

@@ -2,10 +2,13 @@
BLOOD SYSTEM
****************************************************/
//Blood levels. These are percentages based on the species blood_volume var.
//Retained for archival/reference purposes - KK
/*
var/const/BLOOD_VOLUME_SAFE = 85
var/const/BLOOD_VOLUME_OKAY = 75
var/const/BLOOD_VOLUME_BAD = 60
var/const/BLOOD_VOLUME_SURVIVE = 40
*/
var/const/CE_STABLE_THRESHOLD = 0.5
/mob/living/carbon/human/var/datum/reagents/vessel // Container for blood and BLOOD ONLY. Do not transfer other chems here.
@@ -88,22 +91,22 @@ var/const/CE_STABLE_THRESHOLD = 0.5
// dmg_coef = min(1, 10/chem_effects[CE_STABLE]) //TODO: add effect for increased damage
// threshold_coef = min(dmg_coef / CE_STABLE_THRESHOLD, 1)
if(blood_volume >= BLOOD_VOLUME_SAFE)
if(blood_volume_raw >= species.blood_volume*species.blood_level_safe)
if(pale)
pale = 0
update_icons_body()
else if(blood_volume >= BLOOD_VOLUME_OKAY)
else if(blood_volume_raw >= species.blood_volume*species.blood_level_warning)
if(!pale)
pale = 1
update_icons_body()
var/word = pick("dizzy","woosey","faint")
to_chat(src, "<font color='red'>You feel [word]</font>")
var/word = pick("dizzy","woozy","faint","disoriented","unsteady")
to_chat(src, "<font color='red'>You feel slightly [word]</font>")
if(prob(1))
var/word = pick("dizzy","woosey","faint")
var/word = pick("dizzy","woozy","faint","disoriented","unsteady")
to_chat(src, "<font color='red'>You feel [word]</font>")
if(getOxyLoss() < 20 * threshold_coef)
adjustOxyLoss(3 * dmg_coef)
else if(blood_volume >= BLOOD_VOLUME_BAD)
else if(blood_volume_raw >= species.blood_volume*species.blood_level_danger)
if(!pale)
pale = 1
update_icons_body()
@@ -113,13 +116,13 @@ var/const/CE_STABLE_THRESHOLD = 0.5
adjustOxyLoss(1 * dmg_coef)
if(prob(15))
Paralyse(rand(1,3))
var/word = pick("dizzy","woosey","faint")
to_chat(src, "<font color='red'>You feel extremely [word]</font>")
else if(blood_volume >= BLOOD_VOLUME_SURVIVE)
var/word = pick("dizzy","woozy","faint","disoriented","unsteady")
to_chat(src, "<font color='red'>You feel dangerously [word]</font>")
else if(blood_volume_raw >= species.blood_volume*species.blood_level_fatal)
adjustOxyLoss(5 * dmg_coef)
// adjustToxLoss(3 * dmg_coef)
if(prob(15))
var/word = pick("dizzy","woosey","faint")
var/word = pick("dizzy","woozy","faint","disoriented","unsteady")
to_chat(src, "<font color='red'>You feel extremely [word]</font>")
else //Not enough blood to survive (usually)
if(!pale)
@@ -131,7 +134,7 @@ var/const/CE_STABLE_THRESHOLD = 0.5
adjustOxyLoss(75 * dmg_coef) // 15 more than dexp fixes (also more than dex+dexp+tricord)
// Without enough blood you slowly go hungry.
if(blood_volume < BLOOD_VOLUME_SAFE)
if(blood_volume_raw < species.blood_volume*species.blood_level_safe)
if(nutrition >= 300)
adjust_nutrition(-10)
else if(nutrition >= 200)

View File

@@ -525,7 +525,7 @@ This function completely restores a damaged organ to perfect condition.
//Burn damage can cause fluid loss due to blistering and cook-off
if((damage > 5 || damage + burn_dam >= 15) && type == BURN && (robotic < ORGAN_ROBOT) && !(species.flags & NO_BLOOD))
var/fluid_loss = 0.4 * (damage/(owner.getMaxHealth() - config.health_threshold_dead)) * owner.species.blood_volume*(1 - BLOOD_VOLUME_SURVIVE/100)
var/fluid_loss = 0.4 * (damage/(owner.getMaxHealth() - config.health_threshold_dead)) * owner.species.blood_volume*(1 - owner.species.blood_level_fatal)
owner.remove_blood(fluid_loss)
// first check whether we can widen an existing wound

View File

@@ -42,7 +42,7 @@ mob/living/carbon/human/proc/handle_pain()
maxdam = dam
if(damaged_organ && chem_effects[CE_PAINKILLER] < maxdam)
if(maxdam > 10 && paralysis)
paralysis = max(0, paralysis - round(maxdam/10))
AdjustParalysis(-round(maxdam/10))
if(maxdam > 50 && prob(maxdam / 5))
drop_item()
var/burning = damaged_organ.burn_dam > damaged_organ.brute_dam

Some files were not shown because too many files have changed in this diff Show More