This commit is contained in:
Putnam3145
2022-08-07 17:59:28 -07:00
382 changed files with 5255 additions and 2567 deletions
+5 -1
View File
@@ -80,7 +80,7 @@
//DNA - Because fuck you and your magic numbers being all over the codebase.
#define DNA_BLOCK_SIZE 3
#define DNA_UNI_IDENTITY_BLOCKS 15
#define DNA_UNI_IDENTITY_BLOCKS 19
#define DNA_HAIR_COLOR_BLOCK 1
#define DNA_FACIAL_HAIR_COLOR_BLOCK 2
#define DNA_SKIN_TONE_BLOCK 3
@@ -96,6 +96,10 @@
#define DNA_MUTANTEAR_BLOCK 13
#define DNA_MUTANTMARKING_BLOCK 14
#define DNA_TAUR_BLOCK 15
#define DNA_BARK_SOUND_BLOCK 16
#define DNA_BARK_SPEED_BLOCK 17
#define DNA_BARK_PITCH_BLOCK 18
#define DNA_BARK_VARIANCE_BLOCK 19
#define DNA_SEQUENCE_LENGTH 4
#define DNA_MUTATION_BLOCKS 8
+4
View File
@@ -0,0 +1,4 @@
#define DEFINE_BITFIELD(_variable, _flags) /datum/bitfield/##_variable { \
flags = ##_flags; \
variable = #_variable; \
}
+4 -2
View File
@@ -274,6 +274,8 @@
// #define HEARING_SPANS 6
#define HEARING_MESSAGE_MODE 7
// #define HEARING_SOURCE 8
#define COMSIG_MOVABLE_BARK "movable_bark" //from base of atom/movable/proc/bark(): (list/hearers, distance, volume, pitch)
#define COMSIG_MOVABLE_QUEUE_BARK "movable_queue_bark" //from base of atom/movable/proc/send_speech(): (list/hearers, message, range, atom/movable/source, bubble_type, list/spans, datum/language/message_language, message_mode)
#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
#define COMSIG_MOVABLE_TELEPORTED "movable_teleported" //from base of do_teleport(): (channel, turf/origin, turf/destination)
#define COMSIG_MOVABLE_CHASM_DROP "movable_chasm_drop" //from base of /datum/component/chasm/drop() (/datum/component/chasm)
@@ -417,7 +419,7 @@
#define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling
#define COMPONET_INTERRUPT_STATUS_EFFECTS 3 // interrupt status effects
#define COMSIG_LIVING_BIOLOGICAL_LIFE "biological_life" //from base of mob/living/BiologicalLife() (seconds, times_fired)
#define COMSIG_LIVING_BIOLOGICAL_LIFE "biological_life" //from base of mob/living/BiologicalLife() (delta_time, times_fired)
#define COMSIG_LIVING_PHYSICAL_LIFE "physical_life" //from base of mob/living/PhysicalLife() (seconds, times_fired)
@@ -569,7 +571,7 @@
#define COMSIG_MECHA_EQUIPMENT_CLICK "mecha_action_equipment_click"
/// Prevents click from happening.
#define COMPONENT_CANCEL_EQUIPMENT_CLICK (1<<0)
// /mob/living/carbon/human signals
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
@@ -0,0 +1,3 @@
/// Called from /mob/living/PushAM -- Called when this mob is about to push a movable, but before it moves
/// (aotm/movable/being_pushed)
#define COMSIG_LIVING_PUSHING_MOVABLE "living_pushing_movable"
@@ -0,0 +1,2 @@
///From base of mob/living/MobBump() (mob/living)
#define COMSIG_LIVING_MOB_BUMP "living_mob_bump"
@@ -0,0 +1,25 @@
// Subsystem signals. Format:
// When the signal is called: (signal arguments)
// All signals send the source datum of the signal as the first argument
///Subsystem signals
///From base of datum/controller/subsystem/Initialize: (start_timeofday)
#define COMSIG_SUBSYSTEM_POST_INITIALIZE "subsystem_post_initialize"
///Called when the ticker enters the pre-game phase
#define COMSIG_TICKER_ENTER_PREGAME "comsig_ticker_enter_pregame"
///Called when the ticker sets up the game for start
#define COMSIG_TICKER_ENTER_SETTING_UP "comsig_ticker_enter_setting_up"
///Called when the ticker fails to set up the game for start
#define COMSIG_TICKER_ERROR_SETTING_UP "comsig_ticker_error_setting_up"
/// Called when the round has started, but before GAME_STATE_PLAYING
#define COMSIG_TICKER_ROUND_STARTING "comsig_ticker_round_starting"
// Point of interest signals
/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_added : (atom/new_poi)
#define COMSIG_ADDED_POINT_OF_INTEREST "added_point_of_interest"
/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_removed : (atom/old_poi)
#define COMSIG_REMOVED_POINT_OF_INTEREST "removed_point_of_interest"
+3
View File
@@ -187,6 +187,9 @@
#define ABOVE_HUD_LAYER 30
#define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE"
#define LOBBY_BACKGROUND_LAYER 3
#define LOBBY_BUTTON_LAYER 4
#define SPLASHSCREEN_LAYER 90
#define SPLASHSCREEN_PLANE 90
#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"
+5
View File
@@ -91,3 +91,8 @@
#define LOADOUT_TAB 4
#define CONTENT_PREFERENCES_TAB 5
#define KEYBINDINGS_TAB 6
//quirks
#define QUIRK_POSITIVE "Positive"
#define QUIRK_NEGATIVE "Negative"
#define QUIRK_NEUTRAL "Neutral"
+2 -1
View File
@@ -42,6 +42,7 @@
#define LOG_MECHA (1 << 17)
#define LOG_SHUTTLE (1 << 18)
#define LOG_VICTIM (1 << 19)
#define LOG_ECON (1 << 20)
//Individual logging panel pages
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK | LOG_VICTIM)
@@ -50,7 +51,7 @@
#define INDIVIDUAL_COMMS_LOG (LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS)
#define INDIVIDUAL_OOC_LOG (LOG_OOC | LOG_ADMIN)
#define INDIVIDUAL_OWNERSHIP_LOG (LOG_OWNERSHIP)
#define INDIVIDUAL_SHOW_ALL_LOG (LOG_ATTACK | LOG_SAY | LOG_WHISPER | LOG_EMOTE | LOG_DSAY | LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS | LOG_OOC | LOG_ADMIN | LOG_OWNERSHIP | LOG_GAME | LOG_VICTIM)
#define INDIVIDUAL_SHOW_ALL_LOG (LOG_ATTACK | LOG_SAY | LOG_WHISPER | LOG_EMOTE | LOG_DSAY | LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS | LOG_OOC | LOG_ADMIN | LOG_OWNERSHIP | LOG_GAME | LOG_VICTIM | LOG_ECON)
#define LOGSRC_CLIENT "Client"
#define LOGSRC_MOB "Mob"
-1
View File
@@ -5,7 +5,6 @@
// Ready states at roundstart for mob/dead/new_player
#define PLAYER_NOT_READY 0
#define PLAYER_READY_TO_PLAY 1
#define PLAYER_READY_TO_OBSERVE 2
// movement intent defines for the m_intent var
#define MOVE_INTENT_WALK "walk"
+1 -1
View File
@@ -13,7 +13,7 @@ GLOBAL_VAR_INIT(glide_size_multiplier, 1.0)
/// Then that's multiplied by the global glide size multiplier. 1.25 by default feels pretty close to spot on. This is just to try to get byond to behave.
/// The whole result is then clamped to within the range above.
/// Not very readable but it works
#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((32 / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE))
#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((world.icon_size / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE))
/// Enables smooth movement
// #define SMOOTH_MOVEMENT
+2 -1
View File
@@ -8,5 +8,6 @@
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list(
/datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases
/datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc.
/datum/reagent/consumable/semen //NO.
/datum/reagent/consumable/semen, //NO.
/datum/reagent/consumable/milk
))
+2 -1
View File
@@ -15,6 +15,7 @@
#define DISABLE_DEATHRATTLE (1<<12)
#define DISABLE_ARRIVALRATTLE (1<<13)
#define COMBOHUD_LIGHTING (1<<14)
#define SOUND_BARK (1<<15)
#define DEADMIN_ALWAYS (1<<0)
#define DEADMIN_ANTAGONIST (1<<1)
@@ -22,7 +23,7 @@
#define DEADMIN_POSITION_SECURITY (1<<3)
#define DEADMIN_POSITION_SILICON (1<<4)
#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS)
#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS|SOUND_BARK)
//Chat toggles
#define CHAT_OOC (1<<0)
+1
View File
@@ -27,6 +27,7 @@
#define NOBLIUM_RESEARCH_AMOUNT 25
#define BZ_RESEARCH_SCALE 4
#define BZ_RESEARCH_MAX_AMOUNT 400
#define QCD_RESEARCH_AMOUNT 0.2 // often made in absolutely massive quantities due to the simple nature of fusion
#define MIASMA_RESEARCH_AMOUNT 6
#define STIMULUM_RESEARCH_AMOUNT 50
//Plasma fusion properties
+3 -1
View File
@@ -73,7 +73,9 @@
TECHWEB_POINT_TYPE_GENERIC = "General Research"\
)
#define LARGEST_BOMB "bomb"
#define BOMB_TARGET_POINTS 50000 //Adjust as needed. Actual hard cap is double this, but will never be reached due to hyperbolic curve.
#define BOMB_TARGET_SIZE (world.system_type == MS_WINDOWS ? 240 : 50000) // The shockwave radius required for a bomb to get TECHWEB_BOMB_MIDPOINT points.
#define BOMB_TARGET_SIZE 300 // The shockwave radius required for a bomb to get TECHWEB_BOMB_MIDPOINT points.
// Linux still has old trit fires, so
#define BOMB_SUB_TARGET_EXPONENT 3 // The power of the points curve below the target size. Higher = less points for worse bombs, below target.
+22
View File
@@ -37,6 +37,7 @@
#define MODE_ALIEN "alientalk"
#define MODE_HOLOPAD "holopad"
#define MODE_STATUSDISPLAY "statusdisplay"
#define MODE_CHANGELING "changeling"
#define MODE_KEY_CHANGELING "g"
@@ -91,11 +92,32 @@
//ambition end
#define MAX_MESSAGE_LEN 4096 //Citadel edit: What's the WORST that could happen?
#define MAX_FLAVOR_LEN 4096
#define MAX_FLAVOR_PREVIEW_LEN 40
#define MAX_TASTE_LEN 40 //lick... vore... ew...
#define MAX_NAME_LEN 42
#define MAX_BROADCAST_LEN 512
#define MAX_CHARTER_LEN 80
//Bark defines
#define BARK_DEFAULT_MINPITCH 0.6
#define BARK_DEFAULT_MAXPITCH 1.4
#define BARK_DEFAULT_MINVARY 0.1
#define BARK_DEFAULT_MAXVARY 0.4
#define BARK_DEFAULT_MINSPEED 2
#define BARK_DEFAULT_MAXSPEED 8
#define BARK_SPEED_BASELINE 4 //Used to calculate delay between barks, any bark speeds below this feature higher bark density, any speeds above feature lower bark density. Keeps barking length consistent
#define BARK_MAX_BARKS 128
#define BARK_MAX_TIME (10 SECONDS) // More or less the amount of time the above takes to process through with a bark speed of 2.
#define BARK_PITCH_RAND(gend) ((gend == MALE ? rand(60, 120) : (gend == FEMALE ? rand(80, 140) : rand(60,140))) / 100) //Macro for determining random pitch based off gender
#define BARK_VARIANCE_RAND (rand(BARK_DEFAULT_MINVARY * 100, BARK_DEFAULT_MAXVARY * 100) / 100) //Macro for randomizing bark variance to reduce the amount of copy-pasta necessary for that
#define BARK_DO_VARY(pitch, variance) (rand(((pitch * 100) - (variance*50)), ((pitch*100) + (variance*50))) / 100)
#define BARK_SOUND_FALLOFF_EXPONENT(distance) (distance/7) //At lower ranges, we want the exponent to be below 1 so that whispers don't sound too awkward. At higher ranges, we want the exponent fairly high to make yelling less obnoxious
// Is something in the IC chat filter? This is config dependent.
#define CHAT_FILTER_CHECK(T) (config.ic_filter_regex && findtext(T, config.ic_filter_regex))
+2
View File
@@ -233,6 +233,8 @@
#define TRAIT_TRASHCAN "trashcan"
///Used for fireman carry to have mobe not be dropped when passing by a prone individual.
#define TRAIT_BEING_CARRIED "being_carried"
#define TRAIT_GLASS_BONES "glass_bones"
#define TRAIT_PAPER_SKIN "paper_skin"
// mobility flag traits
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
+4
View File
@@ -161,6 +161,10 @@
if (CONFIG_GET(flag/log_telecomms))
WRITE_LOG(GLOB.world_telecomms_log, "TCOMMS: [text]")
/proc/log_econ(text)
if (CONFIG_GET(flag/log_econ))
WRITE_LOG(GLOB.world_econ_log, "MONEY: [text]")
/proc/log_chat(text)
if (CONFIG_GET(flag/log_pda))
//same thing here
+12
View File
@@ -0,0 +1,12 @@
///Returns whether or not a player is a guest using their ckey as an input
/proc/is_guest_key(key)
if(findtext(key, "Guest-", 1, 7) != 1) //was findtextEx
return FALSE
var/i, ch, len = length(key)
for(i = 7, i <= len, ++i) //we know the first 6 chars are Guest-
ch = text2ascii(key, i)
if (ch < 48 || ch > 57) //0-9
return FALSE
return TRUE
+6
View File
@@ -79,6 +79,12 @@
var/datum/emote/E = new path()
E.emote_list[E.key] = E
for(var/path in subtypesof(/datum/bark))
var/datum/bark/B = new path()
GLOB.bark_list[B.id] = path
if(B.allow_random)
GLOB.bark_random_list[B.id] = path
// Hair Gradients - Initialise all /datum/sprite_accessory/hair_gradient into an list indexed by gradient-style name
for(var/path in subtypesof(/datum/sprite_accessory/hair_gradient))
var/datum/sprite_accessory/hair_gradient/H = new path()
+19
View File
@@ -138,6 +138,25 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro
var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
return list(cosval,sinval,0,0, -sinval,cosval,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
/**
* Builds a color matrix that transforms the hue, saturation, and value, all in one operation.
*/
/proc/color_matrix_hsv(hue, saturation, value)
hue = clamp(360 - hue, 0, 360)
// This is very much a rough approximation of hueshifting. This carries some artifacting, such as negative values that simply shouldn't exist, but it does get the job done, and that's what matters.
var/cos_a = cos(hue) // These have to be inverted from 360, otherwise the hue's inverted
var/sin_a = sin(hue)
var/rot_x = cos_a + (1 - cos_a) / 3
var/rot_y = (1 - cos_a) / 3 - 0.5774 * sin_a // 0.5774 is sqrt(1/3)
var/rot_z = (1 - cos_a) / 3 + 0.5774 * sin_a
return list(
round((((1-saturation) * LUMA_R) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_z * saturation)) * value, 0.01),
round((((1-saturation) * LUMA_G) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_y * saturation)) * value, 0.01),
round((((1-saturation) * LUMA_B) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_x * saturation)) * value, 0.01),
0, 0, 0
)
//Returns a matrix addition of A with B
/proc/color_matrix_add(list/A, list/B)
+1 -1
View File
@@ -19,7 +19,7 @@
speed /= segments
if(parallel)
animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
animate(src, transform = matrices[1], time = speed, loops, flags = ANIMATION_PARALLEL)
else
animate(src, transform = matrices[1], time = speed, loops)
+17 -6
View File
@@ -258,15 +258,24 @@
send2adminchat("Server", "A round of [mode.name] just ended[mode_result == "undefined" ? "." : " with a [mode_result]."] Survival rate: [survival_rate]")
if(LAZYLEN(GLOB.round_end_notifiees))
world.TgsTargetedChatBroadcast("[GLOB.round_end_notifiees.Join(", ")] the round has ended.", FALSE)
if(length(CONFIG_GET(keyed_list/cross_server)))
send_news_report()
//tell the nice people on discord what went on before the salt cannon happens.
world.TgsTargetedChatBroadcast("The current round has ended. Please standby for your shift interlude Nanotrasen News Network's report!", FALSE)
world.TgsTargetedChatBroadcast(send_news_report(), FALSE)
if(CONFIG_GET(string/chat_roundend_notice_tag))
var/broadcastmessage = ""
if(LAZYLEN(GLOB.round_end_notifiees))
broadcastmessage += "[GLOB.round_end_notifiees.Join(", ")], "
broadcastmessage += "[((broadcastmessage == "") ? "the" : "The")] current round has ended. Please standby for your shift interlude Nanotrasen News Network's report!\n"
broadcastmessage += "```\n[send_news_report()]\n```"
if(CONFIG_GET(string/chat_reboot_role))
broadcastmessage += "\n\n<@&[CONFIG_GET(string/chat_reboot_role)]>, the server will reboot shortly!"
send2chat(broadcastmessage, CONFIG_GET(string/chat_roundend_notice_tag))
CHECK_TICK
@@ -370,6 +379,8 @@
parts += "[FOURSPACES]Shift Duration: <B>[DisplayTimeText(world.time - SSticker.round_start_time)]</B>"
parts += "[FOURSPACES]Station Integrity: <B>[mode.station_was_nuked ? "<span class='redtext'>Destroyed</span>" : "[popcount["station_integrity"]]%"]</B>"
if(mode.station_was_nuked && SSevents.holidays && SSevents.holidays[PRIDE_MONTH])
parts += "[FOURSPACES]Gender revealed: <B>[pick(500; "Male", 500; "Female", "Bigender", "Agender", "Demiboy", "Demigirl", "Genderfluid", "Pangender", "Xenogender", "Clown", 50; "What", 50; "Oh no.", 50; "Excuse me?")]</B>"
var/total_players = GLOB.joined_player_list.len
if(total_players)
parts+= "[FOURSPACES]Total Population: <B>[total_players]</B>"
@@ -548,7 +559,7 @@
parts += "There were [station_vault] credits collected by crew this shift.<br>"
if(total_players > 0)
parts += "An average of [station_vault/total_players] credits were collected.<br>"
// log_econ("Roundend credit total: [station_vault] credits. Average Credits: [station_vault/total_players]")
log_econ("Roundend credit total: [station_vault] credits. Average Credits: [station_vault/total_players]")
if(mr_moneybags)
parts += "The most affluent crew member at shift end was <b>[mr_moneybags.account_holder] with [mr_moneybags.account_balance]</b> cr!</div>"
else
+7 -10
View File
@@ -1176,25 +1176,22 @@ GLOBAL_REAL_VAR(list/stack_trace_storage)
var/initialpixely = pixel_y
var/shiftx = rand(-pixelshiftx,pixelshiftx)
var/shifty = rand(-pixelshifty,pixelshifty)
animate(src, pixel_x = pixel_x + shiftx, pixel_y = pixel_y + shifty, time = 0.2, loop = duration)
pixel_x = initialpixelx
pixel_y = initialpixely
animate(src, pixel_x = shiftx, pixel_y = shifty, time = 0.2, loop = duration, flags = ANIMATION_RELATIVE)
animate(pixel_x = initialpixelx, pixel_y = initialpixely, time = 0.2)
/atom/proc/do_jiggle(targetangle = 45, timer = 20)
/atom/proc/do_jiggle(targetangle = 25, timer = 20)
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
var/halftime = timer * 0.5
M.Turn(pick(-targetangle, targetangle))
animate(src, transform = M, time = halftime, easing = ELASTIC_EASING)
animate(src, transform = OM, time = halftime, easing = ELASTIC_EASING)
animate(src, transform = M, time = timer * 0.1, easing = BACK_EASING | EASE_IN)
animate(transform = OM, time = timer * 0.4, easing = ELASTIC_EASING)
/atom/proc/do_squish(squishx = 1.2, squishy = 0.6, timer = 20)
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
var/halftime = timer * 0.5
M.Scale(squishx, squishy)
animate(src, transform = M, time = halftime, easing = BOUNCE_EASING)
animate(src, transform = OM, time = halftime, easing = BOUNCE_EASING)
animate(src, transform = M, time = timer * 0.5, easing = ELASTIC_EASING)
animate(transform = OM, time = timer * 0.5, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
/proc/weightclass2text(var/w_class)
switch(w_class)
+377 -328
View File
@@ -1,329 +1,378 @@
GLOBAL_LIST_INIT(bitfields, list(
"appearance_flags" = list(
"LONG_GLIDE" = LONG_GLIDE,
"RESET_COLOR" = RESET_COLOR,
"RESET_ALPHA" = RESET_ALPHA,
"RESET_TRANSFORM" = RESET_TRANSFORM,
"NO_CLIENT_COLOR" = NO_CLIENT_COLOR,
"KEEP_TOGETHER" = KEEP_TOGETHER,
"KEEP_APART" = KEEP_APART,
"PLANE_MASTER" = PLANE_MASTER,
"TILE_BOUND" = TILE_BOUND,
"PIXEL_SCALE" = PIXEL_SCALE
),
"area_flags" = list(
"ABDUCTOR_PROOF" = ABDUCTOR_PROOF,
"BLOBS_ALLOWED" = BLOBS_ALLOWED,
"BLOCK_SUICIDE" = BLOCK_SUICIDE,
"CULT_PERMITTED" = CULT_PERMITTED,
"FLORA_ALLOWED" = FLORA_ALLOWED,
"HIDDEN_AREA" = HIDDEN_AREA,
"MEGAFAUNA_SPAWN_ALLOWED" = MEGAFAUNA_SPAWN_ALLOWED,
"MOB_SPAWN_ALLOWED" = MOB_SPAWN_ALLOWED,
"NO_ALERTS" = NO_ALERTS,
"NOTELEPORT" = NOTELEPORT,
"CAVES_ALLOWED" = CAVES_ALLOWED,
"UNIQUE_AREA" = UNIQUE_AREA,
"VALID_TERRITORY" = VALID_TERRITORY,
"XENOBIOLOGY_COMPATIBLE" = XENOBIOLOGY_COMPATIBLE,
"NO_ALERTS" = NO_ALERTS,
) ,
"sight" = list(
"SEE_INFRA" = SEE_INFRA,
"SEE_SELF" = SEE_SELF,
"SEE_MOBS" = SEE_MOBS,
"SEE_OBJS" = SEE_OBJS,
"SEE_TURFS" = SEE_TURFS,
"SEE_PIXELS" = SEE_PIXELS,
"SEE_THRU" = SEE_THRU,
"SEE_BLACKNESS" = SEE_BLACKNESS,
"BLIND" = BLIND
),
"obj_flags" = list(
"EMAGGED" = EMAGGED,
"IN_USE" = IN_USE,
"CAN_BE_HIT" = CAN_BE_HIT,
"BEING_SHOCKED" = BEING_SHOCKED,
"DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION,
"ON_BLUEPRINTS" = ON_BLUEPRINTS,
"UNIQUE_RENAME" = UNIQUE_RENAME,
"USES_TGUI" = USES_TGUI,
"FROZEN" = FROZEN,
"SHOVABLE_ONTO" = SHOVABLE_ONTO,
"BLOCK_Z_OUT_DOWN" = BLOCK_Z_OUT_DOWN,
"BLOCK_Z_OUT_UP" = BLOCK_Z_OUT_UP,
"BLOCK_Z_IN_DOWN" = BLOCK_Z_IN_DOWN,
"BLOCK_Z_IN_UP" = BLOCK_Z_IN_UP,
"EXAMINE_SKIP" = EXAMINE_SKIP
),
"datum_flags" = list(
"DF_USE_TAG" = DF_USE_TAG,
"DF_VAR_EDITED" = DF_VAR_EDITED,
"DF_ISPROCESSING" = DF_ISPROCESSING,
),
"item_flags" = list(
"BEING_REMOVED" = BEING_REMOVED,
"IN_INVENTORY" = IN_INVENTORY,
"FORCE_STRING_OVERRIDE" = FORCE_STRING_OVERRIDE,
"NEEDS_PERMIT" = NEEDS_PERMIT,
"SLOWS_WHILE_IN_HAND" = SLOWS_WHILE_IN_HAND,
"NO_MAT_REDEMPTION" = NO_MAT_REDEMPTION,
"DROPDEL" = DROPDEL,
"NOBLUDGEON" = NOBLUDGEON,
"ABSTRACT" = ABSTRACT,
"IN_STORAGE" = IN_STORAGE,
"ITEM_CAN_BLOCK" = ITEM_CAN_BLOCK,
"ITEM_CAN_PARRY" = ITEM_CAN_PARRY
),
"admin_flags" = list(
"BUILDMODE" = R_BUILDMODE,
"ADMIN" = R_ADMIN,
"BAN" = R_BAN,
"FUN" = R_FUN,
"SERVER" = R_SERVER,
"DEBUG" = R_DEBUG,
"POSSESS" = R_POSSESS,
"PERMISSIONS" = R_PERMISSIONS,
"STEALTH" = R_STEALTH,
"POLL" = R_POLL,
"VAREDIT" = R_VAREDIT,
"SOUNDS" = R_SOUNDS,
"SPAWN" = R_SPAWN,
"AUTOLOGIN" = R_AUTOLOGIN,
"DBRANKS" = R_DBRANKS,
"SENSITIVE" = R_SENSITIVE
),
"interaction_flags_atom" = list(
"INTERACT_ATOM_REQUIRES_ANCHORED" = INTERACT_ATOM_REQUIRES_ANCHORED,
"INTERACT_ATOM_ATTACK_HAND" = INTERACT_ATOM_ATTACK_HAND,
"INTERACT_ATOM_UI_INTERACT" = INTERACT_ATOM_UI_INTERACT,
"INTERACT_ATOM_REQUIRES_DEXTERITY" = INTERACT_ATOM_REQUIRES_DEXTERITY,
"INTERACT_ATOM_IGNORE_INCAPACITATED" = INTERACT_ATOM_IGNORE_INCAPACITATED,
"INTERACT_ATOM_IGNORE_RESTRAINED" = INTERACT_ATOM_IGNORE_RESTRAINED,
"INTERACT_ATOM_CHECK_GRAB" = INTERACT_ATOM_CHECK_GRAB,
"INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND" = INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND,
"INTERACT_ATOM_NO_FINGERPRINT_INTERACT" = INTERACT_ATOM_NO_FINGERPRINT_INTERACT
),
"interaction_flags_machine" = list(
"INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN,
"INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE,
"INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN,
"INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON,
"INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON,
"INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON,
"INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE
),
"interaction_flags_item" = list(
"INTERACT_ITEM_ATTACK_HAND_PICKUP" = INTERACT_ITEM_ATTACK_HAND_PICKUP,
),
"pass_flags" = list(
"PASSTABLE" = PASSTABLE,
"PASSGLASS" = PASSGLASS,
"PASSGRILLE" = PASSGRILLE,
"PASSBLOB" = PASSBLOB,
"PASSMOB" = PASSMOB,
"PASSCLOSEDTURF" = PASSCLOSEDTURF,
"LETPASSTHROW" = LETPASSTHROW
),
"movement_type" = list(
"GROUND" = GROUND,
"FLYING" = FLYING,
"VENTCRAWLING" = VENTCRAWLING,
"FLOATING" = FLOATING,
"PHASING" = PHASING
),
"resistance_flags" = list(
"LAVA_PROOF" = LAVA_PROOF,
"FIRE_PROOF" = FIRE_PROOF,
"FLAMMABLE" = FLAMMABLE,
"ON_FIRE" = ON_FIRE,
"UNACIDABLE" = UNACIDABLE,
"ACID_PROOF" = ACID_PROOF,
"INDESTRUCTIBLE" = INDESTRUCTIBLE,
"FREEZE_PROOF" = FREEZE_PROOF,
"GOLIATH_RESISTANCE" = GOLIATH_RESISTANCE,
"GOLIATH_WEAKNESS" = GOLIATH_WEAKNESS
),
"flags_1" = list(
"NOJAUNT_1" = NOJAUNT_1,
"UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
"CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1,
"HEAR_1" = HEAR_1,
"DEFAULT_RICOCHET_1" = DEFAULT_RICOCHET_1,
"CONDUCT_1" = CONDUCT_1,
"NO_LAVA_GEN_1" = NO_LAVA_GEN_1,
"NODECONSTRUCT_1" = NODECONSTRUCT_1,
"OVERLAY_QUEUED_1" = OVERLAY_QUEUED_1,
"ON_BORDER_1" = ON_BORDER_1,
"NO_RUINS_1" = NO_RUINS_1,
"PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1,
"HOLOGRAM_1" = HOLOGRAM_1,
"SHOCKED_1" = SHOCKED_1,
"INITIALIZED_1" = INITIALIZED_1,
"NO_SCREENTIPS_1" = NO_SCREENTIPS_1,
"ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1,
"BLOCK_FACE_ATOM_1" = BLOCK_FACE_ATOM_1,
"PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1
),
"flags_ricochet" = list(
"RICOCHET_SHINY" = RICOCHET_SHINY,
"RICOCHET_HARD" = RICOCHET_HARD
),
"clothing_flags" = list(
"LAVAPROTECT" = LAVAPROTECT,
"STOPSPRESSUREDAMAGE" = STOPSPRESSUREDAMAGE,
"BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT,
"ALLOWINTERNALS" = ALLOWINTERNALS,
"NOSLIP" = NOSLIP,
"THICKMATERIAL" = THICKMATERIAL,
"VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE,
"VOICEBOX_DISABLED" = VOICEBOX_DISABLED,
"IGNORE_HAT_TOSS" = IGNORE_HAT_TOSS,
"SCAN_REAGENTS" = SCAN_REAGENTS
),
"zap_flags" = list(
"ZAP_MOB_DAMAGE" = ZAP_MOB_DAMAGE,
"ZAP_OBJ_DAMAGE" = ZAP_OBJ_DAMAGE,
"ZAP_MOB_STUN" = ZAP_MOB_STUN,
"ZAP_ALLOW_DUPLICATES" = ZAP_ALLOW_DUPLICATES,
"ZAP_MACHINE_EXPLOSIVE" = ZAP_MACHINE_EXPLOSIVE,
),
"smooth" = list(
"SMOOTH_TRUE" = SMOOTH_TRUE,
"SMOOTH_MORE" = SMOOTH_MORE,
"SMOOTH_DIAGONAL" = SMOOTH_DIAGONAL,
"SMOOTH_BORDER" = SMOOTH_BORDER,
"SMOOTH_QUEUED" = SMOOTH_QUEUED,
),
"reagents_holder_flags" = list(
"INJECTABLE" = INJECTABLE,
"DRAWABLE" = DRAWABLE,
"REFILLABLE" = REFILLABLE,
"DRAINABLE" = DRAINABLE,
"TRANSPARENT" = TRANSPARENT,
"AMOUNT_VISIBLE" = AMOUNT_VISIBLE,
"NO_REACT" = NO_REACT,
),
"car_traits" = list(
"CAN_KIDNAP" = CAN_KIDNAP,
),
"rad_flags" = list(
"RAD_PROTECT_CONTENTS" = RAD_PROTECT_CONTENTS,
"RAD_NO_CONTAMINATE" = RAD_NO_CONTAMINATE,
),
"disease_flags" = list(
"CURABLE" = CURABLE,
"CAN_CARRY" = CAN_CARRY,
"CAN_RESIST" = CAN_RESIST
),
"chemical_flags" = list(
"REAGENT_DEAD_PROCESS" = REAGENT_DEAD_PROCESS,
"REAGENT_DONOTSPLIT" = REAGENT_DONOTSPLIT,
"REAGENT_ONLYINVERSE" = REAGENT_ONLYINVERSE,
"REAGENT_ONMOBMERGE" = REAGENT_ONMOBMERGE,
"REAGENT_INVISIBLE" = REAGENT_INVISIBLE,
"REAGENT_FORCEONNEW" = REAGENT_FORCEONNEW,
"REAGENT_SNEAKYNAME" = REAGENT_SNEAKYNAME,
"REAGENT_SPLITRETAINVOL" = REAGENT_SPLITRETAINVOL,
"REAGENT_ORGANIC_PROCESS" = REAGENT_ORGANIC_PROCESS,
"REAGENT_ROBOTIC_PROCESS" = REAGENT_ROBOTIC_PROCESS
),
"clear_conversion" = list(
"REACTION_CLEAR_IMPURE" = REACTION_CLEAR_IMPURE,
"REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE
),
"organ_flags" = list(
"ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC,
"ORGAN_FROZEN" = ORGAN_FROZEN,
"ORGAN_FAILING" = ORGAN_FAILING,
"ORGAN_EXTERNAL" = ORGAN_EXTERNAL,
"ORGAN_VITAL" = ORGAN_VITAL,
"ORGAN_NO_SPOIL" = ORGAN_NO_SPOIL
),
"genital_flags" = list(
"GENITAL_BLACKLISTED" = GENITAL_BLACKLISTED,
"GENITAL_INTERNAL" = GENITAL_INTERNAL,
"GENITAL_HIDDEN" = GENITAL_HIDDEN,
"GENITAL_THROUGH_CLOTHES" = GENITAL_THROUGH_CLOTHES,
"GENITAL_FUID_PRODUCTION" = GENITAL_FUID_PRODUCTION,
"CAN_MASTURBATE_WITH" = CAN_MASTURBATE_WITH,
"MASTURBATE_LINKED_ORGAN" = MASTURBATE_LINKED_ORGAN,
"CAN_CLIMAX_WITH" = CAN_CLIMAX_WITH
GLOBAL_LIST_INIT(bitfields, generate_bitfields())
),
"mob_biotypes" = list (
"MOB_ORGANIC" = MOB_ORGANIC,
"MOB_MINERAL" = MOB_MINERAL,
"MOB_ROBOTIC" = MOB_ROBOTIC,
"MOB_UNDEAD" = MOB_UNDEAD,
"MOB_HUMANOID" = MOB_HUMANOID,
"MOB_BUG" = MOB_BUG,
"MOB_BEAST" = MOB_BEAST,
"MOB_EPIC" = MOB_EPIC,
"MOB_REPTILE" = MOB_REPTILE,
"MOB_SPIRIT" = MOB_SPIRIT
),
"mobility_flags" = list(
"MOBILITY_MOVE" = MOBILITY_MOVE,
"MOBILITY_STAND" = MOBILITY_STAND,
"MOBILITY_PICKUP" = MOBILITY_PICKUP,
"MOBILITY_USE" = MOBILITY_USE,
"MOBILITY_UI" = MOBILITY_UI,
"MOBILITY_STORAGE" = MOBILITY_STORAGE,
"MOBILITY_PULL" = MOBILITY_PULL,
"MOBILITY_HOLD" = MOBILITY_HOLD,
"MOBILITY_RESIST" = MOBILITY_RESIST
),
"combat_flags" = list(
"COMBAT_FLAG_SPRINT_TOGGLED" = COMBAT_FLAG_SPRINT_TOGGLED,
"COMBAT_FLAG_SPRINT_ACTIVE" = COMBAT_FLAG_SPRINT_ACTIVE,
"COMBAT_FLAG_ATTEMPTING_CRAWL" = COMBAT_FLAG_ATTEMPTING_CRAWL,
"COMBAT_FLAG_HARD_STAMCRIT" = COMBAT_FLAG_HARD_STAMCRIT,
"COMBAT_FLAG_INTENTIONALLY_RESTING" = COMBAT_FLAG_INTENTIONALLY_RESTING,
"COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST,
"COMBAT_FLAG_SPRINT_FORCED" = COMBAT_FLAG_SPRINT_FORCED
),
"shield_flags" = list(
"SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT,
"SHIELD_ENERGY_WEAK" = SHIELD_ENERGY_WEAK,
"SHIELD_KINETIC_WEAK" = SHIELD_KINETIC_WEAK,
"SHIELD_KINETIC_STRONG" = SHIELD_KINETIC_STRONG,
"SHIELD_ENERGY_STRONG" = SHIELD_ENERGY_STRONG,
"SHIELD_DISABLER_DISRUPTED" = SHIELD_DISABLER_DISRUPTED,
"SHIELD_NO_RANGED" = SHIELD_NO_RANGED,
"SHIELD_NO_MELEE" = SHIELD_NO_MELEE,
"SHIELD_CAN_BASH" = SHIELD_CAN_BASH,
"SHIELD_BASH_WALL_KNOCKDOWN" = SHIELD_BASH_WALL_KNOCKDOWN,
"SHIELD_BASH_ALWAYS_KNOCKDOWN" = SHIELD_BASH_ALWAYS_KNOCKDOWN,
"SHIELD_BASH_WALL_DISARM" = SHIELD_BASH_WALL_DISARM,
"SHIELD_BASH_ALWAYS_DISARM" = SHIELD_BASH_ALWAYS_DISARM,
"SHIELD_BASH_GROUND_SLAM" = SHIELD_BASH_GROUND_SLAM,
"SHIELD_BASH_GROUND_SLAM_DISARM" = SHIELD_BASH_GROUND_SLAM_DISARM
),
"storage_flags" = list(
"STORAGE_LIMIT_MAX_ITEMS" = STORAGE_LIMIT_MAX_ITEMS,
"STORAGE_LIMIT_MAX_W_CLASS" = STORAGE_LIMIT_MAX_W_CLASS,
"STORAGE_LIMIT_COMBINED_W_CLASS" = STORAGE_LIMIT_COMBINED_W_CLASS,
"STORAGE_LIMIT_VOLUME" = STORAGE_LIMIT_VOLUME
),
"mutantrace_variation" = list(
"STYLE_DIGITIGRADE" = STYLE_DIGITIGRADE,
"STYLE_MUZZLE" = STYLE_MUZZLE,
"STYLE_SNEK_TAURIC" = STYLE_SNEK_TAURIC,
"STYLE_PAW_TAURIC" = STYLE_PAW_TAURIC,
"STYLE_HOOF_TAURIC" = STYLE_HOOF_TAURIC,
"STYLE_NO_ANTHRO_ICON" = STYLE_NO_ANTHRO_ICON,
"USE_SNEK_CLIP_MASK" = USE_SNEK_CLIP_MASK,
"USE_QUADRUPED_CLIP_MASK" = USE_QUADRUPED_CLIP_MASK
),
"vis_flags" = list(
"VIS_INHERIT_ICON" = VIS_INHERIT_ICON,
"VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE,
"VIS_INHERIT_DIR" = VIS_INHERIT_DIR,
"VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER,
"VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE,
"VIS_INHERIT_ID" = VIS_INHERIT_ID,
"VIS_UNDERLAY" = VIS_UNDERLAY,
"VIS_HIDE" = VIS_HIDE
)
))
/// Specifies a bitfield for smarter debugging
/datum/bitfield
/// The variable name that contains the bitfield
var/variable
/// An associative list of the readable flag and its true value
var/list/flags
/// Turns /datum/bitfield subtypes into a list for use in debugging
/proc/generate_bitfields()
var/list/bitfields = list()
for (var/_bitfield in subtypesof(/datum/bitfield))
var/datum/bitfield/bitfield = new _bitfield
bitfields[bitfield.variable] = bitfield.flags
return bitfields
DEFINE_BITFIELD(admin_flags, list(
"ADMIN" = R_ADMIN,
"AUTOLOGIN" = R_AUTOLOGIN,
"BAN" = R_BAN,
"BUILDMODE" = R_BUILDMODE,
"DBRANKS" = R_DBRANKS,
"DEBUG" = R_DEBUG,
"FUN" = R_FUN,
"PERMISSIONS" = R_PERMISSIONS,
"POLL" = R_POLL,
"POSSESS" = R_POSSESS,
"SENSITIVE" = R_SENSITIVE,
"SERVER" = R_SERVER,
"SOUNDS" = R_SOUNDS,
"SPAWN" = R_SPAWN,
"STEALTH" = R_STEALTH,
"VAREDIT" = R_VAREDIT,
))
DEFINE_BITFIELD(appearance_flags, list(
"KEEP_APART" = KEEP_APART,
"KEEP_TOGETHER" = KEEP_TOGETHER,
"LONG_GLIDE" = LONG_GLIDE,
"NO_CLIENT_COLOR" = NO_CLIENT_COLOR,
"PASS_MOUSE" = PASS_MOUSE,
"PIXEL_SCALE" = PIXEL_SCALE,
"PLANE_MASTER" = PLANE_MASTER,
"RESET_ALPHA" = RESET_ALPHA,
"RESET_COLOR" = RESET_COLOR,
"RESET_TRANSFORM" = RESET_TRANSFORM,
"TILE_BOUND" = TILE_BOUND,
"TILE_MOVER" = TILE_MOVER,
))
DEFINE_BITFIELD(area_flags, list(
"ABDUCTOR_PROOF" = ABDUCTOR_PROOF,
"BLOBS_ALLOWED" = BLOBS_ALLOWED,
"BLOCK_SUICIDE" = BLOCK_SUICIDE,
"CULT_PERMITTED" = CULT_PERMITTED,
"FLORA_ALLOWED" = FLORA_ALLOWED,
"HIDDEN_AREA" = HIDDEN_AREA,
"MEGAFAUNA_SPAWN_ALLOWED" = MEGAFAUNA_SPAWN_ALLOWED,
"MOB_SPAWN_ALLOWED" = MOB_SPAWN_ALLOWED,
"NO_ALERTS" = NO_ALERTS,
"NOTELEPORT" = NOTELEPORT,
"CAVES_ALLOWED" = CAVES_ALLOWED,
"UNIQUE_AREA" = UNIQUE_AREA,
"VALID_TERRITORY" = VALID_TERRITORY,
"XENOBIOLOGY_COMPATIBLE" = XENOBIOLOGY_COMPATIBLE,
"NO_ALERTS" = NO_ALERTS,
))
DEFINE_BITFIELD(car_traits, list(
"CAN_KIDNAP" = CAN_KIDNAP,
))
DEFINE_BITFIELD(chemical_flags, list(
"REAGENT_DEAD_PROCESS" = REAGENT_DEAD_PROCESS,
"REAGENT_DONOTSPLIT" = REAGENT_DONOTSPLIT,
"REAGENT_FORCEONNEW" = REAGENT_FORCEONNEW,
"REAGENT_INVISIBLE" = REAGENT_INVISIBLE,
"REAGENT_ONLYINVERSE" = REAGENT_ONLYINVERSE,
"REAGENT_ONMOBMERGE" = REAGENT_ONMOBMERGE,
"REAGENT_ORGANIC_PROCESS" = REAGENT_ORGANIC_PROCESS,
"REAGENT_ROBOTIC_PROCESS" = REAGENT_ROBOTIC_PROCESS,
"REAGENT_SNEAKYNAME" = REAGENT_SNEAKYNAME,
"REAGENT_SPLITRETAINVOL" = REAGENT_SPLITRETAINVOL,
))
DEFINE_BITFIELD(clear_conversion, list(
"REACTION_CLEAR_IMPURE" = REACTION_CLEAR_IMPURE,
"REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE
))
DEFINE_BITFIELD(clothing_flags, list(
"ALLOWINTERNALS" = ALLOWINTERNALS,
"BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT,
"IGNORE_HAT_TOSS" = IGNORE_HAT_TOSS,
"LAVAPROTECT" = LAVAPROTECT,
"NOSLIP" = NOSLIP,
"SCAN_REAGENTS" = SCAN_REAGENTS,
"STOPSPRESSUREDAMAGE" = STOPSPRESSUREDAMAGE,
"THICKMATERIAL" = THICKMATERIAL,
"VOICEBOX_DISABLED" = VOICEBOX_DISABLED,
"VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE,
))
DEFINE_BITFIELD(combat_flags, list(
"COMBAT_FLAG_ATTEMPTING_CRAWL" = COMBAT_FLAG_ATTEMPTING_CRAWL,
"COMBAT_FLAG_HARD_STAMCRIT" = COMBAT_FLAG_HARD_STAMCRIT,
"COMBAT_FLAG_INTENTIONALLY_RESTING" = COMBAT_FLAG_INTENTIONALLY_RESTING,
"COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST,
"COMBAT_FLAG_SPRINT_ACTIVE" = COMBAT_FLAG_SPRINT_ACTIVE,
"COMBAT_FLAG_SPRINT_FORCED" = COMBAT_FLAG_SPRINT_FORCED,
"COMBAT_FLAG_SPRINT_TOGGLED" = COMBAT_FLAG_SPRINT_TOGGLED,
))
DEFINE_BITFIELD(datum_flags, list(
"DF_USE_TAG" = DF_USE_TAG,
"DF_VAR_EDITED" = DF_VAR_EDITED,
"DF_ISPROCESSING" = DF_ISPROCESSING,
))
DEFINE_BITFIELD(disease_flags, list(
"CAN_CARRY" = CAN_CARRY,
"CAN_RESIST" = CAN_RESIST,
"CURABLE" = CURABLE,
))
DEFINE_BITFIELD(flags_1, list(
"ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1,
"BLOCK_FACE_ATOM_1" = BLOCK_FACE_ATOM_1,
"CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1,
"CONDUCT_1" = CONDUCT_1,
"DEFAULT_RICOCHET_1" = DEFAULT_RICOCHET_1,
"HEAR_1" = HEAR_1,
"HOLOGRAM_1" = HOLOGRAM_1,
"INITIALIZED_1" = INITIALIZED_1,
"NODECONSTRUCT_1" = NODECONSTRUCT_1,
"NOJAUNT_1" = NOJAUNT_1,
"NO_LAVA_GEN_1" = NO_LAVA_GEN_1,
"NO_RUINS_1" = NO_RUINS_1,
"NO_SCREENTIPS_1" = NO_SCREENTIPS_1,
"OVERLAY_QUEUED_1" = OVERLAY_QUEUED_1,
"ON_BORDER_1" = ON_BORDER_1,
"PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1,
"PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1,
"SHOCKED_1" = SHOCKED_1,
"UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
))
DEFINE_BITFIELD(flags_ricochet, list(
"RICOCHET_SHINY" = RICOCHET_SHINY,
"RICOCHET_HARD" = RICOCHET_HARD
))
DEFINE_BITFIELD(genital_flags, list(
"CAN_CLIMAX_WITH" = CAN_CLIMAX_WITH,
"CAN_MASTURBATE_WITH" = CAN_MASTURBATE_WITH,
"GENITAL_BLACKLISTED" = GENITAL_BLACKLISTED,
"GENITAL_FUID_PRODUCTION" = GENITAL_FUID_PRODUCTION,
"GENITAL_HIDDEN" = GENITAL_HIDDEN,
"GENITAL_INTERNAL" = GENITAL_INTERNAL,
"GENITAL_THROUGH_CLOTHES" = GENITAL_THROUGH_CLOTHES,
"MASTURBATE_LINKED_ORGAN" = MASTURBATE_LINKED_ORGAN,
))
DEFINE_BITFIELD(interaction_flags_atom, list(
"INTERACT_ATOM_ATTACK_HAND" = INTERACT_ATOM_ATTACK_HAND,
"INTERACT_ATOM_CHECK_GRAB" = INTERACT_ATOM_CHECK_GRAB,
"INTERACT_ATOM_IGNORE_INCAPACITATED" = INTERACT_ATOM_IGNORE_INCAPACITATED,
"INTERACT_ATOM_IGNORE_RESTRAINED" = INTERACT_ATOM_IGNORE_RESTRAINED,
"INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND" = INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND,
"INTERACT_ATOM_NO_FINGERPRINT_INTERACT" = INTERACT_ATOM_NO_FINGERPRINT_INTERACT,
"INTERACT_ATOM_REQUIRES_ANCHORED" = INTERACT_ATOM_REQUIRES_ANCHORED,
"INTERACT_ATOM_REQUIRES_DEXTERITY" = INTERACT_ATOM_REQUIRES_DEXTERITY,
"INTERACT_ATOM_UI_INTERACT" = INTERACT_ATOM_UI_INTERACT,
))
DEFINE_BITFIELD(interaction_flags_machine, list(
"INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON,
"INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE,
"INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN,
"INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON,
"INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON,
"INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE,
"INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN,
))
DEFINE_BITFIELD(interaction_flags_item, list(
"INTERACT_ITEM_ATTACK_HAND_PICKUP" = INTERACT_ITEM_ATTACK_HAND_PICKUP,
))
DEFINE_BITFIELD(item_flags, list(
"ABSTRACT" = ABSTRACT,
"BEING_REMOVED" = BEING_REMOVED,
"DROPDEL" = DROPDEL,
"FORCE_STRING_OVERRIDE" = FORCE_STRING_OVERRIDE,
"IN_INVENTORY" = IN_INVENTORY,
"IN_STORAGE" = IN_STORAGE,
"ITEM_CAN_BLOCK" = ITEM_CAN_BLOCK,
"ITEM_CAN_PARRY" = ITEM_CAN_PARRY,
"NEEDS_PERMIT" = NEEDS_PERMIT,
"NOBLUDGEON" = NOBLUDGEON,
"NO_MAT_REDEMPTION" = NO_MAT_REDEMPTION,
"SLOWS_WHILE_IN_HAND" = SLOWS_WHILE_IN_HAND,
))
DEFINE_BITFIELD(mob_biotypes, list(
"MOB_BEAST" = MOB_BEAST,
"MOB_BUG" = MOB_BUG,
"MOB_EPIC" = MOB_EPIC,
"MOB_HUMANOID" = MOB_HUMANOID,
"MOB_MINERAL" = MOB_MINERAL,
"MOB_ORGANIC" = MOB_ORGANIC,
"MOB_REPTILE" = MOB_REPTILE,
"MOB_ROBOTIC" = MOB_ROBOTIC,
"MOB_SPIRIT" = MOB_SPIRIT,
"MOB_UNDEAD" = MOB_UNDEAD,
))
DEFINE_BITFIELD(mobility_flags, list(
"MOBILITY_HOLD" = MOBILITY_HOLD,
"MOBILITY_MOVE" = MOBILITY_MOVE,
"MOBILITY_PICKUP" = MOBILITY_PICKUP,
"MOBILITY_PULL" = MOBILITY_PULL,
"MOBILITY_RESIST" = MOBILITY_RESIST,
"MOBILITY_STAND" = MOBILITY_STAND,
"MOBILITY_STORAGE" = MOBILITY_STORAGE,
"MOBILITY_UI" = MOBILITY_UI,
"MOBILITY_USE" = MOBILITY_USE,
))
DEFINE_BITFIELD(movement_type, list(
"FLOATING" = FLOATING,
"FLYING" = FLYING,
"GROUND" = GROUND,
"PHASING" = PHASING,
"VENTCRAWLING" = VENTCRAWLING,
))
DEFINE_BITFIELD(mutantrace_variation, list(
"STYLE_DIGITIGRADE" = STYLE_DIGITIGRADE,
"STYLE_HOOF_TAURIC" = STYLE_HOOF_TAURIC,
"STYLE_MUZZLE" = STYLE_MUZZLE,
"STYLE_NO_ANTHRO_ICON" = STYLE_NO_ANTHRO_ICON,
"STYLE_PAW_TAURIC" = STYLE_PAW_TAURIC,
"STYLE_SNEK_TAURIC" = STYLE_SNEK_TAURIC,
"USE_SNEK_CLIP_MASK" = USE_SNEK_CLIP_MASK,
"USE_QUADRUPED_CLIP_MASK" = USE_QUADRUPED_CLIP_MASK,
))
DEFINE_BITFIELD(obj_flags, list(
"BEING_SHOCKED" = BEING_SHOCKED,
"BLOCK_Z_IN_DOWN" = BLOCK_Z_IN_DOWN,
"BLOCK_Z_IN_UP" = BLOCK_Z_IN_UP,
"BLOCK_Z_OUT_DOWN" = BLOCK_Z_OUT_DOWN,
"BLOCK_Z_OUT_UP" = BLOCK_Z_OUT_UP,
"CAN_BE_HIT" = CAN_BE_HIT,
"DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION,
"EMAGGED" = EMAGGED,
"EXAMINE_SKIP" = EXAMINE_SKIP,
"FROZEN" = FROZEN,
"IN_USE" = IN_USE,
"ON_BLUEPRINTS" = ON_BLUEPRINTS,
"SHOVABLE_ONTO" = SHOVABLE_ONTO,
"UNIQUE_RENAME" = UNIQUE_RENAME,
"USES_TGUI" = USES_TGUI,
))
DEFINE_BITFIELD(organ_flags, list(
"ORGAN_EXTERNAL" = ORGAN_EXTERNAL,
"ORGAN_FAILING" = ORGAN_FAILING,
"ORGAN_FROZEN" = ORGAN_FROZEN,
"ORGAN_NO_SPOIL" = ORGAN_NO_SPOIL,
"ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC,
"ORGAN_VITAL" = ORGAN_VITAL,
))
DEFINE_BITFIELD(pass_flags, list(
"LETPASSTHROW" = LETPASSTHROW,
"PASSBLOB" = PASSBLOB,
"PASSCLOSEDTURF" = PASSCLOSEDTURF,
"PASSGLASS" = PASSGLASS,
"PASSGRILLE" = PASSGRILLE,
"PASSMOB" = PASSMOB,
"PASSTABLE" = PASSTABLE,
))
DEFINE_BITFIELD(rad_flags, list(
"RAD_PROTECT_CONTENTS" = RAD_PROTECT_CONTENTS,
"RAD_NO_CONTAMINATE" = RAD_NO_CONTAMINATE,
))
DEFINE_BITFIELD(reagents_holder_flags, list(
"AMOUNT_VISIBLE" = AMOUNT_VISIBLE,
"DRAINABLE" = DRAINABLE,
"DRAWABLE" = DRAWABLE,
"INJECTABLE" = INJECTABLE,
"NO_REACT" = NO_REACT,
"REFILLABLE" = REFILLABLE,
"TRANSPARENT" = TRANSPARENT,
))
DEFINE_BITFIELD(resistance_flags, list(
"ACID_PROOF" = ACID_PROOF,
"FIRE_PROOF" = FIRE_PROOF,
"FLAMMABLE" = FLAMMABLE,
"FREEZE_PROOF" = FREEZE_PROOF,
"GOLIATH_RESISTANCE" = GOLIATH_RESISTANCE,
"GOLIATH_WEAKNESS" = GOLIATH_WEAKNESS,
"INDESTRUCTIBLE" = INDESTRUCTIBLE,
"LAVA_PROOF" = LAVA_PROOF,
"ON_FIRE" = ON_FIRE,
"UNACIDABLE" = UNACIDABLE,
))
DEFINE_BITFIELD(shield_flags, list(
"SHIELD_BASH_ALWAYS_DISARM" = SHIELD_BASH_ALWAYS_DISARM,
"SHIELD_BASH_ALWAYS_KNOCKDOWN" = SHIELD_BASH_ALWAYS_KNOCKDOWN,
"SHIELD_BASH_GROUND_SLAM" = SHIELD_BASH_GROUND_SLAM,
"SHIELD_BASH_GROUND_SLAM_DISARM" = SHIELD_BASH_GROUND_SLAM_DISARM,
"SHIELD_BASH_WALL_DISARM" = SHIELD_BASH_WALL_DISARM,
"SHIELD_BASH_WALL_KNOCKDOWN" = SHIELD_BASH_WALL_KNOCKDOWN,
"SHIELD_CAN_BASH" = SHIELD_CAN_BASH,
"SHIELD_DISABLER_DISRUPTED" = SHIELD_DISABLER_DISRUPTED,
"SHIELD_ENERGY_STRONG" = SHIELD_ENERGY_STRONG,
"SHIELD_ENERGY_WEAK" = SHIELD_ENERGY_WEAK,
"SHIELD_KINETIC_STRONG" = SHIELD_KINETIC_STRONG,
"SHIELD_KINETIC_WEAK" = SHIELD_KINETIC_WEAK,
"SHIELD_NO_MELEE" = SHIELD_NO_MELEE,
"SHIELD_NO_RANGED" = SHIELD_NO_RANGED,
"SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT,
))
DEFINE_BITFIELD(sight, list(
"BLIND" = BLIND,
"SEE_BLACKNESS" = SEE_BLACKNESS,
"SEE_INFRA" = SEE_INFRA,
"SEE_MOBS" = SEE_MOBS,
"SEE_OBJS" = SEE_OBJS,
"SEE_PIXELS" = SEE_PIXELS,
"SEE_SELF" = SEE_SELF,
"SEE_THRU" = SEE_THRU,
"SEE_TURFS" = SEE_TURFS,
))
DEFINE_BITFIELD(smooth, list(
"SMOOTH_BORDER" = SMOOTH_BORDER,
"SMOOTH_DIAGONAL" = SMOOTH_DIAGONAL,
"SMOOTH_MORE" = SMOOTH_MORE,
"SMOOTH_QUEUED" = SMOOTH_QUEUED,
"SMOOTH_TRUE" = SMOOTH_TRUE,
))
DEFINE_BITFIELD(storage_flags, list(
"STORAGE_LIMIT_COMBINED_W_CLASS" = STORAGE_LIMIT_COMBINED_W_CLASS,
"STORAGE_LIMIT_MAX_ITEMS" = STORAGE_LIMIT_MAX_ITEMS,
"STORAGE_LIMIT_MAX_W_CLASS" = STORAGE_LIMIT_MAX_W_CLASS,
"STORAGE_LIMIT_VOLUME" = STORAGE_LIMIT_VOLUME,
))
DEFINE_BITFIELD(vis_flags, list(
"VIS_HIDE" = VIS_HIDE,
"VIS_INHERIT_DIR" = VIS_INHERIT_DIR,
"VIS_INHERIT_ICON" = VIS_INHERIT_ICON,
"VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE,
"VIS_INHERIT_ID" = VIS_INHERIT_ID,
"VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER,
"VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE,
"VIS_UNDERLAY" = VIS_UNDERLAY,
))
DEFINE_BITFIELD(zap_flags, list(
"ZAP_ALLOW_DUPLICATES" = ZAP_ALLOW_DUPLICATES,
"ZAP_MACHINE_EXPLOSIVE" = ZAP_MACHINE_EXPLOSIVE,
"ZAP_MOB_DAMAGE" = ZAP_MOB_DAMAGE,
"ZAP_MOB_STUN" = ZAP_MOB_STUN,
"ZAP_OBJ_DAMAGE" = ZAP_OBJ_DAMAGE,
))
+4
View File
@@ -43,6 +43,10 @@ GLOBAL_LIST_EMPTY(arachnid_spinneret_list)
GLOBAL_LIST_EMPTY(arachnid_mandibles_list)
GLOBAL_LIST_EMPTY(caps_list)
//Bark bits
GLOBAL_LIST_EMPTY(bark_list)
GLOBAL_LIST_EMPTY(bark_random_list)
//a way to index the right bodypart list given the type of bodypart
GLOBAL_LIST_INIT(mutant_reference_list, list(
"tail_lizard" = GLOB.tails_list_lizard,
+2
View File
@@ -49,6 +49,8 @@ GLOBAL_VAR(tgui_log)
GLOBAL_PROTECT(tgui_log)
GLOBAL_VAR(world_shuttle_log)
GLOBAL_PROTECT(world_shuttle_log)
GLOBAL_VAR(world_econ_log)
GLOBAL_PROTECT(world_econ_log)
GLOBAL_VAR(perf_log)
GLOBAL_PROTECT(perf_log)
-14
View File
@@ -101,14 +101,6 @@
..()
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
var/list/L = params2list(params)
if (L["middle"])
if (src_object && src_location != over_location)
middragtime = world.time
middragatom = src_object
else
middragtime = 0
middragatom = null
mouseParams = params
mouseLocation = over_location
mouseObject = over_object
@@ -121,9 +113,3 @@
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
return
/client/MouseDrop(src_object, over_object, src_location, over_location, src_control, over_control, params)
if (middragatom == src_object)
middragtime = 0
middragatom = null
..()
+1 -1
View File
@@ -60,7 +60,7 @@
if(client && hud_used)
hud_used.reorganize_alerts()
thealert.transform = matrix(32, 6, MATRIX_TRANSLATE)
animate(thealert, transform = matrix(), time = 2.5, easing = CUBIC_EASING)
animate(thealert, transform = matrix(), time = 2.5, easing = BACK_EASING)
if(thealert.timeout)
addtimer(CALLBACK(src, .proc/alert_timeout, thealert, category), thealert.timeout)
+333
View File
@@ -0,0 +1,333 @@
/datum/hud/new_player
/datum/hud/new_player/proc/populate_buttons(mob/dead/new_player/owner)
var/list/buttons = subtypesof(/atom/movable/screen/lobby)
for(var/button_type in buttons)
var/atom/movable/screen/lobby/lobbyscreen = new button_type()
lobbyscreen.SlowInit()
lobbyscreen.hud = src
static_inventory += lobbyscreen
if(istype(lobbyscreen, /atom/movable/screen/lobby/button))
var/atom/movable/screen/lobby/button/lobby_button = lobbyscreen
lobby_button.owner = REF(owner)
show_hud(hud_version)
/atom/movable/screen/lobby
plane = SPLASHSCREEN_PLANE
layer = LOBBY_BUTTON_LAYER
screen_loc = "TOP,CENTER"
/// Run sleeping actions after initialize
/atom/movable/screen/lobby/proc/SlowInit()
return
/atom/movable/screen/lobby/background
layer = LOBBY_BACKGROUND_LAYER
icon = 'icons/hud/lobby/background.dmi'
icon_state = "background"
screen_loc = "TOP,CENTER:-61"
/atom/movable/screen/lobby/button
///Is the button currently enabled?
var/enabled = TRUE
///Is the button currently being hovered over with the mouse?
var/highlighted = FALSE
/// The ref of the mob that owns this button. Only the owner can click on it.
var/owner
/atom/movable/screen/lobby/button/Click(location, control, params)
if(owner != REF(usr))
return
. = ..()
if(!enabled)
return
flick("[base_icon_state]_pressed", src)
update_appearance(UPDATE_ICON)
return TRUE
/atom/movable/screen/lobby/button/MouseEntered(location,control,params)
if(owner != REF(usr))
return
. = ..()
highlighted = TRUE
update_appearance(UPDATE_ICON)
/atom/movable/screen/lobby/button/MouseExited()
if(owner != REF(usr))
return
. = ..()
highlighted = FALSE
update_appearance(UPDATE_ICON)
/atom/movable/screen/lobby/button/update_icon(updates)
. = ..()
if(!enabled)
icon_state = "[base_icon_state]_disabled"
return
else if(highlighted)
icon_state = "[base_icon_state]_highlighted"
return
icon_state = base_icon_state
/atom/movable/screen/lobby/button/proc/set_button_status(status)
if(status == enabled)
return FALSE
enabled = status
update_appearance(UPDATE_ICON)
return TRUE
///Prefs menu
/atom/movable/screen/lobby/button/character_setup
screen_loc = "TOP:-70,CENTER:-54"
icon = 'icons/hud/lobby/character_setup.dmi'
icon_state = "character_setup"
base_icon_state = "character_setup"
/atom/movable/screen/lobby/button/character_setup/Click(location, control, params)
. = ..()
if(!.)
return
hud.mymob.client.prefs.current_tab = SETTINGS_TAB
hud.mymob.client.prefs.ShowChoices(hud.mymob)
///Button that appears before the game has started
/atom/movable/screen/lobby/button/ready
screen_loc = "TOP:-8,CENTER:-65"
icon = 'icons/hud/lobby/ready.dmi'
icon_state = "not_ready"
base_icon_state = "not_ready"
var/ready = FALSE
/atom/movable/screen/lobby/button/ready/Initialize(mapload)
. = ..()
switch(SSticker.current_state)
if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/hide_ready_button)
if(GAME_STATE_SETTING_UP)
set_button_status(FALSE)
RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/show_ready_button)
else
set_button_status(FALSE)
/atom/movable/screen/lobby/button/ready/proc/hide_ready_button()
SIGNAL_HANDLER
set_button_status(FALSE)
UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/show_ready_button)
/atom/movable/screen/lobby/button/ready/proc/show_ready_button()
SIGNAL_HANDLER
set_button_status(TRUE)
UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/hide_ready_button)
/atom/movable/screen/lobby/button/ready/Click(location, control, params)
. = ..()
if(!.)
return
var/mob/dead/new_player/new_player = hud.mymob
ready = !ready
if(ready)
new_player.ready = PLAYER_READY_TO_PLAY
base_icon_state = "ready"
else
new_player.ready = PLAYER_NOT_READY
base_icon_state = "not_ready"
update_appearance(UPDATE_ICON)
///Shown when the game has started
/atom/movable/screen/lobby/button/join
screen_loc = "TOP:-13,CENTER:-58"
icon = 'icons/hud/lobby/join.dmi'
icon_state = "" //Default to not visible
base_icon_state = "join_game"
enabled = FALSE
/atom/movable/screen/lobby/button/join/Initialize(mapload)
. = ..()
switch(SSticker.current_state)
if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/show_join_button)
if(GAME_STATE_SETTING_UP)
set_button_status(TRUE)
RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/hide_join_button)
else
set_button_status(TRUE)
/atom/movable/screen/lobby/button/join/Click(location, control, params)
. = ..()
if(!.)
return
if(!SSticker?.IsRoundInProgress())
to_chat(hud.mymob, span_boldwarning("The round is either not ready, or has already finished..."))
return
//Determines Relevent Population Cap
var/relevant_cap
var/hpc = CONFIG_GET(number/hard_popcap)
var/epc = CONFIG_GET(number/extreme_popcap)
if(hpc && epc)
relevant_cap = min(hpc, epc)
else
relevant_cap = max(hpc, epc)
var/mob/dead/new_player/new_player = hud.mymob
if(SSticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(new_player.key) in GLOB.admin_datums)))
to_chat(new_player, span_danger("[CONFIG_GET(string/hard_popcap_message)]"))
var/queue_position = SSticker.queued_players.Find(new_player)
if(queue_position == 1)
to_chat(new_player, span_notice("You are next in line to join the game. You will be notified when a slot opens up."))
else if(queue_position)
to_chat(new_player, span_notice("There are [queue_position-1] players in front of you in the queue to join the game."))
else
SSticker.queued_players += new_player
to_chat(new_player, span_notice("You have been added to the queue to join the game. Your position in queue is [SSticker.queued_players.len]."))
return
new_player.LateChoices()
/atom/movable/screen/lobby/button/join/proc/show_join_button()
SIGNAL_HANDLER
set_button_status(TRUE)
UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/hide_join_button)
/atom/movable/screen/lobby/button/join/proc/hide_join_button()
SIGNAL_HANDLER
set_button_status(FALSE)
UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/show_join_button)
/atom/movable/screen/lobby/button/observe
screen_loc = "TOP:-40,CENTER:-54"
icon = 'icons/hud/lobby/observe.dmi'
icon_state = "observe_disabled"
base_icon_state = "observe"
enabled = FALSE
/atom/movable/screen/lobby/button/observe/Initialize(mapload)
. = ..()
if(SSticker.current_state > GAME_STATE_STARTUP)
set_button_status(TRUE)
else
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME, .proc/enable_observing)
/atom/movable/screen/lobby/button/observe/Click(location, control, params)
. = ..()
if(!.)
return
var/mob/dead/new_player/new_player = hud.mymob
new_player.make_me_an_observer()
/atom/movable/screen/lobby/button/observe/proc/enable_observing()
SIGNAL_HANDLER
flick("[base_icon_state]_enabled", src)
set_button_status(TRUE)
UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME, .proc/enable_observing)
/atom/movable/screen/lobby/button/settings
icon = 'icons/hud/lobby/bottom_buttons.dmi'
icon_state = "settings"
base_icon_state = "settings"
screen_loc = "TOP:-122,CENTER:+30"
/atom/movable/screen/lobby/button/settings/Click(location, control, params)
. = ..()
if(!.)
return
hud.mymob.client.prefs.current_tab = GAME_PREFERENCES_TAB
hud.mymob.client.prefs.ShowChoices(hud.mymob)
/atom/movable/screen/lobby/button/changelog_button
icon = 'icons/hud/lobby/bottom_buttons.dmi'
icon_state = "changelog"
base_icon_state = "changelog"
screen_loc ="TOP:-122,CENTER:+58"
/atom/movable/screen/lobby/button/crew_manifest
icon = 'icons/hud/lobby/bottom_buttons.dmi'
icon_state = "crew_manifest"
base_icon_state = "crew_manifest"
screen_loc = "TOP:-122,CENTER:+2"
/atom/movable/screen/lobby/button/crew_manifest/Click(location, control, params)
. = ..()
if(!.)
return
var/mob/dead/new_player/new_player = hud.mymob
new_player.ViewManifest()
/atom/movable/screen/lobby/button/changelog_button/Click(location, control, params)
. = ..()
usr.client?.changelog()
/atom/movable/screen/lobby/button/poll
icon = 'icons/hud/lobby/bottom_buttons.dmi'
icon_state = "poll"
base_icon_state = "poll"
screen_loc = "TOP:-122,CENTER:-26"
var/new_poll = FALSE
/atom/movable/screen/lobby/button/poll/SlowInit(mapload)
. = ..()
if(!usr)
return
var/mob/dead/new_player/new_player = usr
if(is_guest_key(new_player.key))
set_button_status(FALSE)
return
if(!SSdbcore.Connect())
set_button_status(FALSE)
return
var/isadmin = FALSE
if(new_player.client?.holder)
isadmin = TRUE
var/datum/db_query/query_get_new_polls = SSdbcore.NewQuery({"
SELECT id FROM [format_table_name("poll_question")]
WHERE (adminonly = 0 OR :isadmin = 1)
AND Now() BETWEEN starttime AND endtime
AND deleted = 0
AND id NOT IN (
SELECT pollid FROM [format_table_name("poll_vote")]
WHERE ckey = :ckey
AND deleted = 0
)
AND id NOT IN (
SELECT pollid FROM [format_table_name("poll_textreply")]
WHERE ckey = :ckey
AND deleted = 0
)
"}, list("isadmin" = isadmin, "ckey" = new_player.ckey))
if(!query_get_new_polls.Execute())
qdel(query_get_new_polls)
set_button_status(FALSE)
return
if(query_get_new_polls.NextRow())
new_poll = TRUE
else
new_poll = FALSE
update_appearance(UPDATE_OVERLAYS)
qdel(query_get_new_polls)
if(QDELETED(new_player))
set_button_status(FALSE)
return
/atom/movable/screen/lobby/button/poll/update_overlays()
. = ..()
if(new_poll)
. += mutable_appearance('icons/hud/lobby/poll_overlay.dmi', "new_poll")
/atom/movable/screen/lobby/button/poll/Click(location, control, params)
. = ..()
if(!.)
return
var/mob/dead/new_player/new_player = hud.mymob
new_player.handle_player_polling()
+1 -1
View File
@@ -178,7 +178,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
starting.Scale(0.1,0.1)
E.transform = starting
var/matrix/TM = matrix()
animate(E,pixel_x = px,pixel_y = py, transform = TM, time = timing)
animate(E,pixel_x = px,pixel_y = py, transform = TM, time = timing, easing = SINE_EASING | EASE_OUT)
else
E.pixel_y = py
E.pixel_x = px
+2
View File
@@ -126,6 +126,8 @@
return DISCARD_LAST_ACTION
user.do_attack_animation(O)
O.attacked_by(src, user)
if(force >= 20)
shake_camera(user, ((force - 15) * 0.01 + 1), ((force - 15) * 0.01))
/atom/movable/proc/attacked_by()
return
+3 -1
View File
@@ -29,7 +29,9 @@ GLOBAL_LIST_INIT(huds, list(
ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_BLOODSUCKER = new/datum/atom_hud/antag/bloodsucker(),
ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag(),
ANTAG_HUD_HERETIC = new/datum/atom_hud/antag/hidden()
ANTAG_HUD_HERETIC = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_SPACECOP = new/datum/atom_hud/antag(),
ANTAG_HUD_GANGSTER = new/datum/atom_hud/antag/hidden()
))
/datum/atom_hud
+2 -2
View File
@@ -248,7 +248,7 @@
if(P.absolute)
continue
var/matrix/translate_matrix = matrix()
translate_matrix.Translate(cos(turn) * 480, sin(turn) * 480)
translate_matrix.Translate(sin(turn) * 480, cos(turn) * 480)
var/matrix/target_matrix = matrix()
var/move_speed = speed * P.speed
// do the first segment by shifting down one screen
@@ -282,7 +282,7 @@
continue
P.CancelAnimation()
var/matrix/translate_matrix = matrix()
translate_matrix.Translate(cos(turn) * 480, sin(turn) * 480)
translate_matrix.Translate(sin(turn) * 480, cos(turn) * 480)
P.transform = translate_matrix
animate(P, transform = matrix(), time = time, easing = QUAD_EASING | EASE_OUT)
@@ -0,0 +1,14 @@
/datum/config_entry/flag/irc_announce_new_game
deprecated_by = /datum/config_entry/string/chat_announce_new_game
/datum/config_entry/flag/irc_announce_new_game/DeprecationUpdate(value)
return "" //default broadcast
/datum/config_entry/string/chat_announce_new_game
config_entry_value = null
/datum/config_entry/string/chat_reboot_role
/datum/config_entry/string/chat_roundend_notice_tag
/datum/config_entry/string/chat_squawk_tag
@@ -39,16 +39,6 @@
/datum/config_entry/flag/show_irc_name
/datum/config_entry/flag/irc_announce_new_game
deprecated_by = /datum/config_entry/string/chat_announce_new_game
/datum/config_entry/flag/irc_announce_new_game/DeprecationUpdate(value)
return "" //default broadcast
/datum/config_entry/string/chat_announce_new_game
config_entry_value = null
/datum/config_entry/string/default_view
config_entry_value = "15x15"
@@ -79,6 +79,10 @@
/datum/config_entry/flag/log_telecomms
config_entry_value = TRUE
/// log economy
/datum/config_entry/flag/log_econ
config_entry_value = TRUE
/// log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
/datum/config_entry/flag/log_twitter
config_entry_value = TRUE
+1 -1
View File
@@ -31,7 +31,7 @@ SUBSYSTEM_DEF(autotransfer)
if(world.time < targettime)
return
if(maxvotes == NO_MAXVOTES_CAP || maxvotes > curvotes)
SSvote.initiate_vote("transfer","server")
SSvote.initiate_vote("transfer","server", votesystem=APPROVAL_VOTING)
targettime = targettime + voteinterval
curvotes++
else
+8 -3
View File
@@ -367,9 +367,14 @@ SUBSYSTEM_DEF(job)
JobDebug("DO, Handling unrejectable unassigned")
//Mop up people who can't leave.
for(var/mob/dead/new_player/player in unassigned) //Players that wanted to back out but couldn't because they're antags (can you feel the edge case?)
if(!GiveRandomJob(player))
if(!AssignRole(player, SSjob.overflow_role)) //If everything is already filled, make them an assistant
return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll
if(player.client.prefs.joblessrole == BERANDOMJOB) //Gives the player a random role if their preferences are set to it
if(!GiveRandomJob(player))
if(!AssignRole(player, SSjob.overflow_role)) //If everything is already filled, make them the overflow role
return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll
else //If the player prefers to return to lobby or be an assistant, give them assistant
if(!AssignRole(player, SSjob.overflow_role))
if(!GiveRandomJob(player)) //The forced antagonist couldn't be assigned to overflow role (bans, client age) - give a random role
return FALSE //Somehow the forced antagonist couldn't be assigned to the overflow role or the a random role - reroll
return validate_required_jobs(required_jobs)
+90 -23
View File
@@ -1,3 +1,19 @@
//As a brief warning to all those who dare tread upon these grounds:
//The bulk of this code here was written years ago, back in the days of 512.
//We were incredibly drunk back then. And nowadays, we've found that being drunk is a hard requirement for working with this code.
//So if you're here to make changes? Brandish a glass. There are many sins here, but it's exactly as engineered as it needs to be.
//We physically won't be able to tell you what half of this code does. The only thing that'll help you here is the ballmer peak.
//Bottoms up, friend. And be sure to drink responsibly. Be sure to fetch some water, too; it eases the hangover. - Bhijn & Myr
// Jukelist indices
#define JUKE_TRACK 1
#define JUKE_CHANNEL 2
#define JUKE_BOX 3
#define JUKE_FALLOFF 4
#define JUKE_SOUND 5
SUBSYSTEM_DEF(jukeboxes)
name = "Jukeboxes"
wait = 5
@@ -25,27 +41,41 @@ SUBSYSTEM_DEF(jukeboxes)
var/channeltoreserve = pick(freejukeboxchannels)
if(!channeltoreserve)
return FALSE
var/sound/song_to_init = sound(T.song_path)
freejukeboxchannels -= channeltoreserve
var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff)
var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff, song_to_init)
song_to_init.status = SOUND_MUTE
song_to_init.environment = 7
song_to_init.channel = channeltoreserve
song_to_init.volume = 1
song_to_init.falloff = jukefalloff
song_to_init.echo = list(0, null, -10000, null, null, null, null, null, null, null, null, null, null, 1, 1, 1, null, null)
activejukeboxes.len++
activejukeboxes[activejukeboxes.len] = youvegotafreejukebox
//Due to changes in later versions of 512, SOUND_UPDATE no longer properly plays audio when a file is defined in the sound datum. As such, we are now required to init the audio before we can actually do anything with it.
//Downsides to this? This means that you can *only* hear the jukebox audio if you were present on the server when it started playing, and it means that it's now impossible to add loops to the jukebox track list.
var/sound/song_to_init = sound(T.song_path)
song_to_init.status = SOUND_MUTE
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
continue
M.playsound_local(M, null, 100, channel = youvegotafreejukebox[2], S = song_to_init)
SEND_SOUND(M, song_to_init)
return activejukeboxes.len
//Updates jukebox by transferring to different object or modifying falloff.
/datum/controller/subsystem/jukeboxes/proc/updatejukebox(IDtoupdate, obj/jukebox, jukefalloff)
if(islist(activejukeboxes[IDtoupdate]))
if(istype(jukebox))
activejukeboxes[IDtoupdate][JUKE_BOX] = jukebox
if(!isnull(jukefalloff))
activejukeboxes[IDtoupdate][JUKE_FALLOFF] = jukefalloff
/datum/controller/subsystem/jukeboxes/proc/removejukebox(IDtoremove)
if(islist(activejukeboxes[IDtoremove]))
var/jukechannel = activejukeboxes[IDtoremove][2]
var/jukechannel = activejukeboxes[IDtoremove][JUKE_CHANNEL]
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
@@ -85,37 +115,74 @@ SUBSYSTEM_DEF(jukeboxes)
if(!jukeinfo.len)
stack_trace("Active jukebox without any associated metadata.")
continue
var/datum/track/juketrack = jukeinfo[1]
var/datum/track/juketrack = jukeinfo[JUKE_TRACK]
if(!istype(juketrack))
stack_trace("Invalid jukebox track datum.")
continue
var/obj/jukebox = jukeinfo[3]
var/obj/jukebox = jukeinfo[JUKE_BOX]
if(!istype(jukebox))
stack_trace("Nonexistant or invalid object associated with jukebox.")
continue
var/sound/song_played = sound(juketrack.song_path)
var/list/audible_zlevels = get_multiz_accessible_levels(jukebox.z) //TODO - for multiz refresh, this should use the cached zlevel connections var in SSMapping. For now this is fine!
var/sound/song_played = jukeinfo[JUKE_SOUND]
var/turf/currentturf = get_turf(jukebox)
var/area/currentarea = get_area(jukebox)
var/list/hearerscache = hearers(7, jukebox)
var/targetfalloff = jukeinfo[JUKE_FALLOFF]
var/mixes = ((targetfalloff*250)-750)
var/inrange
var/pressure_factor
song_played.falloff = jukeinfo[4]
var/datum/gas_mixture/source_env = (istype(currentturf) ? currentturf.return_air() : null)
var/datum/gas_mixture/hearer_env //We init this var outside of the mob loop for the sake of performance
var/turf/hearerturf //ditto
var/source_pressure = (istype(source_env) ? source_env.return_pressure() : 0)
song_played.falloff = targetfalloff
song_played.volume = min((targetfalloff * 50), 100)
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS) || !M.can_hear())
M.stop_sound_channel(jukeinfo[2])
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
M.stop_sound_channel(jukeinfo[JUKE_CHANNEL])
continue
var/inrange = FALSE
if(jukebox.z == M.z) //todo - expand this to work with mining planet z-levels when robust jukebox audio gets merged to master
song_played.status = SOUND_UPDATE
if(get_area(M) == currentarea)
inrange = TRUE
else if(M in hearerscache)
inrange = TRUE
else
song_played.status = SOUND_MUTE | SOUND_UPDATE //Setting volume = 0 doesn't let the sound properties update at all, which is lame.
M.playsound_local(currentturf, null, 100, channel = jukeinfo[2], S = song_played, envwet = (inrange ? -250 : 0), envdry = (inrange ? 0 : -10000))
inrange = FALSE
song_played.status = SOUND_MUTE | SOUND_UPDATE
if(source_pressure)
hearerturf = get_turf(M)
hearer_env = (istype(hearerturf) ? hearerturf.return_air() : null)
if(istype(hearer_env))
pressure_factor = min(source_pressure, hearer_env.return_pressure())
if(pressure_factor && targetfalloff && M.can_hear() && (hearerturf.z in audible_zlevels))
if(get_area(hearerturf) == currentarea)
inrange = TRUE
else if(M in hearerscache)
inrange = TRUE
song_played.x = (currentturf.x - hearerturf.x) * SOUND_DEFAULT_DISTANCE_MULTIPLIER
song_played.z = (currentturf.y - hearerturf.y) * SOUND_DEFAULT_DISTANCE_MULTIPLIER
song_played.y = (((currentturf.z - hearerturf.z) * 10 * SOUND_DEFAULT_DISTANCE_MULTIPLIER) + ((currentturf.z < hearerturf.z) ? -5 : 5))
if(pressure_factor < ONE_ATMOSPHERE)
song_played.volume = (min((targetfalloff * 50), 100) * max((pressure_factor - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 1))
song_played.echo[1] = (inrange ? 0 : -10000)
song_played.echo[3] = (inrange ? mixes : max(mixes, 0))
song_played.status = SOUND_UPDATE
SEND_SOUND(M, song_played)
CHECK_TICK
return
#undef JUKE_TRACK
#undef JUKE_CHANNEL
#undef JUKE_BOX
#undef JUKE_FALLOFF
#undef JUKE_SOUND
@@ -0,0 +1,11 @@
/**
* Persists polly messages across rounds
*/
/datum/controller/subsystem/persistence/LoadGamePersistence()
. = ..()
LoadPolly()
/datum/controller/subsystem/persistence/proc/LoadPolly()
for(var/mob/living/simple_animal/parrot/Polly/P in GLOB.alive_mob_list)
twitterize(P.speech_buffer, "polytalk")
break //Who's been duping the bird?!
@@ -1,11 +0,0 @@
/**
* Persists poly messages across rounds
*/
/datum/controller/subsystem/persistence/LoadGamePersistence()
. = ..()
LoadPoly()
/datum/controller/subsystem/persistence/proc/LoadPoly()
for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.alive_mob_list)
twitterize(P.speech_buffer, "polytalk")
break //Who's been duping the bird?!
+5 -12
View File
@@ -164,8 +164,8 @@ SUBSYSTEM_DEF(ticker)
to_chat(world, "<span class='boldnotice'>Welcome to [station_name()]!</span>")
send2chat("New round starting on [SSmapping.config.map_name]!", CONFIG_GET(string/chat_announce_new_game))
current_state = GAME_STATE_PREGAME
//Everyone who wants to be an observer is now spawned
create_observers()
SEND_SIGNAL(src, COMSIG_TICKER_ENTER_PREGAME)
fire()
if(GAME_STATE_PREGAME)
//lobby stats for statpanels
@@ -203,6 +203,7 @@ SUBSYSTEM_DEF(ticker)
for(var/client/C in SSvote.voting)
C << browse(null, "window=vote;can_close=0")
SSvote.reset()
SEND_SIGNAL(src, COMSIG_TICKER_ENTER_SETTING_UP)
current_state = GAME_STATE_SETTING_UP
Master.SetRunLevel(RUNLEVEL_SETUP)
if(start_immediately)
@@ -215,6 +216,7 @@ SUBSYSTEM_DEF(ticker)
start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10)
timeLeft = null
Master.SetRunLevel(RUNLEVEL_LOBBY)
SEND_SIGNAL(src, COMSIG_TICKER_ERROR_SETTING_UP)
if(GAME_STATE_PLAYING)
mode.process(wait * 0.1)
@@ -378,8 +380,6 @@ SUBSYSTEM_DEF(ticker)
LAZYOR(player.client.prefs.characters_joined_as, player.new_character.real_name)
else
stack_trace("WARNING: Either a player did not have a new_character, did not have a client, or did not have preferences. This is VERY bad.")
else
player.new_player_panel()
CHECK_TICK
/datum/controller/subsystem/ticker/proc/collect_minds()
@@ -612,7 +612,7 @@ SUBSYSTEM_DEF(ticker)
var/list/ded = SSblackbox.first_death
if(ded.len)
var/last_words = ded["last_words"] ? " Their last words were: \"[ded["last_words"]]\"" : ""
news_message += "\nNT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]"
news_message += "\nNT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died.\nTheir name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]"
else
news_message += "\nNT Sanctioned Psykers proudly confirm reports that nobody died this shift!"
@@ -633,13 +633,6 @@ SUBSYSTEM_DEF(ticker)
else
timeLeft = newtime
//Everyone who wanted to be an observer gets made one now
/datum/controller/subsystem/ticker/proc/create_observers()
for(var/mob/dead/new_player/player in GLOB.player_list)
if(player.ready == PLAYER_READY_TO_OBSERVE && player.mind)
//Break chain since this has a sleep input in it
addtimer(CALLBACK(player, /mob/dead/new_player.proc/make_me_an_observer), 1)
/datum/controller/subsystem/ticker/proc/load_mode()
var/mode = trim(file2text("data/mode.txt"))
if(mode)
+10 -7
View File
@@ -10,7 +10,7 @@ SUBSYSTEM_DEF(title)
/datum/controller/subsystem/title/Initialize()
if(file_path && icon)
return ..()
return
if(fexists("data/previous_title.dat"))
var/previous_path = file2text("data/previous_title.dat")
@@ -31,13 +31,16 @@ SUBSYSTEM_DEF(title)
if(length(title_screens))
file_path = "[global.config.directory]/title_screens/images/[pick(title_screens)]"
if(!file_path || !fexists(file_path))
file_path = "icons/default_title.dmi"
if(!file_path)
file_path = "icons/runtime/default_title.dmi"
if(fexists(file_path))
icon = new(fcopy_rsc(file_path))
if(splash_turf)
splash_turf.icon = icon
ASSERT(fexists(file_path))
icon = new(fcopy_rsc(file_path))
if(splash_turf)
splash_turf.icon = icon
splash_turf.handle_generic_titlescreen_sizes()
return ..()
+1 -1
View File
@@ -169,7 +169,7 @@ SUBSYSTEM_DEF(traumas)
/obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver,
/obj/item/gun/ballistic/automatic/shotgun/bulldog, /obj/item/gun/ballistic/automatic/c20r, /obj/item/gun/ballistic/automatic/m90, /obj/item/gun/ballistic/automatic/l6_saw, /obj/item/storage/belt/grenade/full, /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate, /obj/item/gun/energy/kinetic_accelerator/crossbow,
/obj/item/melee/transforming/energy/sword/saber, /obj/item/dualsaber, /obj/item/melee/powerfist, /obj/item/storage/box/syndie_kit, /obj/item/grenade/spawnergrenade/manhacks, /obj/item/grenade/chem_grenade/bioterrorfoam, /obj/item/reagent_containers/spray/chemsprayer/bioterror, /obj/item/ammo_box/magazine/m10mm,
/obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm195x129, /obj/item/antag_spawner/nuke_ops, /obj/vehicle/sealed/mecha/combat/gygax/dark, /obj/vehicle/sealed/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate,
/obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm712x82, /obj/item/antag_spawner/nuke_ops, /obj/vehicle/sealed/mecha/combat/gygax/dark, /obj/vehicle/sealed/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate,
/obj/item/cartridge/virus/frame, /obj/item/chameleon, /obj/item/storage/box/syndie_kit/cutouts, /obj/item/clothing/suit/space/hardsuit/syndi, /obj/item/card/emag, /obj/item/storage/toolbox/syndicate, /obj/item/storage/book/bible/syndicate, /obj/item/encryptionkey/binary, /obj/item/encryptionkey/syndicate, /obj/item/aiModule/syndicate,
/obj/item/clothing/shoes/magboots/syndie, /obj/item/powersink, /obj/item/sbeacondrop, /obj/item/sbeacondrop/bomb, /obj/item/syndicatedetonator, /obj/item/shield/energy, /obj/item/assault_pod, /obj/item/slimepotion/slime/sentience/nuclear, /obj/item/stack/telecrystal, /obj/item/jammer, /obj/item/codespeak_manual/unlimited,
/obj/item/toy/cards/deck/syndicate, /obj/item/storage/secure/briefcase/syndie, /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/toy/syndicateballoon, /obj/item/clothing/gloves/fingerless/pugilist/rapid, /obj/item/paper/fluff/ruins/thederelict/syndie_mission, /obj/item/organ/cyberimp/eyes/hud/security/syndicate, /obj/item/clothing/head/HoS/syndicate,
+2 -2
View File
@@ -320,11 +320,11 @@ SUBSYSTEM_DEF(vote)
admintext += "\nIt should be noted that this is not a raw tally of votes but rather the median score plus a tiebreaker!"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
admintext += "\n<b>[choices[i]]:</b> [votes]"
admintext += "\n<b>[choices[i]]:</b> [votes ? votes : "0"]" //This is raw data, but the raw data is null by default. If ya don't compensate for it, then it'll look weird!
else
for(var/i=1,i<=scores.len,i++)
var/score = scores[scores[i]]
admintext += "\n<b>[scores[i]]:</b> [score]"
admintext += "\n<b>[scores[i]]:</b> [score ? score : "0"]"
message_admins(admintext)
return .
+150
View File
@@ -0,0 +1,150 @@
//Datums for barks and bark accessories
/datum/bark
var/name = "Default"
var/id = "Default"
var/soundpath //Path for the actual sound file used for the bark
// Pitch vars. The actual range for a bark is [(pitch - (maxvariance*0.5)) to (pitch + (maxvariance*0.5))]
// Make absolutely sure to take variance into account when curating a sound for bark purposes.
var/minpitch = BARK_DEFAULT_MINPITCH
var/maxpitch = BARK_DEFAULT_MAXPITCH
var/minvariance = BARK_DEFAULT_MINVARY
var/maxvariance = BARK_DEFAULT_MAXVARY
// Speed vars. Speed determines the number of characters required for each bark, with lower speeds being faster with higher bark density
var/minspeed = BARK_DEFAULT_MINSPEED
var/maxspeed = BARK_DEFAULT_MAXSPEED
// Visibility vars. Regardless of what's set below, these can still be obtained via adminbus and genetics. Rule of fun.
var/list/ckeys_allowed
var/ignore = FALSE //Controls whether or not this can be chosen in chargen
var/allow_random = FALSE //Allows chargen randomization to use this. This is mainly to restrict the pool to sounds that fit well for most characters
// So the basic jist of the sound design here: We make use primarily of shorter instrument samples for barks. We would've went with animalese instead, but doing so would've involved quite a bit of overhead to saycode.
// Short instrument samples tend to sound surprisingly nice for barks, being able to be played in rapid succession without being outright obnoxious.
// It isn't just instruments that work well here, however. Anything that works well as a stab? Short attack, no sustain, a decent amount of release? Also works extremely well for barks.
/datum/bark/mutedc2
name = "Muted String (Low)"
id = "mutedc2"
soundpath = 'sound/instruments/synthesis_samples/guitar/crisis_muted/C2.ogg'
allow_random = TRUE
/datum/bark/mutedc3
name = "Muted String (Medium)"
id = "mutedc3"
soundpath = 'sound/instruments/synthesis_samples/guitar/crisis_muted/C3.ogg'
allow_random = TRUE
/datum/bark/mutedc4
name = "Muted String (High)"
id = "mutedc4"
soundpath = 'sound/instruments/synthesis_samples/guitar/crisis_muted/C4.ogg'
allow_random = TRUE
/datum/bark/banjoc3
name = "Banjo (Medium)"
id = "banjoc3"
soundpath = 'sound/instruments/banjo/Cn3.ogg'
allow_random = TRUE
/datum/bark/banjoc4
name = "Banjo (High)"
id = "banjoc4"
soundpath = 'sound/instruments/banjo/Cn4.ogg'
allow_random = TRUE
/datum/bark/squeaky
name = "Squeaky"
id = "squeak"
soundpath = 'sound/items/toysqueak1.ogg'
maxspeed = 4
/datum/bark/beep
name = "Beepy"
id = "beep"
soundpath = 'sound/machines/terminal_select.ogg'
maxpitch = 1 //Bringing the pitch higher just hurts your ears :<
maxspeed = 4 //This soundbyte's too short for larger speeds to not sound awkward
/datum/bark/chitter
name = "Chittery"
id = "chitter"
minspeed = 4 //Even with the sound being replaced with a unique, shorter sound, this is still a little too long for higher speeds
soundpath = 'sound/voice/barks/chitter.ogg'
/datum/bark/synthetic_grunt
name = "Synthetic (Grunt)"
id = "synthgrunt"
soundpath = 'sound/misc/bloop.ogg'
/datum/bark/synthetic
name = "Synthetic (Normal)"
id = "synth"
soundpath = 'sound/machines/uplinkerror.ogg'
/datum/bark/bullet
name = "Windy"
id = "bullet"
maxpitch = 1.6 //This works well with higher pitches!
soundpath = 'sound/weapons/bulletflyby.ogg' //This works... Surprisingly well as a bark? It's neat!
/datum/bark/coggers
name = "Brassy"
id = "coggers"
soundpath = 'sound/machines/clockcult/integration_cog_install.ogg' //Yet another unexpectedly good bark sound
// Genetics-only/admin-only sounds. These either clash hard with the audio design of the above sounds, or have some other form of audio design issue, but aren't *too* awful as a sometimes thing.
// Rule of fun very much applies to this section. Audio design is extremely important for the above section, but down here? No gods, no masters, pure anarchy.
// The min/max variables simply don't apply to these, as only chargen cares about them. As such, there's no need to define those.
/datum/bark/bikehorn
name = "Bikehorn"
id = "horn"
soundpath = 'sound/instruments/bikehorn/Cn4.ogg'
ignore = TRUE // This is an unusually quiet sound.
/datum/bark/bwoink
name = "Bwoink"
id = "bwoink"
soundpath = 'sound/effects/adminhelp.ogg'
ignore = TRUE // Emergent heart attack generation
/datum/bark/merp
name = "Merp"
id = "merp"
soundpath = 'modular_citadel/sound/voice/merp.ogg'
ignore = TRUE
/datum/bark/bark
name = "Bark"
id = "bark"
soundpath = 'modular_citadel/sound/voice/bark1.ogg'
ignore = TRUE
/datum/bark/nya
name = "Nya"
id = "nya"
soundpath = 'modular_citadel/sound/voice/nya.ogg'
ignore = TRUE
/datum/bark/moff
name = "Moff"
id = "moff"
soundpath = 'modular_citadel/sound/voice/mothsqueak.ogg'
ignore = TRUE
/datum/bark/weh
name = "Weh"
id = "weh"
soundpath = 'modular_citadel/sound/voice/weh.ogg'
ignore = TRUE
/datum/bark/honk
name = "Annoying Honk"
id = "honk"
soundpath = 'sound/creatures/goose1.ogg'
ignore = TRUE
@@ -123,7 +123,7 @@
trauma = _trauma
return ..()
/mob/living/split_personality/BiologicalLife(seconds, times_fired)
/mob/living/split_personality/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(QDELETED(body))
+1 -4
View File
@@ -164,6 +164,7 @@
message.maptext_height = mheight
message.maptext_x = (CHAT_MESSAGE_WIDTH - owner.bound_width) * -0.5
message.maptext = MAPTEXT(complete_text)
message.pixel_x = -owner.pixel_x //Dogborgs and other wide boys have a pixel offset. This accounts for that
// View the message
LAZYADDASSOC(owned_by.seen_messages, message_loc, src)
@@ -174,10 +175,6 @@
scheduled_destruction = world.time + (lifespan - CHAT_MESSAGE_EOL_FADE)
enter_subsystem()
var/mob/living/silicon/robot/R = target
if(iscyborg(R))
if((R.module.dogborg == TRUE || R.dogborg == TRUE) && isturf(R.loc)) //I hate whoever that thought that putting two types of dogborg that don't even sync up properly was good
message.pixel_x = 16
/**
* Applies final animations to overlay CHAT_MESSAGE_EOL_FADE deciseconds prior to message deletion
+1 -1
View File
@@ -32,7 +32,7 @@
var/atom/movable/A = parent
switch(rand(1, 3))
if(1)
A.do_jiggle(45 + rand(-10, 10) * bouncy_mod, 14)
A.do_jiggle(25 + rand(-5, 5) * bouncy_mod, 14)
if(2)
var/min_b = 0.6/bouncy_mod
var/max_b = 1.2 * bouncy_mod
@@ -39,7 +39,7 @@
name = "tea cup"
desc = "A glass cup made for sipping tea!"
icon = 'icons/obj/glass_ware.dmi'
icon_state = "tea_plate"
icon_state = "tea_cup"
//////////////////////Chem Disk/////////////////////
//Two Steps //
@@ -145,7 +145,7 @@
qdel(src)
/obj/item/glasswork/glass_base/glass_lens_part5
name = "unpolished glass lens"
name = "unpolished glass (lens)"
desc = "An unpolished glass lens. It needs to be polished with some dry cloth."
icon = 'icons/obj/glass_ware.dmi'
icon_state = "glass_optics"
@@ -159,7 +159,7 @@
qdel(src)
/obj/item/glasswork/glass_base/glass_lens_part6
name = "unrefined glass lens"
name = "unrefined glass (lens)"
desc = "A polished glass lens. It needs to be refined with some sandstone."
icon = 'icons/obj/glass_ware.dmi'
icon_state = "glass_optics"
@@ -179,7 +179,7 @@
/obj/item/glasswork/glass_base/spouty
name = "Glass fodder sheet (spout)"
desc = "A set of glass sheets set aside for glass working. This one is ideal for a spouty flask. It needs to heated with something very hot."
desc = "A set of glass sheets set aside for glass working. This one is ideal for a spouty flask. It needs to be cut with some glassworking tools."
next_step = /obj/item/glasswork/glass_base/spouty_part2
/obj/item/glasswork/glass_base/spouty/attackby(obj/item/I, mob/user, params)
@@ -413,7 +413,7 @@
qdel(src)
qdel(I)
/obj/item/glasswork/glass_base/tea_cupe2
/obj/item/glasswork/glass_base/tea_cup2
name = "glassblowing rod (tea cup)"
desc = "A hollow metal rod made for blowing glass. There is a blob of shapen glass at the end of it that needs to be cut off with some glassworking tools."
icon_state = "blowing_rods_inuse"
@@ -433,7 +433,7 @@
icon_state = "glass_base_half"
next_step = /obj/item/glasswork/glass_base/tea_cup4
/obj/item/glasswork/glass_base/cup3/attackby(obj/item/I, mob/user, params)
/obj/item/glasswork/glass_base/tea_cup3/attackby(obj/item/I, mob/user, params)
..()
if(istype(I, /obj/item/stack/sheet/cloth))
if(do_after(user,10, target = src))
@@ -446,7 +446,7 @@
icon_state = "glass_base_half"
next_step = /obj/item/tea_cup
/obj/item/glasswork/glass_base/cup4/attackby(obj/item/I, mob/user, params)
/obj/item/glasswork/glass_base/tea_cup4/attackby(obj/item/I, mob/user, params)
..()
if(istype(I, /obj/item/stack/sheet/glass))
if(do_after(user,10, target = src))
+2 -2
View File
@@ -346,9 +346,9 @@
/datum/component/embedded/proc/examineTurf(datum/source, mob/user, list/examine_list)
if(harmful)
examine_list += "\t <a href='?src=[REF(src)];embedded_object=[REF(weapon)]' class='warning'>There is \a [weapon] embedded in [parent]!</a>"
examine_list += "<a href='?src=[REF(src)];embedded_object=[REF(weapon)]' class='warning'>There is \a [weapon] embedded in [parent]!</a>"
else
examine_list += "\t <a href='?src=[REF(src)];embedded_object=[REF(weapon)]' class='warning'>There is \a [weapon] stuck to [parent]!</a>"
examine_list += "<a href='?src=[REF(src)];embedded_object=[REF(weapon)]' class='warning'>There is \a [weapon] stuck to [parent]!</a>"
/// Someone is ripping out the item from the turf by hand
+2 -2
View File
@@ -61,7 +61,7 @@
if(identification_method_flags & ID_COMPONENT_EFFECT_NO_ACTIONS)
return COMPONENT_NO_GRANT_ACTIONS
/datum/component/identification/proc/check_knowledge(mob/user)
/datum/component/identification/proc/check_knowledge(datum/source, mob/user)
return ID_COMPONENT_KNOWLEDGE_NONE
/datum/component/identification/proc/on_identify(mob/user)
@@ -83,7 +83,7 @@
*/
/datum/component/identification/syndicate
/datum/component/identification/syndicate/check_knowledge(mob/user)
/datum/component/identification/syndicate/check_knowledge(datum/source, mob/user)
. = ..()
if(user?.mind?.has_antag_datum(/datum/antagonist/traitor))
. = max(., ID_COMPONENT_KNOWLEDGE_FULL)
+12 -11
View File
@@ -50,7 +50,7 @@
STOP_PROCESSING(SSobj, src)
/datum/component/mood/proc/print_mood(mob/user)
var/msg = "<span class='info'>*---------*\n<EM>Your current mood</EM>\n"
var/msg = "<blockquote class='[sanity > SANITY_DISTURBED ? "nicegreen" : "warning"]'><span class='info'><EM>Your current mood</EM></span>\n"
msg += "<span class='notice'>My mental status: </span>" //Long term
switch(sanity)
if(SANITY_GREAT to INFINITY)
@@ -69,23 +69,23 @@
msg += "<span class='notice'>My current mood: </span>" //Short term
switch(mood_level)
if(1)
msg += "<span class='boldwarning'>I wish I was dead!<span>\n"
msg += "<span class='boldwarning'>I wish I was dead!</span>\n"
if(2)
msg += "<span class='boldwarning'>I feel terrible...<span>\n"
msg += "<span class='boldwarning'>I feel terrible...</span>\n"
if(3)
msg += "<span class='boldwarning'>I feel very upset.<span>\n"
msg += "<span class='boldwarning'>I feel very upset.</span>\n"
if(4)
msg += "<span class='boldwarning'>I'm a bit sad.<span>\n"
msg += "<span class='boldwarning'>I'm a bit sad.</span>\n"
if(5)
msg += "<span class='nicegreen'>I'm alright.<span>\n"
msg += "<span class='nicegreen'>I'm alright.</span>\n"
if(6)
msg += "<span class='nicegreen'>I feel pretty okay.<span>\n"
msg += "<span class='nicegreen'>I feel pretty okay.</span>\n"
if(7)
msg += "<span class='nicegreen'>I feel pretty good.<span>\n"
msg += "<span class='nicegreen'>I feel pretty good.</span>\n"
if(8)
msg += "<span class='nicegreen'>I feel amazing!<span>\n"
msg += "<span class='nicegreen'>I feel amazing!</span>\n"
if(9)
msg += "<span class='nicegreen'>I love life!<span>\n"
msg += "<span class='nicegreen'>I love life!</span>\n"
msg += "<span class='notice'>Moodlets:\n</span>"//All moodlets
if(mood_events.len)
@@ -93,7 +93,8 @@
var/datum/mood_event/event = mood_events[i]
msg += event.description
else
msg += "<span class='nicegreen'>I don't have much of a reaction to anything right now.<span>\n"
msg += "<span class='nicegreen'>I don't have much of a reaction to anything right now.</span>\n"
msg += "</blockquote>"
to_chat(user || parent, msg)
///Called after moodevent/s have been added/removed.
+5 -4
View File
@@ -431,25 +431,26 @@
if(M.incapacitated() || !M.canUseStorage())
return
var/atom/A = parent
A.add_fingerprint(M)
// this must come before the screen objects only block, dunno why it wasn't before
if(over_object == M)
user_show_to_mob(M, trigger_on_found = TRUE)
if(isrevenant(M))
INVOKE_ASYNC(GLOBAL_PROC, .proc/RevenantThrow, over_object, M, source)
return
if(check_locked(null, M) || !M.CanReach(A) || (!M.CanReach(over_object) && !istype(over_object, /atom/movable/screen)))
return
playsound(A, "rustle", 50, TRUE, -5)
A.do_jiggle()
A.add_fingerprint(M)
if(!istype(over_object, /atom/movable/screen))
INVOKE_ASYNC(src, .proc/dump_content_at, over_object, M)
return
if(A.loc != M)
return
playsound(A, "rustle", 50, TRUE, -5)
A.do_jiggle()
if(istype(over_object, /atom/movable/screen/inventory/hand))
var/atom/movable/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(A, H.held_index)
return
A.add_fingerprint(M)
/datum/component/storage/proc/user_show_to_mob(mob/M, force = FALSE, trigger_on_found = FALSE)
var/atom/A = parent
+4
View File
@@ -63,6 +63,8 @@
if(QDELETED(O))
continue
var/atom/movable/screen/storage/item_holder/D = new(null, src, O)
// SNOWFLAKE: make O opaque too, pending storage rewrite
O.mouse_opacity = MOUSE_OPACITY_OPAQUE
D.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip"
D.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]"
O.maptext = ""
@@ -138,6 +140,8 @@
I = i
var/percent = percentage_by_item[I]
var/atom/movable/screen/storage/volumetric_box/center/B = new /atom/movable/screen/storage/volumetric_box/center(null, src, I)
// SNOWFLAKE: force it to icon until we unfuck storage/click passing
I.mouse_opacity = MOUSE_OPACITY_ICON
var/pixels_to_use = overrun? MINIMUM_PIXELS_PER_ITEM : max(using_horizontal_pixels * percent, MINIMUM_PIXELS_PER_ITEM)
var/addrow = FALSE
if(CEILING(pixels_to_use, 1) >= FLOOR(horizontal_pixels - current_pixel - VOLUMETRIC_STORAGE_EDGE_PADDING, 1))
+1 -1
View File
@@ -84,9 +84,9 @@
if(VR)
VR.level_below = src
level_above = VR
M.transfer_ckey(vr_M, FALSE)
mastermind = M.mind
mastermind.current.audiovisual_redirect = parent
M.transfer_ckey(vr_M, FALSE)
RegisterSignal(mastermind, COMSIG_PRE_MIND_TRANSFER, .proc/switch_player)
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING), .proc/game_over)
RegisterSignal(M, COMSIG_MOB_PRE_PLAYER_CHANGE, .proc/player_hijacked)
+1 -1
View File
@@ -13,7 +13,7 @@
severity = DISEASE_SEVERITY_MEDIUM
infectable_biotypes = MOB_ORGANIC|MOB_UNDEAD|MOB_ROBOTIC|MOB_MINERAL
bypasses_immunity = TRUE //2spook
var/mob/living/simple_animal/parrot/Poly/ghost/parrot
var/mob/living/simple_animal/parrot/Polly/ghost/parrot
/datum/disease/parrot_possession/stage_act()
..()
+27 -10
View File
@@ -77,6 +77,7 @@
new_dna.species = new species.type
new_dna.species.say_mod = species.say_mod
new_dna.species.exotic_blood_color = species.exotic_blood_color //it can change from the default value
new_dna.species.exotic_blood_blend_mode = species.exotic_blood_blend_mode
new_dna.species.eye_type = species.eye_type
new_dna.species.limbs_id = species.limbs_id || species.id
new_dna.real_name = real_name
@@ -137,9 +138,9 @@
L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)
L[DNA_LEFT_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.left_eye_color)
L[DNA_RIGHT_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.right_eye_color)
L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"], 6)
L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"], 6)
L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"], 6)
L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"])
L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"])
L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"])
if(!GLOB.mam_tails_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list)
L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
@@ -152,6 +153,10 @@
if(!GLOB.taur_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/taur, GLOB.taur_list)
L[DNA_TAUR_BLOCK] = construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len)
L[DNA_BARK_SOUND_BLOCK] = construct_block(GLOB.bark_list.Find(H.vocal_bark_id), GLOB.bark_list.len)
L[DNA_BARK_SPEED_BLOCK] = construct_block(H.vocal_speed * 4, 16)
L[DNA_BARK_PITCH_BLOCK] = construct_block(H.vocal_pitch * 30, 48)
L[DNA_BARK_VARIANCE_BLOCK] = construct_block(H.vocal_pitch_range * 48, 48)
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
if(L[i])
@@ -247,19 +252,19 @@
if(DNA_HAIR_STYLE_BLOCK)
setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len))
if(DNA_COLOR_ONE_BLOCK)
sanitize_hexcolor(features["mcolor"], 6)
setblock(uni_identity, blocknumber, sanitize_hexcolor(features["mcolor"]))
if(DNA_COLOR_TWO_BLOCK)
sanitize_hexcolor(features["mcolor2"], 6)
setblock(uni_identity, blocknumber, sanitize_hexcolor(features["mcolor2"]))
if(DNA_COLOR_THREE_BLOCK)
sanitize_hexcolor(features["mcolor3"], 6)
setblock(uni_identity, blocknumber, sanitize_hexcolor(features["mcolor3"]))
if(DNA_MUTANTTAIL_BLOCK)
construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
setblock(uni_identity, blocknumber, construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len))
if(DNA_MUTANTEAR_BLOCK)
construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len)
setblock(uni_identity, blocknumber, construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len))
if(DNA_MUTANTMARKING_BLOCK)
construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len)
setblock(uni_identity, blocknumber, construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len))
if(DNA_TAUR_BLOCK)
construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len)
setblock(uni_identity, blocknumber, construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len))
if(species.mutant_bodyparts["taur"] && ishuman(holder))
var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]]
switch(T?.taur_mode)
@@ -271,6 +276,14 @@
H.physiology.footstep_type = FOOTSTEP_MOB_CRAWL
else
H.physiology.footstep_type = null
if(DNA_BARK_SOUND_BLOCK)
setblock(uni_identity, blocknumber, construct_block(GLOB.bark_list.Find(H.vocal_bark_id), GLOB.bark_list.len))
if(DNA_BARK_SPEED_BLOCK)
setblock(uni_identity, blocknumber, construct_block(H.vocal_speed * 4, 16))
if(DNA_BARK_PITCH_BLOCK)
setblock(uni_identity, blocknumber, construct_block(H.vocal_pitch * 30, 48))
if(DNA_BARK_VARIANCE_BLOCK)
setblock(uni_identity, blocknumber, construct_block(H.vocal_pitch_range * 48, 48))
//Please use add_mutation or activate_mutation instead
/datum/dna/proc/force_give(datum/mutation/human/HM)
@@ -490,6 +503,10 @@
update_body_parts()
if(mutations_overlay_update)
update_mutations_overlay()
set_bark(GLOB.bark_list[deconstruct_block(getblock(structure, DNA_BARK_SOUND_BLOCK), GLOB.bark_list.len)])
vocal_speed = (deconstruct_block(getblock(structure, DNA_BARK_SPEED_BLOCK), 16) / 4)
vocal_pitch = (deconstruct_block(getblock(structure, DNA_BARK_PITCH_BLOCK), 48) / 30)
vocal_pitch_range = (deconstruct_block(getblock(structure, DNA_BARK_VARIANCE_BLOCK), 48) / 48)
/mob/proc/domutcheck()
+3 -3
View File
@@ -76,10 +76,10 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
if(examine_full_view)
examine_list += "[msg]"
return
if(length_char(msg) <= 40)
if(length_char(msg) <= MAX_FLAVOR_PREVIEW_LEN)
examine_list += "<span class='notice'>[msg]</span>"
else
examine_list += "<span class='notice'>[copytext_char(msg, 1, 37)]... <a href='?src=[REF(src)];show_flavor=[REF(target)]'>More...</span></a>"
examine_list += "<span class='notice'>[copytext_char(msg, 1, (MAX_FLAVOR_PREVIEW_LEN - 3))]... <a href='?src=[REF(src)];show_flavor=[REF(target)]'>More...</span></a>"
/datum/element/flavor_text/Topic(href, href_list)
. = ..()
@@ -199,7 +199,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
if(ismob(target))
add_verb(target, /mob/proc/set_pose)
/datum/element/flavor_Text/carbon/temporary/Detach(datum/source, force)
/datum/element/flavor_text/carbon/temporary/Detach(datum/source, force)
. = ..()
if(ismob(source))
remove_verb(source, /mob/proc/set_pose)
+18 -7
View File
@@ -136,13 +136,19 @@
if (isnull(item))
return FALSE
source.visible_message(
span_warning("[user] tries to remove [source]'s [item.name]."),
span_userdanger("[user] tries to remove your [item.name]."),
ignored_mobs = user,
)
var/strip_silence
var/obj/item/clothing/gloves/gloves = user.get_item_by_slot(ITEM_SLOT_GLOVES)
if(istype(gloves))
strip_silence = gloves.strip_silence
to_chat(user, span_danger("You try to remove [source]'s [item]..."))
if(!strip_silence)
source.visible_message(
span_warning("[user] tries to remove [source]'s [item.name]."),
span_userdanger("[user] tries to remove your [item.name]."),
ignored_mobs = user,
)
to_chat(user, strip_silence ? span_danger("You try to remove [source]'s [item]...") : span_notice("You try to remove [source]'s [item]..."))
user.log_message("[key_name(source)] is being stripped of [item] by [key_name(user)]", LOG_ATTACK, color="red")
source.log_message("[key_name(source)] is being stripped of [item] by [key_name(user)]", LOG_VICTIM, color="red", log_globally=FALSE)
item.add_fingerprint(source)
@@ -284,7 +290,12 @@
/// A utility function for `/datum/strippable_item`s to start unequipping an item from a mob.
/proc/start_unequip_mob(obj/item/item, mob/source, mob/user, strip_delay)
if (!do_mob(user, source, strip_delay || item.strip_delay, ignorehelditem = TRUE))
var/strip_mod = 1
var/obj/item/clothing/gloves/gloves = user.get_item_by_slot(ITEM_SLOT_GLOVES)
if(istype(gloves))
strip_mod = gloves.strip_mod
if (!do_mob(user, source, (strip_delay || item.strip_delay) / strip_mod, ignorehelditem = TRUE))
return FALSE
return TRUE
+2 -1
View File
@@ -10,7 +10,7 @@
// And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
// Helper similar to image()
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE, color = "#FFFFFF")
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE, color = "#FFFFFF", blend_mode = BLEND_DEFAULT)
var/mutable_appearance/MA = new()
MA.icon = icon
MA.icon_state = icon_state
@@ -19,5 +19,6 @@
MA.alpha = alpha
MA.appearance_flags |= appearance_flags
MA.color = color
MA.blend_mode = blend_mode
return MA
+11
View File
@@ -120,6 +120,17 @@
return FALSE
return TRUE
/datum/saymode/statusdisplay
key = "q"
mode = MODE_STATUSDISPLAY
/datum/saymode/statusdisplay/handle_message(mob/living/user, message, datum/language/language)
if(isAI(user))
var/mob/living/silicon/ai/AI = user
AI.statusdisplay_talk(message, language)
return FALSE
return TRUE
/datum/saymode/monkey
key = "k"
mode = MODE_MONKEY
+5 -2
View File
@@ -14,6 +14,7 @@
/// should we immediately call on_spawn or add a timer to trigger
var/on_spawn_immediate = TRUE
var/mob/living/quirk_holder
var/processing_quirk = FALSE
/datum/quirk/New(mob/living/quirk_mob, spawn_effects)
if(!quirk_mob || (human_only && !ishuman(quirk_mob)) || quirk_mob.has_quirk(type))
@@ -25,7 +26,8 @@
quirk_holder.roundstart_quirks += src
if(mob_trait)
ADD_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
START_PROCESSING(SSquirks, src)
if(processing_quirk)
START_PROCESSING(SSquirks, src)
add()
if(spawn_effects)
if(on_spawn_immediate)
@@ -35,7 +37,8 @@
addtimer(CALLBACK(src, .proc/post_add), 30)
/datum/quirk/Destroy()
STOP_PROCESSING(SSquirks, src)
if(processing_quirk)
STOP_PROCESSING(SSquirks, src)
remove()
if(quirk_holder)
to_chat(quirk_holder, lose_text)
+1
View File
@@ -72,6 +72,7 @@
mob_trait = TRAIT_JOLLY
mood_quirk = TRUE
medical_record_text = "Patient demonstrates constant euthymia irregular for environment. It's a bit much, to be honest."
processing_quirk = TRUE
/datum/quirk/jolly/on_process()
if(prob(0.05))
+83 -17
View File
@@ -25,6 +25,7 @@
lose_text = "<span class='notice'>You no longer feel depressed.</span>" //if only it were that easy!
medical_record_text = "Patient has a severe mood disorder, causing them to experience acute episodes of depression."
mood_quirk = TRUE
processing_quirk = TRUE
/datum/quirk/depression/on_process()
if(prob(0.05))
@@ -38,6 +39,7 @@
medical_record_text = "Patient demonstrates an unnatural attachment to a family heirloom."
var/obj/item/heirloom
var/where
processing_quirk = TRUE
GLOBAL_LIST_EMPTY(family_heirlooms)
@@ -102,6 +104,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
gain_text = "<span class='danger'>You feel smooth.</span>"
lose_text = "<span class='notice'>You feel wrinkled again.</span>"
medical_record_text = "Patient has a tumor in their brain that is slowly driving them to brain death."
processing_quirk = TRUE
/datum/quirk/brainproblems/on_process()
quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2)
@@ -129,25 +132,38 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
value = -1
medical_record_text = "Patient demonstrates a fear of the dark. (Seriously?)"
/datum/quirk/nyctophobia/on_process()
var/mob/living/carbon/human/H = quirk_holder
if(H.dna.species.id in list("shadow", "nightmare"))
return //we're tied with the dark, so we don't get scared of it; don't cleanse outright to avoid cheese
var/turf/T = get_turf(quirk_holder)
var/lums = T.get_lumcount()
if(lums <= 0.2)
if(quirk_holder.m_intent == MOVE_INTENT_RUN)
addtimer(CALLBACK(src, .proc/recheck),2) //0.2 seconds of being in the dark
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
else
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
/datum/quirk/nyctophobia/add()
RegisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
/datum/quirk/nyctophobia/proc/recheck()
var/turf/T = get_turf(quirk_holder)
var/lums = T.get_lumcount()
if(lums <= 0.2) //check again, did they remain in the dark for 0.2 seconds?
to_chat(quirk_holder, "<span class='warning'>Easy, easy, take it slow... you're in the dark...</span>")
/datum/quirk/nyctophobia/remove()
UnregisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED)
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
/// Called when the quirk holder moves. Updates the quirk holder's mood.
/datum/quirk/nyctophobia/proc/on_holder_moved(mob/living/source, atom/old_loc, dir, forced)
if(quirk_holder.stat != CONSCIOUS || quirk_holder.IsSleeping() || quirk_holder.IsUnconscious())
return
var/mob/living/carbon/human/human_holder = quirk_holder
if(human_holder.dna?.species.id in list(SPECIES_SHADOW, SPECIES_NIGHTMARE))
return
if((human_holder.sight & SEE_TURFS) == SEE_TURFS)
return
var/turf/holder_turf = get_turf(quirk_holder)
var/lums = holder_turf.get_lumcount()
if(lums > 0.2)
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
return
if(quirk_holder.m_intent == MOVE_INTENT_RUN)
to_chat(quirk_holder, span_warning("Easy, easy, take it slow... you're in the dark..."))
quirk_holder.toggle_move_intent()
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
/datum/quirk/lightless
name = "Light Sensitivity"
@@ -157,6 +173,36 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
lose_text = "<span class='notice'>Enlightening.</span>"
medical_record_text = "Despite my warnings, the patient refuses turn on the lights, only to end up rolling down a full flight of stairs and into the cellar."
/datum/quirk/lightless/add()
RegisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
/datum/quirk/lightless/remove()
UnregisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED)
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "brightlight")
/datum/quirk/lightless/proc/on_holder_moved(mob/living/source, atom/old_loc, dir, forced)
if(quirk_holder.stat != CONSCIOUS || quirk_holder.IsSleeping() || quirk_holder.IsUnconscious())
return
var/mob/living/carbon/human/human_holder = quirk_holder
if(human_holder.dna?.species.id in list(SPECIES_SHADOW, SPECIES_NIGHTMARE))
return
if((human_holder.sight & SEE_TURFS) == SEE_TURFS)
return
var/turf/holder_turf = get_turf(quirk_holder)
var/lums = holder_turf.get_lumcount()
if(lums < 0.8)
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "brightlight")
return
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "brightlight", /datum/mood_event/brightlight)
/datum/quirk/lightless/on_process()
var/turf/T = get_turf(quirk_holder)
var/lums = T.get_lumcount()
@@ -236,6 +282,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
gain_text = "<span class='userdanger'>...</span>"
lose_text = "<span class='notice'>You feel in tune with the world again.</span>"
medical_record_text = "Patient suffers from acute Reality Dissociation Syndrome and experiences vivid hallucinations."
processing_quirk = TRUE
/datum/quirk/insanity/on_process()
if(quirk_holder.reagents.has_reagent(/datum/reagent/toxin/mindbreaker))
@@ -261,6 +308,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
lose_text = "<span class='notice'>You feel easier about talking again.</span>" //if only it were that easy!
medical_record_text = "Patient is usually anxious in social encounters and prefers to avoid them."
var/dumb_thing = TRUE
processing_quirk = TRUE
/datum/quirk/social_anxiety/add()
RegisterSignal(quirk_holder, COMSIG_MOB_EYECONTACT, .proc/eye_contact)
@@ -425,3 +473,21 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
gain_text = "<span class='notice'>You can't smell anything!</span>"
lose_text = "<span class='notice'>You can smell again!</span>"
medical_record_text = "Patient suffers from anosmia and is incapable of smelling gases or particulates."
/datum/quirk/paper_skin
name = "Paper Skin"
desc = "Your flesh is weaker, resulting in receiving cuts more easily."
value = -1
mob_trait = TRAIT_PAPER_SKIN
gain_text = "<span class='notice'>Your flesh feels weak!</span>"
lose_text = "<span class='notice'>Your flesh feels more durable!</span>"
medical_record_text = "Patient suffers from weak flesh, resulting in them receiving cuts far more easily."
/datum/quirk/glass_bones
name = "Glass Bones"
desc = "Your bones are far more brittle, and more vulnerable to breakage."
value = -1
mob_trait = TRAIT_GLASS_BONES
gain_text = "<span class='notice'>Your bones feels weak!</span>"
lose_text = "<span class='notice'>Your bones feels more durable!</span>"
medical_record_text = "Patient suffers from brittle bones, resulting in them receiving breakages far more easily."
+1 -1
View File
@@ -118,7 +118,7 @@
if(WOUND_SEVERITY_LOSS)
msg = "[victim.p_their(TRUE)] [limb.name] [description]." // different format
msg = "<span class='notice'><i><b>[msg]</b></i></span>"
return "\t[msg]"
return "[msg]"
/// Whether a scar can currently be seen by the viewer
/datum/scar/proc/is_visible(mob/viewer)
+1 -1
View File
@@ -167,7 +167,7 @@
if(WOUND_INFECTION_SEPTIC to INFINITY)
. += "Infection Level: <span class='deadsay'>LOSS IMMINENT</span>\n"
if(infestation > sanitization)
. += "\tSurgical debridement, antiobiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n"
. += "Surgical debridement, antiobiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n"
if(flesh_damage > 0)
. += "Flesh damage detected: Please apply ointment or regenerative mesh to allow recovery.\n"
+4
View File
@@ -212,6 +212,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
// airlock_wires = /datum/wires/airlock/maint
sound_environment = SOUND_AREA_TUNNEL_ENCLOSED
minimap_color = "#454545"
//Maintenance - Departmental
@@ -435,6 +436,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hallway
nightshift_public_area = NIGHTSHIFT_AREA_PUBLIC
sound_environment = SOUND_AREA_STANDARD_STATION
minimap_color = "#aaaaaa"
/area/hallway/primary
name = "Primary Hallway"
@@ -490,6 +492,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hallway/secondary/exit
name = "Escape Shuttle Hallway"
icon_state = "escape"
minimap_color = "#baa0a0"
/area/hallway/secondary/exit/departure_lounge
name = "Departure Lounge"
@@ -498,6 +501,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hallway/secondary/entry
name = "Arrival Shuttle Hallway"
icon_state = "entry"
minimap_color = "#a0a0ba"
/area/hallway/secondary/service
name = "Service Hallway"
+4
View File
@@ -124,6 +124,10 @@
/// Color on minimaps, if it's null (which is default) it makes one at random.
var/minimap_color
var/minimap_color2 // if this isn't null, then this will show as a checkerboard pattern mixed in with the above. works even if the above is null (for better or worse)
var/minimap_show_walls = TRUE
/**
* These two vars allow for multiple unique areas to be linked to a master area
* and share some functionalities such as APC powernet nodes, fire alarms etc, without sacrificing
+3
View File
@@ -9,6 +9,9 @@
ambientsounds = RUINS
sound_environment = SOUND_ENVIRONMENT_STONEROOM
var/valid_territory = FALSE // hey so what if we did not allow things like cult summons to appear on ruins
minimap_color = "#775940"
minimap_color2 = "#6b5d48"
minimap_show_walls = FALSE
/area/ruin/unpowered
+16 -5
View File
@@ -518,7 +518,7 @@
. = list("[get_examine_string(user, TRUE)].")
if(desc)
. += desc
. += "<hr>[desc]"
if(custom_materials)
var/list/materials_list = list()
@@ -702,7 +702,7 @@
var/blood_id = get_blood_id()
if(!(blood_id in GLOB.blood_reagent_types))
return
return list("color" = BLOOD_COLOR_HUMAN, "ANIMAL DNA" = "Y-")
return list("color" = BLOOD_COLOR_HUMAN, "blendmode" = BLEND_MULTIPLY, "ANIMAL DNA" = "Y-")
/mob/living/carbon/get_blood_dna_list()
var/blood_id = get_blood_id()
@@ -711,14 +711,16 @@
var/list/blood_dna = list()
if(dna)
blood_dna["color"] = dna.species.exotic_blood_color //so when combined, the list grows with the number of colors
blood_dna["blendmode"] = dna.species.exotic_blood_blend_mode
blood_dna[dna.unique_enzymes] = dna.blood_type
else
blood_dna["color"] = BLOOD_COLOR_HUMAN
blood_dna["blendmode"] = BLEND_MULTIPLY
blood_dna["UNKNOWN DNA"] = "X*"
return blood_dna
/mob/living/carbon/alien/get_blood_dna_list()
return list("color" = BLOOD_COLOR_XENO, "UNKNOWN DNA" = "X*")
return list("color" = BLOOD_COLOR_XENO, "blendmode" = BLEND_MULTIPLY, "UNKNOWN DNA" = "X*")
//to add a mob's dna info into an object's blood_DNA list.
/atom/proc/transfer_mob_blood_dna(mob/living/L)
@@ -737,6 +739,7 @@
var/old = blood_DNA["color"]
blood_DNA["color"] = BlendRGB(blood_DNA["color"], new_blood_dna["color"])
changed = old != blood_DNA["color"]
blood_DNA["blendmode"] = new_blood_dna["blendmode"]
if(blood_DNA.len == old_length)
return FALSE
return changed
@@ -756,6 +759,7 @@
blood_DNA["color"] = blood_dna["color"]
else
blood_DNA["color"] = BlendRGB(blood_DNA["color"], blood_dna["color"])
blood_DNA["blendmode"] = blood_dna["blendmode"]
//to add blood from a mob onto something, and transfer their dna info
/atom/proc/add_mob_blood(mob/living/M)
@@ -826,6 +830,11 @@
/atom/proc/blood_DNA_to_color()
return (blood_DNA && blood_DNA["color"]) || BLOOD_COLOR_HUMAN
/atom/proc/blood_DNA_to_blend()
if(blood_DNA && !isnull(blood_DNA["blendmode"]))
return blood_DNA["blendmode"]
return BLEND_MULTIPLY
/atom/proc/clean_blood()
. = blood_DNA? TRUE : FALSE
blood_DNA = null
@@ -1192,6 +1201,8 @@
log_mecha(log_text)
if(LOG_SHUTTLE)
log_shuttle(log_text)
if(LOG_ECON)
log_econ(log_text)
else
stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).")
log_game(log_text)
@@ -1295,7 +1306,7 @@
filters += filter(arglist(arguments))
UNSETEMPTY(filter_data)
/atom/proc/transition_filter(name, time, list/new_params, easing, loop)
/atom/proc/transition_filter(name, time, list/new_params, easing, loop, parallel = TRUE)
var/filter = get_filter(name)
if(!filter)
return
@@ -1306,7 +1317,7 @@
for(var/thing in new_params)
params[thing] = new_params[thing]
animate(filter, new_params, time = time, easing = easing, loop = loop)
animate(filter, new_params, time = time, easing = easing, loop = loop, flags = (parallel ? ANIMATION_PARALLEL : 0))
for(var/param in params)
filter_data[name][param] = params[param]
+29 -4
View File
@@ -64,6 +64,16 @@
/// last time we yelled
var/last_yell = 0
// Text-to-bark sounds
var/sound/vocal_bark
var/vocal_bark_id
var/vocal_pitch = 1
var/vocal_pitch_range = 0.2 //Actual pitch is (pitch - (vocal_pitch_range*0.5)) to (pitch + (vocal_pitch_range*0.5))
var/vocal_volume = 70 //Baseline. This gets modified by yelling and other factors
var/vocal_speed = 4 //Lower values are faster, higher values are slower
var/vocal_current_bark //When barks are queued, this gets passed to the bark proc. If vocal_current_bark doesn't match the args passed to the bark proc (if passed at all), then the bark simply doesn't play. Basic curtailing of spam~
/atom/movable/Initialize(mapload)
. = ..()
switch(blocks_emissive)
@@ -217,6 +227,10 @@
if(NAMEOF(src, glide_size))
set_glide_size(var_value)
. = TRUE
if(NAMEOF(src, vocal_bark))
if(isfile(var_value))
vocal_bark = sound(var_value) //bark() expects vocal_bark to already be a sound datum, for performance reasons. adminbus QoL!
. = TRUE
if(!isnull(.))
datum_flags |= DF_VAR_EDITED
@@ -604,11 +618,11 @@
if(throwing && !throw_override)
return
if(on && !(movement_type & FLOATING))
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
animate(src, pixel_z = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
animate(pixel_z = -4, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
setMovetype(movement_type | FLOATING)
else if (!on && (movement_type & FLOATING))
animate(src, pixel_y = initial(pixel_y), time = 10)
animate(src, pixel_z = initial(pixel_y), time = 10)
setMovetype(movement_type & ~FLOATING)
floating_need_update = FALSE // assume it's done
@@ -696,6 +710,17 @@
var/datum/language_holder/LH = get_language_holder()
return LH.update_atom_languages(src)
/// Sets the vocal bark for the atom, using the bark's ID
/atom/movable/proc/set_bark(id)
if(!id)
return FALSE
var/datum/bark/B = GLOB.bark_list[id]
if(!B)
return FALSE
vocal_bark = sound(initial(B.soundpath))
vocal_bark_id = id
return vocal_bark
/* End language procs */
@@ -774,4 +799,4 @@
M.Turn(pick(-30, 30))
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
sleep(1)
animate(I, alpha = 0, transform = matrix(), time = 1)
animate(I, alpha = 0, transform = matrix(), time = 1, flags = ANIMATION_PARALLEL)
+34
View File
@@ -104,6 +104,10 @@ Class Procs:
anchored = TRUE
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
vocal_bark_id = "synth"
vocal_pitch = 0.6
vocal_volume = 40
var/stat = 0
var/use_power = IDLE_POWER_USE
//0 = dont run the auto
@@ -312,6 +316,36 @@ Class Procs:
return TRUE // If we passed all of those checks, woohoo! We can interact with this machine.
/obj/machinery/proc/can_transact(obj/item/card/id/thecard, allowdepartment, silent)
if(!istype(thecard))
if(!silent)
say("No card found.")
return FALSE
else if (!thecard.registered_account)
if(!silent)
say("No account found.")
return FALSE
else if(!allowdepartment && !thecard.registered_account.account_job)
if(!silent)
say("Departmental accounts have been blacklisted from personal expenses due to embezzlement.")
return FALSE
return TRUE
/obj/machinery/proc/attempt_transact(obj/item/card/id/thecard, transaction_cost)
if(!istype(thecard))
return FALSE
var/datum/bank_account/account = thecard.registered_account
if(!istype(account))
return FALSE
if(transaction_cost)
if(!account.adjust_money(-transaction_cost))
return FALSE
var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
if(D)
D.adjust_money(transaction_cost)
return TRUE
/obj/machinery/proc/check_nap_violations()
if(!SSeconomy.full_ancap)
return TRUE
+14 -3
View File
@@ -62,14 +62,15 @@
if(!is_operational())
return
if(shocked && !(stat & NOPOWER))
shock(user,50)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Autolathe", capitalize(src.name))
ui.open()
if(shocked && !(stat & NOPOWER))
if(shock(user,50))
ui.close() //close the window if they got zapped successfully as to prevent them from getting zapped infinitely.
/obj/machinery/autolathe/ui_data(mob/user)
var/list/data = list()
data["materials"] = list()
@@ -298,6 +299,16 @@
wires.interact(user)
return STOP_ATTACK_PROC_CHAIN
/obj/machinery/autolathe/wirecutter_act(mob/living/user, obj/item/I)
. = ..()
if(busy)
balloon_alert(user, "it's busy!")
return STOP_ATTACK_PROC_CHAIN
if(panel_open)
wires.interact(user)
return STOP_ATTACK_PROC_CHAIN
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
use_power(MINERAL_MATERIAL_AMOUNT / 10)
+94 -68
View File
@@ -1,6 +1,10 @@
#define COLORMATE_TINT 1
#define COLORMATE_HSV 2
#define COLORMATE_MATRIX 3
/obj/machinery/gear_painter
name = "\improper Color Mate"
desc = "A machine to give your apparel a fresh new color! Recommended to use with white items for best results."
desc = "A machine to give your apparel a fresh new color!"
icon = 'icons/obj/vending.dmi'
icon_state = "colormate"
// light_mask = "colormate-light-mask"
@@ -10,7 +14,11 @@
var/atom/movable/inserted
var/activecolor = "#FFFFFF"
var/list/color_matrix_last
var/matrix_mode = FALSE
var/active_mode = COLORMATE_HSV
var/build_hue = 0
var/build_sat = 1
var/build_val = 1
/// Allow holder'd mobs
var/allow_mobs = TRUE
/// Minimum lightness for normal mode
@@ -71,8 +79,8 @@
return
if(!QDELETED(H))
H.release()
insert_mob(victim, user)
temp = "[victim] has been inserted."
SStgui.update_uis(src)
if(is_type_in_list(I, allowed_types) && is_operational())
@@ -85,7 +93,6 @@
inserted = I
update_icon()
temp = "[I] has been inserted."
SStgui.update_uis(src)
else
@@ -134,7 +141,7 @@
/obj/machinery/gear_painter/ui_data(mob/user)
. = list()
.["matrixactive"] = matrix_mode
.["activemode"] = active_mode
.["matrixcolors"] = list(
"rr" = color_matrix_last[1],
"rg" = color_matrix_last[2],
@@ -149,6 +156,9 @@
"cg" = color_matrix_last[11],
"cb" = color_matrix_last[12]
)
.["buildhue"] = build_hue
.["buildsat"] = build_sat
.["buildval"] = build_val
if(temp)
.["temp"] = temp
if(inserted)
@@ -166,7 +176,7 @@
if(inserted)
switch(action)
if("switch_modes")
matrix_mode = text2num(params["mode"])
active_mode = text2num(params["mode"])
return TRUE
if("choose_color")
var/chosen_color = input(usr, "Choose a color: ", "Colormate color picking", activecolor) as color|null
@@ -174,14 +184,11 @@
activecolor = chosen_color
return TRUE
if("paint")
if(!check_valid_color(activecolor, usr))
return TRUE
inserted.add_atom_colour(activecolor, FIXED_COLOUR_PRIORITY)
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
do_paint(usr)
temp = "Painted Successfully!"
return TRUE
if("drop")
temp = "Ejected \the [inserted]!"
temp = ""
drop_item()
return TRUE
if("clear")
@@ -192,76 +199,95 @@
if("set_matrix_color")
color_matrix_last[params["color"]] = params["value"]
return TRUE
if("matrix_paint")
var/list/cm = rgb_construct_color_matrix(
text2num(color_matrix_last[1]),
text2num(color_matrix_last[2]),
text2num(color_matrix_last[3]),
text2num(color_matrix_last[4]),
text2num(color_matrix_last[5]),
text2num(color_matrix_last[6]),
text2num(color_matrix_last[7]),
text2num(color_matrix_last[8]),
text2num(color_matrix_last[9]),
text2num(color_matrix_last[10]),
text2num(color_matrix_last[11]),
text2num(color_matrix_last[12])
)
if(!check_valid_color(cm, usr))
return TRUE
inserted.add_atom_colour(cm, FIXED_COLOUR_PRIORITY)
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
temp = "Matrix Painted Successfully!"
if("set_hue")
build_hue = clamp(text2num(params["buildhue"]), 0, 360)
return TRUE
if("set_sat")
build_sat = clamp(text2num(params["buildsat"]), -10, 10)
return TRUE
if("set_val")
build_val = clamp(text2num(params["buildval"]), -10, 10)
return TRUE
/obj/machinery/gear_painter/proc/do_paint(mob/user)
var/color_to_use
switch(active_mode)
if(COLORMATE_TINT)
color_to_use = activecolor
if(COLORMATE_MATRIX)
color_to_use = rgb_construct_color_matrix(
text2num(color_matrix_last[1]),
text2num(color_matrix_last[2]),
text2num(color_matrix_last[3]),
text2num(color_matrix_last[4]),
text2num(color_matrix_last[5]),
text2num(color_matrix_last[6]),
text2num(color_matrix_last[7]),
text2num(color_matrix_last[8]),
text2num(color_matrix_last[9]),
text2num(color_matrix_last[10]),
text2num(color_matrix_last[11]),
text2num(color_matrix_last[12])
)
if(COLORMATE_HSV)
color_to_use = color_matrix_hsv(build_hue, build_sat, build_val)
color_matrix_last = color_to_use
if(!color_to_use || !check_valid_color(color_to_use, user))
to_chat(user, "<span class='notice'>Invalid color.</span>")
return FALSE
inserted.add_atom_colour(color_to_use, FIXED_COLOUR_PRIORITY)
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
return TRUE
/// Produces the preview image of the item, used in the UI, the way the color is not stacking is a sin.
/obj/machinery/gear_painter/proc/build_preview()
if(inserted) //sanity
if(matrix_mode)
var/list/cm = rgb_construct_color_matrix(
text2num(color_matrix_last[1]),
text2num(color_matrix_last[2]),
text2num(color_matrix_last[3]),
text2num(color_matrix_last[4]),
text2num(color_matrix_last[5]),
text2num(color_matrix_last[6]),
text2num(color_matrix_last[7]),
text2num(color_matrix_last[8]),
text2num(color_matrix_last[9]),
text2num(color_matrix_last[10]),
text2num(color_matrix_last[11]),
text2num(color_matrix_last[12])
)
if(!check_valid_color(cm, usr))
temp = "Failed to generate preview: Invalid color!"
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
var/list/cm
switch(active_mode)
if(COLORMATE_MATRIX)
cm = rgb_construct_color_matrix(
text2num(color_matrix_last[1]),
text2num(color_matrix_last[2]),
text2num(color_matrix_last[3]),
text2num(color_matrix_last[4]),
text2num(color_matrix_last[5]),
text2num(color_matrix_last[6]),
text2num(color_matrix_last[7]),
text2num(color_matrix_last[8]),
text2num(color_matrix_last[9]),
text2num(color_matrix_last[10]),
text2num(color_matrix_last[11]),
text2num(color_matrix_last[12])
)
if(!check_valid_color(cm, usr))
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
var/cur_color = inserted.color
inserted.color = null
inserted.color = cm
var/icon/preview = getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
inserted.color = cur_color
if(COLORMATE_TINT)
if(!check_valid_color(activecolor, usr))
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
. = preview
if(COLORMATE_HSV)
cm = color_matrix_hsv(build_hue, build_sat, build_val)
color_matrix_last = cm
if(!check_valid_color(cm, usr))
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
else
if(!check_valid_color(activecolor, usr))
temp = "Failed to generate preview: Invalid color!"
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
var/cur_color = inserted.color
inserted.color = null
inserted.color = (active_mode == COLORMATE_TINT ? activecolor : cm)
var/icon/preview = getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
inserted.color = cur_color
temp = ""
var/cur_color = inserted.color
inserted.color = null
inserted.color = activecolor
var/icon/preview = getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
inserted.color = cur_color
. = preview
. = preview
/obj/machinery/gear_painter/proc/check_valid_color(list/cm, mob/user)
if(!islist(cm)) // normal
var/list/HSV = ReadHSV(RGBtoHSV(cm))
if(HSV[3] < minimum_normal_lightness)
temp = "[cm] is far too dark (min lightness [minimum_normal_lightness]!"
temp = "[cm] is too dark (Minimum lightness: [minimum_normal_lightness])"
return FALSE
return TRUE
else // matrix
@@ -275,6 +301,6 @@
COLORTEST("FFFFFF", cm)
#undef COLORTEST
if(passed < minimum_matrix_tests)
temp = "[english_list(color)] is not allowed (passed [passed] out of 4, minimum [minimum_matrix_tests], minimum lightness [minimum_matrix_lightness])."
temp = "Matrix is too dark. (passed [passed] out of [minimum_matrix_tests] required tests. Minimum lightness: [minimum_matrix_lightness])."
return FALSE
return TRUE
+103 -41
View File
@@ -6,17 +6,22 @@
verb_say = "states"
density = TRUE
req_one_access = list(ACCESS_BAR, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_ENGINE, ACCESS_CARGO, ACCESS_THEATRE)
payment_department = ACCOUNT_SRV
var/active = FALSE
var/list/rangers = list()
var/stop = 0
var/volume = 70
var/datum/track/selection = null
var/queuecost = PRICE_CHEAP //Set to -1 to make this jukebox require access for queueing
var/datum/track/playing = null
var/datum/track/selectedtrack = null
var/list/queuedplaylist = list()
var/queuecooldown //This var exists solely to prevent accidental repeats of John Mulaney's 'What's New Pussycat?' incident. Intentional, however......
/obj/machinery/jukebox/disco
name = "radiant dance machine mark IV"
desc = "The first three prototypes were discontinued after mass casualty incidents."
icon_state = "disco"
req_access = list(ACCESS_ENGINE)
req_one_access = list(ACCESS_ENGINE)
anchored = FALSE
var/list/spotlights = list()
var/list/sparkles = list()
@@ -24,7 +29,7 @@
/obj/machinery/jukebox/disco/indestructible
name = "radiant dance machine mark V"
desc = "Now redesigned with data gathered from the extensive disco and plasma research."
req_access = null
req_one_access = null
anchored = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
flags_1 = NODECONSTRUCT_1
@@ -46,6 +51,16 @@
return
return ..()
/obj/machinery/jukebox/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
queuecost = PRICE_FREE
req_one_access = null
to_chat(user, "<span class='notice'>You've bypassed [src]'s audio volume limiter, and enabled free play.</span>")
return TRUE
/obj/machinery/jukebox/update_icon_state()
if(active)
icon_state = "[initial(icon_state)]-active"
@@ -56,7 +71,7 @@
if(!anchored)
to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>")
return UI_CLOSE
if(!allowed(user) && !isobserver(user))
if((queuecost < 0 && !allowed(user)) && !isobserver(user))
to_chat(user,"<span class='warning'>Error: Access Denied.</span>")
user.playsound_local(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
return UI_CLOSE
@@ -77,18 +92,21 @@
data["active"] = active
data["songs"] = list()
for(var/datum/track/S in SSjukeboxes.songs)
var/list/track_data = list(
name = S.song_name
)
var/list/track_data = list(name = S.song_name)
data["songs"] += list(track_data)
data["queued_tracks"] = list()
for(var/datum/track/S in queuedplaylist)
var/list/track_data = list(name = S.song_name)
data["queued_tracks"] += list(track_data)
data["track_selected"] = null
data["track_length"] = null
data["track_beat"] = null
if(selection)
data["track_selected"] = selection.song_name
data["track_length"] = DisplayTimeText(selection.song_length)
data["track_beat"] = selection.song_beat
if(playing)
data["track_selected"] = playing.song_name
data["track_length"] = DisplayTimeText(playing.song_length)
data["volume"] = volume
data["is_emagged"] = (obj_flags & EMAGGED)
data["cost_for_play"] = queuecost
data["has_access"] = allowed(user)
return data
/obj/machinery/jukebox/ui_act(action, list/params)
@@ -100,57 +118,91 @@
if("toggle")
if(QDELETED(src))
return
if(!active)
if(stop > world.time)
to_chat(usr, "<span class='warning'>Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].</span>")
playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE)
return
if(!allowed(usr))
return
if(!active && !playing)
activate_music()
START_PROCESSING(SSobj, src)
return TRUE
else
stop = 0
return TRUE
if("select_track")
if(active)
to_chat(usr, "<span class='warning'>Error: You cannot change the song until the current one is over.</span>")
return TRUE
if("add_to_queue")
if(QDELETED(src))
return
if(world.time < queuecooldown)
return
if(!istype(selectedtrack, /datum/track))
return
if(!allowed(usr) && queuecost)
var/obj/item/card/id/C
if(isliving(usr))
var/mob/living/L = usr
C = L.get_idcard(TRUE)
if(!can_transact(C))
queuecooldown = world.time + (1 SECONDS)
playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
return
if(!attempt_transact(C, queuecost))
say("Insufficient funds.")
queuecooldown = world.time + (1 SECONDS)
playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
return
to_chat(usr, "<span class='notice'>You spend [queuecost] credits to queue [selectedtrack.song_name].</span>")
log_econ("[queuecost] credits were inserted into [src] by [key_name(usr)] (ID: [C.registered_name]) to queue [selectedtrack.song_name].")
queuedplaylist += selectedtrack
if(active)
say("[selectedtrack.song_name] has been added to the queue.")
else if(!playing)
activate_music()
playsound(src, 'sound/machines/ping.ogg', 50, TRUE)
queuecooldown = world.time + (3 SECONDS)
return TRUE
if("select_track")
var/list/available = list()
for(var/datum/track/S in SSjukeboxes.songs)
available[S.song_name] = S
var/selected = params["track"]
if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
return
selection = available[selected]
selectedtrack = available[selected]
return TRUE
if("set_volume")
if(!allowed(usr))
return
var/new_volume = params["volume"]
if(new_volume == "reset")
volume = initial(volume)
return TRUE
else if(new_volume == "min")
volume = 0
return TRUE
else if(new_volume == "max")
volume = 100
return TRUE
volume = ((obj_flags & EMAGGED) ? 210 : 100)
else if(text2num(new_volume) != null)
volume = text2num(new_volume)
return TRUE
volume = clamp(0, text2num(new_volume), ((obj_flags & EMAGGED) ? 210 : 100))
var/wherejuke = SSjukeboxes.findjukeboxindex(src)
if(wherejuke)
SSjukeboxes.updatejukebox(wherejuke, jukefalloff = volume/35)
return TRUE
/obj/machinery/jukebox/proc/activate_music()
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2)
if(playing || !queuedplaylist.len)
return FALSE
playing = queuedplaylist[1]
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, playing, volume/35)
if(jukeboxslottotake)
active = TRUE
update_icon()
START_PROCESSING(SSobj, src)
stop = world.time + selection.song_length
stop = world.time + playing.song_length
queuedplaylist.Cut(1, 2)
say("Now playing: [playing.song_name]")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, TRUE)
return TRUE
else
return FALSE
/obj/machinery/jukebox/disco/activate_music()
..()
. = ..()
if(!.)
return
dance_setup()
lights_spin()
@@ -243,7 +295,7 @@
S.pixel_y = 7
S.forceMove(get_turf(src))
sleep(7)
if(selection.song_name == "Engineering's Ultimate High-Energy Hustle")
if(playing.song_name == "Engineering's Ultimate High-Energy Hustle")
sleep(280)
for(var/obj/reveal in sparkles)
reveal.alpha = 255
@@ -299,7 +351,7 @@
continue
if(prob(2)) // Unique effects for the dance floor that show up randomly to mix things up
INVOKE_ASYNC(src, .proc/hierofunk)
sleep(selection.song_beat)
sleep(playing.song_beat)
#undef DISCO_INFENO_RANGE
@@ -431,6 +483,7 @@
return
SSjukeboxes.removejukebox(position)
STOP_PROCESSING(SSobj, src)
playing = null
rangers = list()
/obj/machinery/jukebox/disco/dance_over()
@@ -439,12 +492,21 @@
QDEL_LIST(sparkles)
/obj/machinery/jukebox/process()
if(active && world.time >= stop)
active = FALSE
dance_over()
playsound(src,'sound/machines/terminal_off.ogg',50,1)
update_icon()
stop = world.time + 100
if(active)
if(world.time >= stop)
active = FALSE
dance_over()
if(stop && queuedplaylist.len)
activate_music()
else
playsound(src,'sound/machines/terminal_off.ogg',50,1)
update_icon()
playing = null
stop = 0
else if(volume > 140) // BOOM BOOM BOOM BOOM
for(var/mob/living/carbon/C in hearers(round(volume/35), src)) // I WANT YOU IN MY ROOM
if(istype(C)) // LETS SPEND THE NIGHT TOGETHER
C.adjustEarDamage(max((((volume/35) - sqrt(get_dist(C, src) * 4)) - C.get_ear_protection())*0.1, 0)) // FROM NOW UNTIL FOREVER
/obj/machinery/jukebox/disco/process()
+1
View File
@@ -1356,6 +1356,7 @@
/obj/machinery/door/airlock/proc/remove_electrify()
secondsElectrified = NOT_ELECTRIFIED
unelectrify_timerid = null
diag_hud_set_electrified()
/obj/machinery/door/airlock/proc/set_electrified(seconds, mob/user)
secondsElectrified = seconds
+7 -3
View File
@@ -203,9 +203,13 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
point_gain = (BOMB_TARGET_POINTS * 2 * orig_light) / (orig_light + BOMB_TARGET_SIZE)
/*****The Point Capper*****/
if(point_gain > linked_techweb.largest_bomb_value)
var/old_tech_largest_bomb_value = linked_techweb.largest_bomb_value //held so we can pull old before we do math
linked_techweb.largest_bomb_value = point_gain
var/list/largest_values = linked_techweb.largest_values
if(!(LARGEST_BOMB in largest_values))
largest_values[LARGEST_BOMB] = 0
if(point_gain > largest_values[LARGEST_BOMB])
var/old_tech_largest_bomb_value = largest_values[LARGEST_BOMB] //held so we can pull old before we do math
linked_techweb.largest_values[LARGEST_BOMB] = point_gain
point_gain -= old_tech_largest_bomb_value
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_SCI)
if(D)
+4 -4
View File
@@ -230,13 +230,13 @@
if(beaker)
if(beaker.reagents && beaker.reagents.reagent_list.len)
. += "\t<span class='notice'>Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.</span>\n"
. += "<span class='notice'>Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.</span>\n"
else
. += "\t<span class='notice'>Attached is an empty [beaker.name].</span>\n"
. += "<span class='notice'>Attached is an empty [beaker.name].</span>\n"
else
. += "\t<span class='notice'>No chemicals are attached.</span>\n"
. += "<span class='notice'>No chemicals are attached.</span>\n"
. += "\t<span class='notice'>[attached ? attached : "No one"] is attached.</span>"
. += "<span class='notice'>[attached ? attached : "No one"] is attached.</span>"
/obj/machinery/iv_drip/telescopic
name = "telescopic IV drip"
@@ -13,6 +13,17 @@
#define TURRET_FLAG_SHOOT_BORGS (1<<6) // checks if it can shoot cyborgs
#define TURRET_FLAG_SHOOT_HEADS (1<<7) // checks if it can shoot at heads of staff
DEFINE_BITFIELD(turret_flags, list(
"TURRET_FLAG_AUTH_WEAPONS" = TURRET_FLAG_AUTH_WEAPONS,
"TURRET_FLAG_SHOOT_ALL" = TURRET_FLAG_SHOOT_ALL,
"TURRET_FLAG_SHOOT_ALL_REACT" = TURRET_FLAG_SHOOT_ALL_REACT,
"TURRET_FLAG_SHOOT_ANOMALOUS" = TURRET_FLAG_SHOOT_ANOMALOUS,
"TURRET_FLAG_SHOOT_BORGS" = TURRET_FLAG_SHOOT_BORGS,
"TURRET_FLAG_SHOOT_CRIMINALS" = TURRET_FLAG_SHOOT_CRIMINALS,
"TURRET_FLAG_SHOOT_HEADS" = TURRET_FLAG_SHOOT_HEADS,
"TURRET_FLAG_SHOOT_UNSHIELDED" = TURRET_FLAG_SHOOT_UNSHIELDED,
))
/obj/machinery/porta_turret
name = "turret"
icon = 'icons/obj/turrets.dmi'
+46
View File
@@ -29,10 +29,12 @@
var/obj/effect/overlay/status_display_text/message1_overlay
var/obj/effect/overlay/status_display_text/message2_overlay
var/mutable_appearance/ai_vtuber_overlay
var/current_picture = ""
var/current_mode = SD_BLANK
var/message1 = ""
var/message2 = ""
var/mob/living/silicon/ai/master
/obj/item/wallframe/status_display
name = "status display frame"
@@ -122,6 +124,10 @@
if(overlay && message == overlay.message)
return null
// if an AI is controlling, we don't update the overlay
if(master)
return
if(overlay)
qdel(overlay)
@@ -147,6 +153,10 @@
remove_messages()
return
if(master)
remove_messages()
return
switch(current_mode)
if(SD_BLANK)
remove_messages()
@@ -493,6 +503,42 @@
user.emote(initial(emote.key))
break
// ai vtuber moment
/obj/machinery/status_display/AICtrlClick(mob/living/silicon/ai/user)
if(!isAI(user) || master || (user.current && !istype(user.current, /obj/machinery/status_display))) // don't let two AIs control the same one, don't let AI control two things at once
return
if(!user.client.prefs.custom_holoform_icon)
to_chat(user, span_notice("You have no custom holoform set!"))
return
// move AI to the location, set master, update overlays (removes messages)
user.current = src
user.eyeobj.setLoc(get_turf(src))
icon_state = initial(icon_state)
user.controlled_display = src
master = user
update_overlays()
update_appearance()
// we set the avatar here
var/icon/I = icon(user.client.prefs.custom_holoform_icon)
I.Crop(1,16,32,32)
ai_vtuber_overlay = mutable_appearance(I)
ai_vtuber_overlay.blend_mode = BLEND_ADD
ai_vtuber_overlay.pixel_y = 8
update_overlays()
add_overlay(ai_vtuber_overlay)
// tell the user how to speak
to_chat(user, span_notice("Use :q to relay messages through the status display."))
// modified version of how holopads 'hear' and relay to AIs
/obj/machinery/status_display/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list())
. = ..()
if(master && !radio_freq && master.controlled_display == src)
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
/obj/machinery/status_display/ai/process()
if(stat & NOPOWER)
update_appearance()
@@ -3,6 +3,7 @@
desc = "They look bloody and gruesome."
icon_state = "gibbl5"
layer = LOW_OBJ_LAYER
blend_mode = BLEND_DEFAULT
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
mergeable_decal = FALSE
bloodiness = 0 //This isn't supposed to be bloody.
@@ -3,6 +3,7 @@
desc = "It's gooey. Perhaps it's the chef's cooking?"
icon = 'icons/effects/blood.dmi'
icon_state = "floor1"
blend_mode = BLEND_MULTIPLY
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
blood_state = BLOOD_STATE_BLOOD
bloodiness = BLOOD_AMOUNT_PER_DECAL
@@ -33,16 +34,20 @@
. = ..()
if(!fixed_color)
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
blend_mode = blood_DNA_to_blend()
/obj/effect/decal/cleanable/blood/PersistenceSave(list/data)
. = ..()
data["color"] = color
data["blendmode"] = blend_mode
/obj/effect/decal/cleanable/blood/PersistenceLoad(list/data)
. = ..()
if(data["color"])
fixed_color = TRUE
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
if(data["blendmode"])
blend_mode = data["blendmode"]
name = "dried blood"
desc = "Looks like it's been here a while. Eew"
bloodiness = 0
@@ -82,8 +87,8 @@
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
name = "blood"
icon = 'icons/effects/blood.dmi'
icon_state = "ltrails_1"
desc = "Your instincts say you shouldn't be following these."
blend_mode = BLEND_MULTIPLY
random_icon_states = null
beauty = -50
persistent = TRUE
@@ -95,6 +100,7 @@
. = ..()
data["dir"] = dir
data["color"] = color
data["blendmode"] = blend_mode
/obj/effect/decal/cleanable/trail_holder/PersistenceLoad(list/data)
. = ..()
@@ -103,11 +109,14 @@
if(data["color"])
fixed_color = TRUE
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
if(data["blendmode"])
blend_mode = data["blendmode"]
/obj/effect/decal/cleanable/trail_holder/update_icon()
. = ..()
if(!fixed_color)
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
blend_mode = blood_DNA_to_blend()
/obj/effect/cleanable/trail_holder/Initialize(mapload)
. = ..()
+1
View File
@@ -1,4 +1,5 @@
GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/effects/fire.dmi', "fire"))
GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons/effects/welding_effect.dmi', "welding_sparks", GASFIRE_LAYER, ABOVE_LIGHTING_PLANE))
GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// if true, everyone item when created will have its name changed to be
+6 -5
View File
@@ -601,11 +601,12 @@
H.adjustOxyLoss(H.health - HALFWAYCRITDEATH, 0)
else
var/overall_damage = total_brute + total_burn + H.getToxLoss() + H.getOxyLoss()
var/mobhealth = H.health
H.adjustOxyLoss((mobhealth - HALFWAYCRITDEATH) * (H.getOxyLoss() / overall_damage), 0)
H.adjustToxLoss((mobhealth - HALFWAYCRITDEATH) * (H.getToxLoss() / overall_damage), 0)
H.adjustFireLoss((mobhealth - HALFWAYCRITDEATH) * (total_burn / overall_damage), 0)
H.adjustBruteLoss((mobhealth - HALFWAYCRITDEATH) * (total_brute / overall_damage), 0)
if(overall_damage)
var/mobhealth = H.health
H.adjustOxyLoss((mobhealth - HALFWAYCRITDEATH) * (H.getOxyLoss() / overall_damage), 0)
H.adjustToxLoss((mobhealth - HALFWAYCRITDEATH) * (H.getToxLoss() / overall_damage), 0)
H.adjustFireLoss((mobhealth - HALFWAYCRITDEATH) * (total_burn / overall_damage), 0)
H.adjustBruteLoss((mobhealth - HALFWAYCRITDEATH) * (total_brute / overall_damage), 0)
H.updatehealth() // Previous "adjust" procs don't update health, so we do it manually.
user.visible_message("<span class='notice'>[req_defib ? "[defib]" : "[src]"] pings: Resuscitation successful.</span>")
playsound(src, 'sound/machines/defib_success.ogg', 50, 0)
+32 -33
View File
@@ -145,32 +145,29 @@ GENETICS SCANNER
mob_status = "<span class='alert'><b>Deceased</b></span>"
oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss
var/msg = "<span class='info'>*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]"
var/msg = "<span class='info'>Analyzing results for [M]:\n<blockquote class='notice'>Overall status: [mob_status]"
// Damage descriptions
if(brute_loss > 10)
msg += "\n\t<span class='alert'>[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.</span>"
msg += "\n<span class='alert'>[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.</span>"
if(fire_loss > 10)
msg += "\n\t<span class='alert'>[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.</span>"
msg += "\n<span class='alert'>[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.</span>"
if(oxy_loss > 10)
msg += "\n\t<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>"
msg += "\n<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>"
if(tox_loss > 10)
msg += "\n\t<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of [HAS_TRAIT(M, TRAIT_ROBOTIC_ORGANISM) ? "system corruption" : "toxin damage"] detected.</span>"
msg += "\n<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of [HAS_TRAIT(M, TRAIT_ROBOTIC_ORGANISM) ? "system corruption" : "toxin damage"] detected.</span>"
if(M.getStaminaLoss())
msg += "\n\t<span class='alert'>Subject appears to be suffering from fatigue.</span>"
msg += "\n<span class='alert'>Subject appears to be suffering from fatigue.</span>"
if(advanced)
msg += "\n\t<span class='info'>Fatigue Level: [M.getStaminaLoss()]%.</span>"
msg += "\n<span class='info'>Fatigue Level: [M.getStaminaLoss()]%.</span>"
if (M.getCloneLoss())
msg += "\n\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>"
msg += "\n<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>"
if(advanced)
msg += "\n\t<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>"
msg += "\n<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>"
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(advanced && H.has_dna())
msg += "\n\t<span class='info'>Genetic Stability: [H.dna.stability]%.</span>"
to_chat(user, msg)
msg = ""
msg += "\n<span class='info'>Genetic Stability: [H.dna.stability]%.</span>"
// Body part damage report
var/list/dmgreport = list()
@@ -178,7 +175,7 @@ GENETICS SCANNER
var/mob/living/carbon/C = M
var/list/damaged = C.get_damaged_bodyparts(1,1)
if(length(damaged)>0 || oxy_loss>0 || tox_loss>0 || fire_loss>0)
dmgreport += "<table style='margin-left:33px'><tr><font face='Verdana'>\
dmgreport += "<table><tr><font face='Verdana'>\
<td style='width: 90px;'><font color='#0000CC'>Damage:</font></td>\
<td style='width: 55px;'><font color='red'><b>Brute</b></font></td>\
<td style='width: 45px;'><font color='orange'><b>Burn</b></font></td>\
@@ -196,7 +193,7 @@ GENETICS SCANNER
<td><font color='red'>[(org.brute_dam > 0) ? "[org.brute_dam]" : "0"]</font></td>\
<td><font color='orange'>[(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]</font></td></tr>"
dmgreport += "</table>"
to_chat(user, dmgreport.Join())
msg += "\n[dmgreport.Join()]"
//Organ damages report
@@ -317,7 +314,7 @@ GENETICS SCANNER
damage_message += " <font color='red'>Minor [O.name] failure detected.</span>"
if(temp_message || damage_message)
msg += "\t<b><span class='info'>[uppertext(O.name)]:</b></span> [damage_message] [temp_message]\n"
msg += "\n<b><span class='info'>[uppertext(O.name)]:</b></span> [damage_message] [temp_message]\n"
@@ -332,24 +329,24 @@ GENETICS SCANNER
var/has_liver = C.dna && !(NOLIVER in C.dna.species.species_traits)
var/has_stomach = C.dna && !(NOSTOMACH in C.dna.species.species_traits)
if(!M.getorganslot(ORGAN_SLOT_EYES))
msg += "\t<span class='alert'><b>Subject does not have eyes.</b></span>\n"
msg += "<span class='alert'><b>Subject does not have eyes.</b></span>\n"
if(!M.getorganslot(ORGAN_SLOT_EARS))
msg += "\t<span class='alert'><b>Subject does not have ears.</b></span>\n"
msg += "<span class='alert'><b>Subject does not have ears.</b></span>\n"
if(!M.getorganslot(ORGAN_SLOT_BRAIN))
msg += "\t<span class='alert'><b>Subject's brain function is non-existent!</b></span>\n"
msg += "<span class='alert'><b>Subject's brain function is non-existent!</b></span>\n"
if(has_liver && !M.getorganslot(ORGAN_SLOT_LIVER))
msg += "\t<span class='alert'><b>Subject's liver is missing!</b></span>\n"
msg += "<span class='alert'><b>Subject's liver is missing!</b></span>\n"
if(blooded && !M.getorganslot(ORGAN_SLOT_HEART))
msg += "\t<span class='alert'><b>Subject's heart is missing!</b></span>\n"
msg += "<span class='alert'><b>Subject's heart is missing!</b></span>\n"
if(breathes && !M.getorganslot(ORGAN_SLOT_LUNGS))
msg += "\t<span class='alert'><b>Subject's lungs have collapsed from trauma!</b></span>\n"
msg += "<span class='alert'><b>Subject's lungs have collapsed from trauma!</b></span>\n"
if(has_stomach && !M.getorganslot(ORGAN_SLOT_STOMACH))
msg += "\t<span class='alert'><b>Subject's stomach is missing!</span>\n"
msg += "<span class='alert'><b>Subject's stomach is missing!</span>\n"
if(M.radiation)
msg += "\t<span class='alert'>Subject is irradiated.</span>\n"
msg += "\t<span class='info'>Radiation Level: [M.radiation] rad</span>\n"
msg += "<span class='alert'>Subject is irradiated.</span>\n"
msg += "<span class='info'>Radiation Level: [M.radiation] rad</span>\n"
@@ -383,11 +380,11 @@ GENETICS SCANNER
else if (S.flying_species != initial(S.flying_species))
mutant = TRUE
msg += "\t<span class='info'>Reported Species: [H.spec_trait_examine_font()][H.dna.custom_species ? H.dna.custom_species : S.name]</font></span>\n"
msg += "\t<span class='info'>Base Species: [H.spec_trait_examine_font()][S.name]</font></span>\n"
msg += "\n<span class='info'>Reported Species: [H.spec_trait_examine_font()][H.dna.custom_species ? H.dna.custom_species : S.name]</font></span>\n"
msg += "<span class='info'>Base Species: [H.spec_trait_examine_font()][S.name]</font></span>\n"
if(mutant)
msg += "\t<span class='info'>Subject has mutations present.</span>\n"
msg += "\t<span class='info'>Body temperature: [round(M.bodytemperature-T0C,0.1)] &deg;C ([round(M.bodytemperature*1.8-459.67,0.1)] &deg;F)</span>\n"
msg += "<span class='info'>Subject has mutations present.</span>\n"
msg += "<span class='info'>Body temperature: [round(M.bodytemperature-T0C,0.1)] &deg;C ([round(M.bodytemperature*1.8-459.67,0.1)] &deg;F)</span>\n"
// Time of death
if(M.tod && (M.stat == DEAD || ((HAS_TRAIT(M, TRAIT_FAKEDEATH)) && !advanced)))
@@ -452,14 +449,14 @@ GENETICS SCANNER
if(cyberimp_detect)
msg += "<span class='notice'>Detected cybernetic modifications:</span>\n"
msg += "<span class='notice'>[cyberimp_detect]</span>\n"
msg += "<span class='notice'>*---------*</span>"
msg += "</blockquote>"
to_chat(user, msg)
SEND_SIGNAL(M, COMSIG_NANITE_SCAN, user, FALSE)
/proc/chemscan(mob/living/user, mob/living/M)
if(istype(M))
if(M.reagents)
var/msg = "<span class='info'>*---------*\n"
var/msg = "<blockquote class='purple'>"
if(M.reagents.reagent_list.len)
var/list/datum/reagent/reagents = list()
for(var/datum/reagent/R in M.reagents.reagent_list)
@@ -498,7 +495,7 @@ GENETICS SCANNER
if(95 to INFINITY)
msg += "<span class='danger'>Subject contains a extremely dangerous amount of toxic isomers.</span>\n"
msg += "*---------*</span>"
msg += "</blockquote>"
to_chat(user, msg)
/obj/item/healthanalyzer/verb/toggle_mode()
@@ -529,12 +526,14 @@ GENETICS SCANNER
var/render_list = ""
for(var/i in patient.get_wounded_bodyparts())
if(render_list == "")
render_list += "<blockquote class='warning'>"
var/obj/item/bodypart/wounded_part = i
render_list += "<span class='alert ml-1'><b>Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]</b>"
for(var/k in wounded_part.wounds)
var/datum/wound/W = k
render_list += "<div class='ml-2'>[W.get_scanner_description()]</div>\n"
render_list += "</span>"
render_list += "</blockquote>"
if(render_list == "")
if(istype(scanner))
@@ -205,6 +205,10 @@
if(!throw_item(target, I, user))
break
if(user)
shake_camera(user, (pressureSetting * 0.75 + 1), (pressureSetting * 0.75))
/obj/item/pneumatic_cannon/proc/throw_item(turf/target, obj/item/I, mob/user)
if(!istype(I))
return FALSE
@@ -22,8 +22,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
new/datum/stack_recipe("spout flask", /obj/item/glasswork/glass_base/spouty, 20), \
new/datum/stack_recipe("small bulb flask", /obj/item/glasswork/glass_base/flask_small, 5), \
new/datum/stack_recipe("large bottle flask", /obj/item/glasswork/glass_base/flask_large, 15), \
new/datum/stack_recipe("tea cup", /obj/item/glasswork/glass_base/tea_plate, 5), \
new/datum/stack_recipe("tea plate", /obj/item/glasswork/glass_base/tea_cup, 5), \
new/datum/stack_recipe("tea cup", /obj/item/glasswork/glass_base/tea_cup, 5), \
new/datum/stack_recipe("tea plate", /obj/item/glasswork/glass_base/tea_plate, 5), \
)), \
))
@@ -561,4 +561,4 @@
singular_name = "catwalk floor tile"
desc = "Flooring that shows its contents underneath. Engineers love it!"
icon_state = "catwalk_tile"
turf_type = /turf/open/floor/plating/catwalk_floor
turf_type = /turf/open/floor/catwalk_floor
@@ -119,6 +119,11 @@
dyn_explosion(T, plasmaAmount/5)//20 plasma in a standard welder has a 4 power explosion. no breaches, but enough to kill/dismember holder
qdel(src)
/obj/item/weldingtool/use_tool(atom/target, mob/living/user, delay, amount, volume, datum/callback/extra_checks, skill_gain_mult)
target.add_overlay(GLOB.welding_sparks)
. = ..()
target.cut_overlay(GLOB.welding_sparks)
/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user)
if(!istype(H))
return ..()
+2
View File
@@ -7,6 +7,8 @@
var/obj_flags = CAN_BE_HIT
var/set_obj_flags // ONLY FOR MAPPING: Sets flags from a string list, handled in Initialize. Usage: set_obj_flags = "EMAGGED;!CAN_BE_HIT" to set EMAGGED and clear CAN_BE_HIT.
var/minimap_override_color // allows this obj to set its own color on the minimap
var/damtype = BRUTE
var/force = 0
+1 -1
View File
@@ -65,7 +65,7 @@
/obj/structure/proc/do_climb(atom/movable/A)
if(climbable)
density = FALSE
. = step(A,get_dir(A,src.loc))
. = step(A, (A.loc == loc ? dir : get_dir(A,src.loc)))
density = TRUE
/obj/structure/proc/climb_structure(mob/living/user)
@@ -156,9 +156,10 @@
for(var/atom/movable/AM in L)
if(AM != src && insert(AM) == -1) // limit reached
break
// for(var/i in reverseRange(L.GetAllContents()))
// var/atom/movable/thing = i
// SEND_SIGNAL(thing, COMSIG_TRY_STORAGE_HIDE_ALL)
// todo: this should be unnecessary, storage should auto close on move wtf
for(var/i in reverseRange(L.GetAllContents()))
var/atom/movable/thing = i
SEND_SIGNAL(thing, COMSIG_TRY_STORAGE_HIDE_ALL)
/obj/structure/closet/proc/open(mob/living/user, force = FALSE)
if(!can_open(user, force))
@@ -64,6 +64,7 @@
new /obj/item/clothing/under/rank/security/officer/blueshirt/seccorp/hoscorp(src)
new /obj/item/clothing/suit/armor/vest/leather(src)
new /obj/item/clothing/suit/armor/hos(src)
new /obj/item/clothing/suit/armor/hos/platecarrier(src)
new /obj/item/clothing/under/rank/security/head_of_security/skirt(src)
new /obj/item/clothing/under/rank/security/head_of_security/alt(src)
new /obj/item/clothing/under/rank/security/head_of_security/alt/skirt(src)
+29 -1
View File
@@ -31,14 +31,42 @@ GLOBAL_LIST_INIT(freqtospan, list(
/atom/movable/proc/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args)
/atom/movable/proc/bark(list/hearers, distance, volume, pitch, queue_time)
if(queue_time && vocal_current_bark != queue_time)
return
if(SEND_SIGNAL(src, COMSIG_MOVABLE_BARK, hearers, distance, volume, pitch))
return //bark interception. this probably counts as some flavor of BDSM
if(!vocal_bark)
if(!vocal_bark_id || !set_bark(vocal_bark_id)) //just-in-time bark generation
return
volume = min(volume, 100)
var/turf/T = get_turf(src)
for(var/mob/M in hearers)
M.playsound_local(T, vol = volume, vary = TRUE, frequency = pitch, max_distance = distance, falloff_distance = 0, falloff_exponent = BARK_SOUND_FALLOFF_EXPONENT(distance), S = vocal_bark, distance_multiplier = 1)
/atom/movable/proc/can_speak()
return 1
/atom/movable/proc/send_speech(message, range = 7, atom/movable/source = src, bubble_type, list/spans, datum/language/message_language = null, message_mode)
var/rendered = compose_message(src, message_language, message, , spans, message_mode, source)
for(var/_AM in get_hearers_in_view(range, source))
var/list/hearers = get_hearers_in_view(range, source)
for(var/_AM in hearers)
var/atom/movable/AM = _AM
AM.Hear(rendered, src, message_language, message, , spans, message_mode, source)
if(SEND_SIGNAL(src, COMSIG_MOVABLE_QUEUE_BARK, hearers, args) || vocal_bark || vocal_bark_id)
for(var/mob/M in hearers)
if(!M.client)
continue
if(!(M.client.prefs.toggles & SOUND_BARK))
hearers -= M
var/barks = min(round((LAZYLEN(message) / vocal_speed)) + 1, BARK_MAX_BARKS)
var/total_delay
vocal_current_bark = world.time //this is juuuuust random enough to reliably be unique every time send_speech() is called, in most scenarios
for(var/i in 1 to barks)
if(total_delay > BARK_MAX_TIME)
break
addtimer(CALLBACK(src, .proc/bark, hearers, range, vocal_volume, BARK_DO_VARY(vocal_pitch, vocal_pitch_range), vocal_current_bark), total_delay)
total_delay += rand(DS2TICKS(vocal_speed / BARK_SPEED_BASELINE), DS2TICKS(vocal_speed / BARK_SPEED_BASELINE) + DS2TICKS(vocal_speed / BARK_SPEED_BASELINE)) TICKS
/atom/movable/proc/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, face_name = FALSE, atom/movable/source)
if(!source)
+11 -4
View File
@@ -110,13 +110,20 @@ distance_multiplier - Can be used to multiply the distance at which the sound is
*/
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff_exponent = SOUND_FALLOFF_EXPONENT, channel = 0, pressure_affected = TRUE, sound/S, max_distance,
falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = SOUND_DEFAULT_DISTANCE_MULTIPLIER, envwet = -10000, envdry = 0)
if(!client || !can_hear())
falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = SOUND_DEFAULT_DISTANCE_MULTIPLIER, envwet = -10000, envdry = 0, virtual_hearer)
if(audiovisual_redirect)
virtual_hearer = get_turf(src)
audiovisual_redirect.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, max_distance, falloff_distance, distance_multiplier, max(0, envwet), -10000, virtual_hearer)
//No return here, as we want to deliberately support the possibility of shenanigans in which mobs with clients can have active AV redirects to completely different players
if(!client)
return
if(!S)
S = sound(get_sfx(soundin))
if(!can_hear() && !(S.status & SOUND_UPDATE)) //This is primarily to make sure sound updates still go through when a spaceman's deaf
return
S.wait = 0 //No queue
S.channel = channel || SSsounds.random_available_channel()
S.volume = vol
@@ -131,7 +138,7 @@ distance_multiplier - Can be used to multiply the distance at which the sound is
S.frequency = get_rand_frequency()
if(isturf(turf_source))
var/turf/T = get_turf(src)
var/turf/T = virtual_hearer || get_turf(src)
//sound volume falloff with distance
var/distance = get_dist(T, turf_source)
@@ -173,7 +180,7 @@ distance_multiplier - Can be used to multiply the distance at which the sound is
var/dz = turf_source.y - T.y // Hearing from infront/behind
S.z = dz * distance_multiplier
var/dy = (turf_source.z - T.z) * 5 * distance_multiplier // Hearing from above / below, multiplied by 5 because we assume height is further along coords.
S.y = dy + 1
S.y = dy + distance_multiplier
S.falloff = isnull(max_distance)? FALLOFF_SOUNDS : max_distance //use max_distance, else just use 1 as we are a direct sound so falloff isnt relevant.
+20 -4
View File
@@ -73,16 +73,26 @@
/turf/closed/indestructible/splashscreen
name = "Space Station 13"
icon = 'icons/blank_title.png'
desc = null
icon = 'icons/blanks/blank_title.png'
icon_state = ""
layer = FLY_LAYER
plane = SPLASHSCREEN_PLANE
bullet_bounce_sound = null
/turf/closed/indestructible/splashscreen/New()
INITIALIZE_IMMEDIATE(/turf/closed/indestructible/splashscreen)
/turf/closed/indestructible/splashscreen/Initialize(mapload)
. = ..()
SStitle.splash_turf = src
if(SStitle.icon)
icon = SStitle.icon
..()
handle_generic_titlescreen_sizes()
///helper proc that will center the screen if the icon is changed to a generic width, to make admins have to fudge around with pixel_x less. returns null
/turf/closed/indestructible/splashscreen/proc/handle_generic_titlescreen_sizes()
var/icon/size_check = icon(SStitle.icon, icon_state)
var/width = size_check.Width()
pixel_x = (672 - width) * 0.5 //The title screen is mapped with the expectation that it's 672x480. Should probably turn the title screen size into a define some time!
/turf/closed/indestructible/splashscreen/vv_edit_var(var_name, var_value)
. = ..()
@@ -90,7 +100,13 @@
switch(var_name)
if(NAMEOF(src, icon))
SStitle.icon = icon
handle_generic_titlescreen_sizes()
/turf/closed/indestructible/start_area
name = null
desc = null
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/turf/closed/indestructible/riveted
icon = 'icons/turf/walls/riveted.dmi'
icon_state = "riveted"
+14 -8
View File
@@ -5,7 +5,7 @@
* you can crowbar it to interact with the underneath stuff without destroying the tile...
* unless you want to!
*/
/turf/open/floor/plating/catwalk_floor
/turf/open/floor/catwalk_floor
icon = 'icons/turf/floors/catwalk_plating.dmi'
icon_state = "catwalk_below"
floor_tile = /obj/item/stack/tile/catwalk
@@ -16,29 +16,35 @@
barefootstep = FOOTSTEP_CATWALK
clawfootstep = FOOTSTEP_CATWALK
heavyfootstep = FOOTSTEP_CATWALK
intact = FALSE
var/covered = TRUE
/turf/open/floor/plating/catwalk_floor/Initialize(mapload)
/turf/open/floor/catwalk_floor/Initialize(mapload)
. = ..()
layer = CATWALK_LAYER
update_icon(UPDATE_OVERLAYS)
/turf/open/floor/plating/catwalk_floor/update_overlays()
/turf/open/floor/catwalk_floor/update_overlays()
. = ..()
var/static/catwalk_overlay
var/static/image/catwalk_overlay
if(isnull(catwalk_overlay))
catwalk_overlay = iconstate2appearance(icon, "catwalk_above")
catwalk_overlay = new()
catwalk_overlay.icon = icon
catwalk_overlay.icon_state = "catwalk_above"
catwalk_overlay.plane = GAME_PLANE
catwalk_overlay.layer = CATWALK_LAYER
catwalk_overlay = catwalk_overlay.appearance
if(covered)
. += catwalk_overlay
/turf/open/floor/plating/catwalk_floor/screwdriver_act(mob/living/user, obj/item/tool)
/turf/open/floor/catwalk_floor/screwdriver_act(mob/living/user, obj/item/tool)
. = ..()
covered = !covered
user.balloon_alert(user, "[!covered ? "cover removed" : "cover added"]")
update_icon(UPDATE_OVERLAYS)
/turf/open/floor/plating/catwalk_floor/pry_tile(obj/item/crowbar, mob/user, silent)
/turf/open/floor/catwalk_floor/crowbar_act(mob/user, obj/item/I)
if(covered)
user.balloon_alert(user, "remove cover first!")
return FALSE
. = ..()
return pry_tile(I, user)
+1
View File
@@ -117,6 +117,7 @@ GLOBAL_LIST(topic_status_cache)
GLOB.world_asset_log = "[GLOB.log_directory]/asset.log"
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
GLOB.world_victim_log = "[GLOB.log_directory]/victim.log"
GLOB.world_econ_log = "[GLOB.log_directory]/econ.log"
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
GLOB.world_manifest_log = "[GLOB.log_directory]/manifest.log"

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