Merge remote-tracking branch 'upstream/master' into ambitioncheck
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#define SHOVABLE_ONTO (1<<13)//called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
|
||||
#define EXAMINE_SKIP (1<<14) /// Makes the Examine proc not read out this item.
|
||||
#define IN_STORAGE (1<<15) //is this item in the storage item, such as backpack? used for tooltips
|
||||
#define HAND_ITEM (1<<16) // If an item is just your hand (circled hand, slapper) and shouldn't block things like riding
|
||||
|
||||
/// Integrity defines for clothing (not flags but close enough)
|
||||
#define CLOTHING_PRISTINE 0 // We have no damage on the clothing
|
||||
|
||||
@@ -112,6 +112,18 @@ GLOBAL_LIST_EMPTY(living_heart_cache) //A list of all living hearts in existance
|
||||
#define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread
|
||||
#define BLOB_REFLECTOR_COST 15
|
||||
|
||||
/// How many telecrystals a normal traitor starts with
|
||||
#define TELECRYSTALS_DEFAULT 20
|
||||
/// How many telecrystals mapper/admin only "precharged" uplink implant
|
||||
#define TELECRYSTALS_PRELOADED_IMPLANT 10
|
||||
/// The normal cost of an uplink implant; used for calcuating how many
|
||||
/// TC to charge someone if they get a free implant through choice or
|
||||
/// because they have nothing else that supports an implant.
|
||||
#define UPLINK_IMPLANT_TELECRYSTAL_COST 4
|
||||
|
||||
/// The dimensions of the antagonist preview icon. Will be scaled to this size.
|
||||
#define ANTAGONIST_PREVIEW_ICON_SIZE 96
|
||||
|
||||
//Objectives-Ambitions Panel
|
||||
#define REQUEST_NEW_OBJECTIVE "new_objective"
|
||||
#define REQUEST_DEL_OBJECTIVE "del_objective"
|
||||
|
||||
@@ -68,6 +68,21 @@
|
||||
|
||||
#define TEMPERATURE_DAMAGE_COEFFICIENT 1.5 //This is used in handle_temperature_damage() for humans, and in reagents that affect body temperature. Temperature damage is multiplied by this amount.
|
||||
|
||||
#define SYNTH_PASSIVE_HEAT_GAIN 10 //Degrees C per handle_environment() Synths passively heat up. Mitigated by cooling efficiency. Can lead to overheating if not managed.
|
||||
#define SYNTH_MAX_PASSIVE_GAIN_TEMP 250 //Degrees C that a synth can be heated up to by their internal heat gain, provided their cooling is insufficient to mitigate it.
|
||||
#define SYNTH_MIN_PASSIVE_COOLING_TEMP -30 //Degrees C a synth can cool towards at very high cooling efficiency.
|
||||
#define SYNTH_HEAT_EFFICIENCY_COEFF 0.005 //How quick the difference between the Synth and the environment starts to matter. The smaller the higher the difference has to be for the same change.
|
||||
#define SYNTH_SINGLE_INFLUENCE_COOLING_EFFECT_CAP 3 //How big can the multiplier for heat / pressure cooling be in an optimal environment
|
||||
#define SYNTH_TOTAL_ENVIRONMENT_EFFECT_CAP 2 //How big of an multiplier can the environment give in an optimal scenario (maximum efficiency in the end is at a lower cap, this mostly counters low coolant levels)
|
||||
#define SYNTH_MAX_COOLING_EFFICIENCY 1.5 //The maximum possible cooling efficiency one can achieve at optimal conditions.
|
||||
#define SYNTH_ACTIVE_COOLING_TEMP_BOUNDARY 10 //The minimum distance from room temperature a Synth needs to have for active cooling to actively cool.
|
||||
#define SYNTH_ACTIVE_COOLING_LOW_PRESSURE_THRESHOLD 0.05 //At how much percentage of default pressure (or lower) active cooling gets a massive cost penalty.
|
||||
#define SYNTH_ACTIVE_COOLING_LOW_PRESSURE_PENALTY 2.5 //By how much is active cooling cost multiplied if in a very-low-pressure environment?
|
||||
#define SYNTH_ACTIVE_COOLING_MIN_ADJUSTMENT 5 //What is the minimum amount of temp you move towards the target point, even if it would be less with default calculations?
|
||||
#define SYNTH_INTEGRATION_COOLANT_PENALTY 0.4 //Integrating coolant is multiplied with this for calculation of impact on passive cooling.
|
||||
#define SYNTH_INTEGRATION_COOLANT_CAP 0.25 //Integrating coolant is capped at counting as current_blood * this number. This is so you can't just run on salglu or whatever.
|
||||
#define SYNTH_COLD_OFFSET -125 //How much colder temps Synths can tolerate. Used in their species.
|
||||
|
||||
#define BODYTEMP_NORMAL 310.15 //The natural temperature for a body
|
||||
#define BODYTEMP_AUTORECOVERY_DIVISOR 11 //This is the divisor which handles how much of the temperature difference between the current body temperature and 310.15K (optimal temperature) humans auto-regenerate each tick. The higher the number, the slower the recovery. This is applied each tick, so long as the mob is alive.
|
||||
#define BODYTEMP_AUTORECOVERY_MINIMUM 12 //Minimum amount of kelvin moved toward 310K per tick. So long as abs(310.15 - bodytemp) is more than 50.
|
||||
@@ -128,6 +143,7 @@
|
||||
#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3)
|
||||
#define TANK_MIN_RELEASE_PRESSURE 0
|
||||
#define TANK_DEFAULT_RELEASE_PRESSURE 17
|
||||
#define TANK_POST_FRAGMENT_REACTIONS 5
|
||||
|
||||
//CANATMOSPASS
|
||||
#define ATMOS_PASS_YES 1
|
||||
@@ -160,6 +176,9 @@
|
||||
//SNOSTATION
|
||||
#define ICEMOON_DEFAULT_ATMOS "ICEMOON_ATMOS"
|
||||
|
||||
//FESTIVESTATION
|
||||
#define FESTIVE_ATMOS "o2=22;n2=82;TEMP=266" //this goes here right putnam??
|
||||
|
||||
//ATMOSIA GAS MONITOR TAGS
|
||||
#define ATMOS_GAS_MONITOR_INPUT_O2 "o2_in"
|
||||
#define ATMOS_GAS_MONITOR_OUTPUT_O2 "o2_out"
|
||||
@@ -257,6 +276,7 @@
|
||||
#define GAS_HYPERNOB "nob"
|
||||
#define GAS_NITROUS "n2o"
|
||||
#define GAS_NITRYL "no2"
|
||||
#define GAS_HYDROGEN "hydrogen"
|
||||
#define GAS_TRITIUM "tritium"
|
||||
#define GAS_BZ "bz"
|
||||
#define GAS_STIMULUM "stim"
|
||||
@@ -264,9 +284,16 @@
|
||||
#define GAS_MIASMA "miasma"
|
||||
#define GAS_METHANE "methane"
|
||||
#define GAS_METHYL_BROMIDE "methyl_bromide"
|
||||
#define GAS_BROMINE "bromine"
|
||||
#define GAS_AMMONIA "ammonia"
|
||||
#define GAS_FLUORINE "fluorine"
|
||||
#define GAS_ETHANOL "ethanol"
|
||||
|
||||
#define GAS_GROUP_CHEMICALS "Chemicals"
|
||||
|
||||
#define GAS_FLAG_DANGEROUS (1<<0)
|
||||
#define GAS_FLAG_BREATH_PROC (1<<1)
|
||||
#define GAS_FLAG_CHEMICAL (1<<2)
|
||||
|
||||
//SUPERMATTER DEFINES
|
||||
#define HEAT_PENALTY "heat penalties"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
//different types of atom colorations
|
||||
#define ADMIN_COLOUR_PRIORITY 1 //only used by rare effects like greentext coloring mobs and when admins varedit color
|
||||
#define TEMPORARY_COLOUR_PRIORITY 2 //e.g. purple effect of the revenant on a mob, black effect when mob electrocuted
|
||||
#define WASHABLE_COLOUR_PRIORITY 3 //color splashed onto an atom (e.g. paint on turf)
|
||||
#define FIXED_COLOUR_PRIORITY 4 //color inherent to the atom (e.g. blob color)
|
||||
#define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are.
|
||||
@@ -0,0 +1,197 @@
|
||||
// This is eventually for wjohn to add more color standardization stuff like I keep asking him >:(
|
||||
|
||||
#define COLOR_INPUT_DISABLED "#F0F0F0"
|
||||
#define COLOR_INPUT_ENABLED "#D3B5B5"
|
||||
|
||||
#define COLOR_DARKMODE_BACKGROUND "#202020"
|
||||
#define COLOR_DARKMODE_DARKBACKGROUND "#171717"
|
||||
#define COLOR_DARKMODE_TEXT "#a4bad6"
|
||||
|
||||
#define COLOR_WHITE "#FFFFFF"
|
||||
#define COLOR_VERY_LIGHT_GRAY "#EEEEEE"
|
||||
#define COLOR_SILVER "#C0C0C0"
|
||||
#define COLOR_GRAY "#808080"
|
||||
#define COLOR_FLOORTILE_GRAY "#8D8B8B"
|
||||
#define COLOR_DARK "#454545"
|
||||
#define COLOR_ALMOST_BLACK "#333333"
|
||||
#define COLOR_BLACK "#000000"
|
||||
#define COLOR_HALF_TRANSPARENT_BLACK "#0000007A"
|
||||
|
||||
#define COLOR_RED "#FF0000"
|
||||
#define COLOR_MOSTLY_PURE_RED "#FF3300"
|
||||
#define COLOR_DARK_RED "#A50824"
|
||||
#define COLOR_RED_LIGHT "#FF3333"
|
||||
#define COLOR_MAROON "#800000"
|
||||
#define COLOR_VIVID_RED "#FF3232"
|
||||
#define COLOR_LIGHT_GRAYISH_RED "#E4C7C5"
|
||||
#define COLOR_SOFT_RED "#FA8282"
|
||||
#define COLOR_BUBBLEGUM_RED "#950A0A"
|
||||
|
||||
#define COLOR_YELLOW "#FFFF00"
|
||||
#define COLOR_VIVID_YELLOW "#FBFF23"
|
||||
#define COLOR_VERY_SOFT_YELLOW "#FAE48E"
|
||||
|
||||
#define COLOR_OLIVE "#808000"
|
||||
#define COLOR_VIBRANT_LIME "#00FF00"
|
||||
#define COLOR_LIME "#32CD32"
|
||||
#define COLOR_DARK_LIME "#00aa00"
|
||||
#define COLOR_VERY_PALE_LIME_GREEN "#DDFFD3"
|
||||
#define COLOR_VERY_DARK_LIME_GREEN "#003300"
|
||||
#define COLOR_GREEN "#008000"
|
||||
#define COLOR_DARK_MODERATE_LIME_GREEN "#44964A"
|
||||
|
||||
#define COLOR_CYAN "#00FFFF"
|
||||
#define COLOR_DARK_CYAN "#00A2FF"
|
||||
#define COLOR_TEAL "#008080"
|
||||
#define COLOR_BLUE "#0000FF"
|
||||
#define COLOR_STRONG_BLUE "#1919c8"
|
||||
#define COLOR_BRIGHT_BLUE "#2CB2E8"
|
||||
#define COLOR_MODERATE_BLUE "#555CC2"
|
||||
#define COLOR_AMETHYST "#822BFF"
|
||||
#define COLOR_BLUE_LIGHT "#33CCFF"
|
||||
#define COLOR_NAVY "#000080"
|
||||
#define COLOR_BLUE_GRAY "#75A2BB"
|
||||
|
||||
#define COLOR_PINK "#FFC0CB"
|
||||
#define COLOR_LIGHT_PINK "#ff3cc8"
|
||||
#define COLOR_MOSTLY_PURE_PINK "#E4005B"
|
||||
#define COLOR_MAGENTA "#FF00FF"
|
||||
#define COLOR_STRONG_MAGENTA "#B800B8"
|
||||
#define COLOR_PURPLE "#800080"
|
||||
#define COLOR_VIOLET "#B900F7"
|
||||
#define COLOR_STRONG_VIOLET "#6927c5"
|
||||
|
||||
#define COLOR_ORANGE "#FF9900"
|
||||
#define COLOR_MOSTLY_PURE_ORANGE "#ff8000"
|
||||
#define COLOR_TAN_ORANGE "#FF7B00"
|
||||
#define COLOR_BRIGHT_ORANGE "#E2853D"
|
||||
#define COLOR_LIGHT_ORANGE "#ffc44d"
|
||||
#define COLOR_PALE_ORANGE "#FFBE9D"
|
||||
#define COLOR_BEIGE "#CEB689"
|
||||
#define COLOR_DARK_ORANGE "#C3630C"
|
||||
#define COLOR_DARK_MODERATE_ORANGE "#8B633B"
|
||||
|
||||
#define COLOR_BROWN "#BA9F6D"
|
||||
#define COLOR_DARK_BROWN "#997C4F"
|
||||
#define COLOR_ORANGE_BROWN "#a9734f"
|
||||
|
||||
//Color defines used by the soapstone (based on readability against grey tiles)
|
||||
#define COLOR_SOAPSTONE_PLASTIC "#a19d94"
|
||||
#define COLOR_SOAPSTONE_IRON "#b2b2b2"
|
||||
#define COLOR_SOAPSTONE_BRONZE "#FE8001"
|
||||
#define COLOR_SOAPSTONE_SILVER "#FFFFFF"
|
||||
#define COLOR_SOAPSTONE_GOLD "#FFD900"
|
||||
#define COLOR_SOAPSTONE_DIAMOND "#00ffee"
|
||||
|
||||
#define COLOR_GREEN_GRAY "#99BB76"
|
||||
#define COLOR_RED_GRAY "#B4696A"
|
||||
#define COLOR_PALE_BLUE_GRAY "#98C5DF"
|
||||
#define COLOR_PALE_GREEN_GRAY "#B7D993"
|
||||
#define COLOR_PALE_RED_GRAY "#D59998"
|
||||
#define COLOR_PALE_PURPLE_GRAY "#CBB1CA"
|
||||
#define COLOR_PURPLE_GRAY "#AE8CA8"
|
||||
|
||||
//Color defines used by the assembly detailer.
|
||||
#define COLOR_ASSEMBLY_BLACK "#545454"
|
||||
#define COLOR_ASSEMBLY_BGRAY "#9497AB"
|
||||
#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
|
||||
#define COLOR_ASSEMBLY_RED "#CC4242"
|
||||
#define COLOR_ASSEMBLY_ORANGE "#E39751"
|
||||
#define COLOR_ASSEMBLY_BEIGE "#AF9366"
|
||||
#define COLOR_ASSEMBLY_BROWN "#97670E"
|
||||
#define COLOR_ASSEMBLY_GOLD "#AA9100"
|
||||
#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
|
||||
#define COLOR_ASSEMBLY_GURKHA "#999875"
|
||||
#define COLOR_ASSEMBLY_LGREEN "#789876"
|
||||
#define COLOR_ASSEMBLY_GREEN "#44843C"
|
||||
#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
|
||||
#define COLOR_ASSEMBLY_BLUE "#38559E"
|
||||
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
|
||||
|
||||
///Colors for xenobiology vatgrowing
|
||||
#define COLOR_SAMPLE_YELLOW "#c0b823"
|
||||
#define COLOR_SAMPLE_PURPLE "#342941"
|
||||
#define COLOR_SAMPLE_GREEN "#98b944"
|
||||
#define COLOR_SAMPLE_BROWN "#91542d"
|
||||
#define COLOR_SAMPLE_GRAY "#5e5856"
|
||||
|
||||
///Main colors for UI themes
|
||||
#define COLOR_THEME_MIDNIGHT "#6086A0"
|
||||
#define COLOR_THEME_PLASMAFIRE "#FFB200"
|
||||
#define COLOR_THEME_RETRO "#24CA00"
|
||||
#define COLOR_THEME_SLIMECORE "#4FB259"
|
||||
#define COLOR_THEME_OPERATIVE "#B8221F"
|
||||
#define COLOR_THEME_GLASS "#75A4C4"
|
||||
#define COLOR_THEME_CLOCKWORK "#CFBA47"
|
||||
|
||||
///Colors for eigenstates
|
||||
#define COLOR_PERIWINKLEE "#9999FF"
|
||||
/**
|
||||
* Some defines to generalise colours used in lighting.
|
||||
*
|
||||
* Important note: colors can end up significantly different from the basic html picture, especially when saturated
|
||||
*/
|
||||
/// Bright but quickly dissipating neon green. rgb(100, 200, 100)
|
||||
#define LIGHT_COLOR_GREEN "#64C864"
|
||||
/// Electric green. rgb(0, 255, 0)
|
||||
#define LIGHT_COLOR_ELECTRIC_GREEN "#00FF00"
|
||||
/// Cold, diluted blue. rgb(100, 150, 250)
|
||||
#define LIGHT_COLOR_BLUE "#6496FA"
|
||||
/// Light blueish green. rgb(125, 225, 175)
|
||||
#define LIGHT_COLOR_BLUEGREEN "#7DE1AF"
|
||||
/// Diluted cyan. rgb(125, 225, 225)
|
||||
#define LIGHT_COLOR_CYAN "#7DE1E1"
|
||||
/// Electric cyan rgb(0, 255, 255)
|
||||
#define LIGHT_COLOR_ELECTRIC_CYAN "#00FFFF"
|
||||
/// More-saturated cyan. rgb(64, 206, 255)
|
||||
#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF"
|
||||
/// Saturated blue. rgb(51, 117, 248)
|
||||
#define LIGHT_COLOR_DARK_BLUE "#6496FA"
|
||||
/// Diluted, mid-warmth pink. rgb(225, 125, 225)
|
||||
#define LIGHT_COLOR_PINK "#E17DE1"
|
||||
/// Dimmed yellow, leaning kaki. rgb(225, 225, 125)
|
||||
#define LIGHT_COLOR_YELLOW "#E1E17D"
|
||||
/// Clear brown, mostly dim. rgb(150, 100, 50)
|
||||
#define LIGHT_COLOR_BROWN "#966432"
|
||||
/// Mostly pure orange. rgb(250, 150, 50)
|
||||
#define LIGHT_COLOR_ORANGE "#FA9632"
|
||||
/// Light Purple. rgb(149, 44, 244)
|
||||
#define LIGHT_COLOR_PURPLE "#952CF4"
|
||||
/// Less-saturated light purple. rgb(155, 81, 255)
|
||||
#define LIGHT_COLOR_LAVENDER "#9B51FF"
|
||||
///slightly desaturated bright yellow.
|
||||
#define LIGHT_COLOR_HOLY_MAGIC "#FFF743"
|
||||
/// deep crimson
|
||||
#define LIGHT_COLOR_BLOOD_MAGIC "#D00000"
|
||||
|
||||
/* These ones aren't a direct colour like the ones above, because nothing would fit */
|
||||
/// Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25)
|
||||
#define LIGHT_COLOR_FIRE "#FAA019"
|
||||
/// Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24)
|
||||
#define LIGHT_COLOR_LAVA "#C48A18"
|
||||
/// Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75)
|
||||
#define LIGHT_COLOR_FLARE "#FA644B"
|
||||
/// Weird color, between yellow and green, very slimy. rgb(175, 200, 75)
|
||||
#define LIGHT_COLOR_SLIME_LAMP "#AFC84B"
|
||||
/// Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
|
||||
#define LIGHT_COLOR_TUNGSTEN "#FAE1AF"
|
||||
/// Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250)
|
||||
#define LIGHT_COLOR_HALOGEN "#F0FAFA"
|
||||
|
||||
//The GAGS greyscale_colors for each department's computer/machine circuits
|
||||
#define CIRCUIT_COLOR_GENERIC "#1A7A13"
|
||||
#define CIRCUIT_COLOR_COMMAND "#1B4594"
|
||||
#define CIRCUIT_COLOR_SECURITY "#9A151E"
|
||||
#define CIRCUIT_COLOR_SCIENCE "#BC4A9B"
|
||||
#define CIRCUIT_COLOR_SERVICE "#92DCBA"
|
||||
#define CIRCUIT_COLOR_MEDICAL "#00CCFF"
|
||||
#define CIRCUIT_COLOR_ENGINEERING "#F8D700"
|
||||
#define CIRCUIT_COLOR_SUPPLY "#C47749"
|
||||
|
||||
/// Colors for pride week
|
||||
#define COLOR_PRIDE_RED "#FF6666"
|
||||
#define COLOR_PRIDE_ORANGE "#FC9F3C"
|
||||
#define COLOR_PRIDE_YELLOW "#EAFF51"
|
||||
#define COLOR_PRIDE_GREEN "#41FC66"
|
||||
#define COLOR_PRIDE_BLUE "#42FFF2"
|
||||
#define COLOR_PRIDE_PURPLE "#5D5DFC"
|
||||
@@ -0,0 +1,4 @@
|
||||
//Luma coefficients suggested for HDTVs. If you change these, make sure they add up to 1.
|
||||
#define LUMA_R 0.213
|
||||
#define LUMA_G 0.715
|
||||
#define LUMA_B 0.072
|
||||
@@ -1,62 +0,0 @@
|
||||
// This is eventually for wjohn to add more color standardization stuff like I keep asking him >:(
|
||||
|
||||
#define COLOR_INPUT_DISABLED "#F0F0F0"
|
||||
#define COLOR_INPUT_ENABLED "#D3B5B5"
|
||||
#define COLOR_FLOORTILE_GRAY "#8D8B8B"
|
||||
#define COLOR_ALMOST_BLACK "#333333"
|
||||
#define COLOR_BLACK "#000000"
|
||||
#define COLOR_RED "#FF0000"
|
||||
#define COLOR_RED_LIGHT "#FF3333"
|
||||
#define COLOR_MAROON "#800000"
|
||||
#define COLOR_YELLOW "#FFFF00"
|
||||
#define COLOR_OLIVE "#808000"
|
||||
#define COLOR_LIME "#32CD32"
|
||||
#define COLOR_GREEN "#008000"
|
||||
#define COLOR_CYAN "#00FFFF"
|
||||
#define COLOR_TEAL "#008080"
|
||||
#define COLOR_BLUE "#0000FF"
|
||||
#define COLOR_BLUE_LIGHT "#33CCFF"
|
||||
#define COLOR_NAVY "#000080"
|
||||
#define COLOR_PINK "#FFC0CB"
|
||||
#define COLOR_MAGENTA "#FF00FF"
|
||||
#define COLOR_PURPLE "#800080"
|
||||
#define COLOR_ORANGE "#FF9900"
|
||||
#define COLOR_BEIGE "#CEB689"
|
||||
#define COLOR_BLUE_GRAY "#75A2BB"
|
||||
#define COLOR_BROWN "#BA9F6D"
|
||||
#define COLOR_SOFT_RED "#FA8282"
|
||||
#define COLOR_DARK_BROWN "#997C4F"
|
||||
#define COLOR_DARK_ORANGE "#C3630C"
|
||||
#define COLOR_GREEN_GRAY "#99BB76"
|
||||
#define COLOR_RED_GRAY "#B4696A"
|
||||
#define COLOR_PALE_BLUE_GRAY "#98C5DF"
|
||||
#define COLOR_PALE_GREEN_GRAY "#B7D993"
|
||||
#define COLOR_PALE_ORANGE "#FFC066"
|
||||
#define COLOR_PALE_RED_GRAY "#D59998"
|
||||
#define COLOR_PALE_PURPLE_GRAY "#CBB1CA"
|
||||
#define COLOR_PURPLE_GRAY "#AE8CA8"
|
||||
|
||||
// Color defines used by the assembly detailer.
|
||||
#define COLOR_ASSEMBLY_BLACK "#545454"
|
||||
#define COLOR_ASSEMBLY_BGRAY "#9497AB"
|
||||
#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
|
||||
#define COLOR_ASSEMBLY_RED "#CC4242"
|
||||
#define COLOR_ASSEMBLY_ORANGE "#E39751"
|
||||
#define COLOR_ASSEMBLY_BEIGE "#AF9366"
|
||||
#define COLOR_ASSEMBLY_BROWN "#97670E"
|
||||
#define COLOR_ASSEMBLY_GOLD "#AA9100"
|
||||
#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
|
||||
#define COLOR_ASSEMBLY_GURKHA "#999875"
|
||||
#define COLOR_ASSEMBLY_LGREEN "#789876"
|
||||
#define COLOR_ASSEMBLY_GREEN "#44843C"
|
||||
#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
|
||||
#define COLOR_ASSEMBLY_BLUE "#38559E"
|
||||
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
|
||||
#define COLOR_ASSEMBLY_PINK "#ff4adc"
|
||||
|
||||
#define COLOR_WHITE "#FFFFFF"
|
||||
#define COLOR_VERY_LIGHT_GRAY "#EEEEEE"
|
||||
#define COLOR_SILVER "#C0C0C0"
|
||||
#define COLOR_GRAY "#808080"
|
||||
#define COLOR_HALF_TRANSPARENT_BLACK "#0000007A"
|
||||
#define COLOR_BRIGHT_BLUE "#2CB2E8"
|
||||
@@ -25,6 +25,15 @@
|
||||
/// Do not allow this random event to continue.
|
||||
#define CANCEL_PRE_RANDOM_EVENT (1<<0)
|
||||
|
||||
/// a weather event of some kind occured
|
||||
#define COMSIG_WEATHER_TELEGRAPH(event_type) "!weather_telegraph [event_type]"
|
||||
#define COMSIG_WEATHER_START(event_type) "!weather_start [event_type]"
|
||||
#define COMSIG_WEATHER_WINDDOWN(event_type) "!weather_winddown [event_type]"
|
||||
#define COMSIG_WEATHER_END(event_type) "!weather_end [event_type]"
|
||||
|
||||
/// called by auxgm add_gas: (gas_id)
|
||||
#define COMSIG_GLOB_NEW_GAS "!new_gas"
|
||||
|
||||
// signals from globally accessible objects
|
||||
/// from SSsun when the sun changes position : (primary_sun, suns)
|
||||
#define COMSIG_SUN_MOVED "sun_moved"
|
||||
@@ -45,6 +54,8 @@
|
||||
#define COMSIG_PARENT_QDELETING "parent_qdeleting"
|
||||
/// generic topic handler (usr, href_list)
|
||||
#define COMSIG_TOPIC "handle_topic"
|
||||
/// from datum ui_act (usr, action)
|
||||
#define COMSIG_UI_ACT "COMSIG_UI_ACT"
|
||||
|
||||
/// fires on the target datum when an element is attached to it (/datum/element)
|
||||
#define COMSIG_ELEMENT_ATTACH "element_attach"
|
||||
@@ -415,6 +426,12 @@
|
||||
///from /obj/machinery/obj_break(damage_flag): (damage_flag)
|
||||
#define COMSIG_MACHINERY_BROKEN "machinery_broken"
|
||||
|
||||
// /obj/machinery/power/supermatter_crystal signals
|
||||
/// from /obj/machinery/power/supermatter_crystal/process_atmos(); when the SM delam reaches the point of sounding alarms
|
||||
#define COMSIG_SUPERMATTER_DELAM_START_ALARM "sm_delam_start_alarm"
|
||||
/// from /obj/machinery/power/supermatter_crystal/process_atmos(); when the SM sounds an audible alarm
|
||||
#define COMSIG_SUPERMATTER_DELAM_ALARM "sm_delam_alarm"
|
||||
|
||||
// /obj/item signals
|
||||
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
|
||||
#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob)
|
||||
@@ -455,6 +472,14 @@
|
||||
#define COMSIG_MINE_TRIGGERED "minegoboom" ///from [/obj/effect/mine/proc/triggermine]:
|
||||
// Uncovered information
|
||||
#define COMPONENT_DEEPSCAN_UNCOVERED_INFORMATION 1
|
||||
///Called when an item is being offered, from [/obj/item/proc/on_offered(mob/living/carbon/offerer)]
|
||||
#define COMSIG_ITEM_OFFERING "item_offering"
|
||||
///Interrupts the offer proc
|
||||
#define COMPONENT_OFFER_INTERRUPT (1<<0)
|
||||
///Called when an someone tries accepting an offered item, from [/obj/item/proc/on_offer_taken(mob/living/carbon/offer, mob/living/carbon/taker)]
|
||||
#define COMSIG_ITEM_OFFER_TAKEN "item_offer_taken"
|
||||
///Interrupts the offer acceptance
|
||||
#define COMPONENT_OFFER_TAKE_INTERRUPT (1<<0)
|
||||
///from [/obj/structure/closet/supplypod/proc/endlaunch]:
|
||||
#define COMSIG_SUPPLYPOD_LANDED "supplypodgoboom"
|
||||
|
||||
|
||||
@@ -76,10 +76,9 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
#define isvampire(A) (is_species(A,/datum/species/vampire))
|
||||
#define isdullahan(A) (is_species(A, /datum/species/dullahan))
|
||||
|
||||
#define isangel(A) (is_species(A, /datum/species/angel))
|
||||
#define ismush(A) (is_species(A, /datum/species/mush))
|
||||
#define isshadow(A) (is_species(A, /datum/species/shadow))
|
||||
#define isrobotic(A) (is_species(A, /datum/species/ipc) || is_species(A, /datum/species/synthliz))
|
||||
#define isrobotic(A) (is_species(A, /datum/species/ipc) || is_species(A, /datum/species/synthliz) || is_species(A, /datum/species/mammal/synthetic))
|
||||
#define isdwarf(A) (is_species(A, /datum/species/dwarf))
|
||||
|
||||
// Citadel specific species
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
|
||||
#define CLICKCATCHER_PLANE -99
|
||||
|
||||
#define PLANE_SPACE -95
|
||||
#define PLANE_SPACE -98
|
||||
#define PLANE_SPACE_RENDER_TARGET "PLANE_SPACE"
|
||||
#define PLANE_SPACE_PARALLAX -90
|
||||
|
||||
#define PLANE_SPACE_PARALLAX -95
|
||||
#define PLANE_SPACE_PARALLAX_RENDER_TARGET "PLANE_SPACE_PARALLAX"
|
||||
|
||||
#define OPENSPACE_LAYER 17 //Openspace layer over all
|
||||
@@ -153,6 +154,10 @@
|
||||
#define CAMERA_STATIC_LAYER 19
|
||||
#define CAMERA_STATIC_RENDER_TARGET "CAMERA_STATIC_PLANE"
|
||||
|
||||
/// Plane for balloon text (text that fades up)
|
||||
/// It's over lighting and every other crap because this is nearly as important as hud content and only visible to the user.
|
||||
#define BALLOON_CHAT_PLANE 20
|
||||
|
||||
//HUD layer defines
|
||||
|
||||
#define FULLSCREEN_PLANE 20
|
||||
|
||||
@@ -30,31 +30,6 @@
|
||||
//Important note on colors. Colors can end up significantly different from the basic html picture, especially when saturated
|
||||
#define LIGHT_COLOR_WHITE "#FFFFFF"
|
||||
#define LIGHT_COLOR_RED "#FA8282" //Warm but extremely diluted red. rgb(250, 130, 130)
|
||||
#define LIGHT_COLOR_GREEN "#64C864" //Bright but quickly dissipating neon green. rgb(100, 200, 100)
|
||||
#define LIGHT_COLOR_BLUE "#6496FA" //Cold, diluted blue. rgb(100, 150, 250)
|
||||
|
||||
#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" //Light blueish green. rgb(125, 225, 175)
|
||||
#define LIGHT_COLOR_PALEBLUE "#7DAFE1" //A pale blue-ish color. rgb(125, 175, 225)
|
||||
#define LIGHT_COLOR_CYAN "#7DE1E1" //Diluted cyan. rgb(125, 225, 225)
|
||||
#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF" //More-saturated cyan. rgb(64, 206, 255)
|
||||
#define LIGHT_COLOR_DARK_BLUE "#6496FA" //Saturated blue. rgb(51, 117, 248)
|
||||
#define LIGHT_COLOR_PINK "#E17DE1" //Diluted, mid-warmth pink. rgb(225, 125, 225)
|
||||
#define LIGHT_COLOR_YELLOW "#E1E17D" //Dimmed yellow, leaning kaki. rgb(225, 225, 125)
|
||||
#define LIGHT_COLOR_BROWN "#966432" //Clear brown, mostly dim. rgb(150, 100, 50)
|
||||
#define LIGHT_COLOR_ORANGE "#FA9632" //Mostly pure orange. rgb(250, 150, 50)
|
||||
#define LIGHT_COLOR_PURPLE "#952CF4" //Light Purple. rgb(149, 44, 244)
|
||||
#define LIGHT_COLOR_LAVENDER "#9B51FF" //Less-saturated light purple. rgb(155, 81, 255)
|
||||
|
||||
#define LIGHT_COLOR_HOLY_MAGIC "#FFF743" //slightly desaturated bright yellow.
|
||||
#define LIGHT_COLOR_BLOOD_MAGIC "#D00000" //deep crimson
|
||||
|
||||
//These ones aren't a direct colour like the ones above, because nothing would fit
|
||||
#define LIGHT_COLOR_FIRE "#FAA019" //Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25)
|
||||
#define LIGHT_COLOR_LAVA "#C48A18" //Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24)
|
||||
#define LIGHT_COLOR_FLARE "#FA644B" //Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75)
|
||||
#define LIGHT_COLOR_SLIME_LAMP "#AFC84B" //Weird color, between yellow and green, very slimy. rgb(175, 200, 75)
|
||||
#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" //Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
|
||||
#define LIGHT_COLOR_HALOGEN "#F0FAFA" //Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250)
|
||||
|
||||
#define LIGHT_RANGE_FIRE 3 //How many tiles standard fires glow.
|
||||
|
||||
|
||||
@@ -40,15 +40,16 @@
|
||||
#define LOG_ASAY (1 << 15)
|
||||
#define LOG_VIRUS (1 << 16)
|
||||
#define LOG_SHUTTLE (1 << 18)
|
||||
#define LOG_VICTIM (1 << 19)
|
||||
|
||||
//Individual logging panel pages
|
||||
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK)
|
||||
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK | LOG_VICTIM)
|
||||
#define INDIVIDUAL_SAY_LOG (LOG_SAY | LOG_WHISPER | LOG_DSAY)
|
||||
#define INDIVIDUAL_EMOTE_LOG (LOG_EMOTE | LOG_SUBTLER)
|
||||
#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)
|
||||
#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 LOGSRC_CLIENT "Client"
|
||||
#define LOGSRC_MOB "Mob"
|
||||
|
||||
+18
-11
@@ -48,32 +48,39 @@
|
||||
#define MC_CHARGE "CHARGE"
|
||||
#define MC_AI "AI"
|
||||
#define MC_SENSORS "SENSORS"
|
||||
#define MC_SIGNALER "SIGNALER"
|
||||
|
||||
//NTNet stuff, for modular computers
|
||||
// NTNet module-configuration values. Do not change these. If you need to add another use larger number (5..6..7 etc)
|
||||
#define NTNET_SOFTWAREDOWNLOAD 1 // Downloads of software from NTNet
|
||||
#define NTNET_PEERTOPEER 2 // P2P transfers of files between devices
|
||||
#define NTNET_COMMUNICATION 3 // Communication (messaging)
|
||||
#define NTNET_SYSTEMCONTROL 4 // Control of various systems, RCon, air alarm control, etc.
|
||||
#define NTNET_SOFTWAREDOWNLOAD 1 // Downloads of software from NTNet
|
||||
#define NTNET_PEERTOPEER 2 // P2P transfers of files between devices
|
||||
#define NTNET_COMMUNICATION 3 // Communication (messaging)
|
||||
#define NTNET_SYSTEMCONTROL 4 // Control of various systems, RCon, air alarm control, etc.
|
||||
|
||||
//NTNet transfer speeds, used when downloading/uploading a file/program.
|
||||
#define NTNETSPEED_LOWSIGNAL 0.5 // GQ/s transfer speed when the device is wirelessly connected and on Low signal
|
||||
#define NTNETSPEED_HIGHSIGNAL 1 // GQ/s transfer speed when the device is wirelessly connected and on High signal
|
||||
#define NTNETSPEED_ETHERNET 2 // GQ/s transfer speed when the device is using wired connection
|
||||
#define NTNETSPEED_LOWSIGNAL 0.5 // GQ/s transfer speed when the device is wirelessly connected and on Low signal
|
||||
#define NTNETSPEED_HIGHSIGNAL 1 // GQ/s transfer speed when the device is wirelessly connected and on High signal
|
||||
#define NTNETSPEED_ETHERNET 2 // GQ/s transfer speed when the device is using wired connection
|
||||
|
||||
//Caps for NTNet logging. Less than 10 would make logging useless anyway, more than 500 may make the log browser too laggy. Defaults to 100 unless user changes it.
|
||||
#define MAX_NTNET_LOGS 300
|
||||
#define MIN_NTNET_LOGS 10
|
||||
|
||||
//Program bitflags
|
||||
#define PROGRAM_ALL (~0)
|
||||
#define PROGRAM_CONSOLE (1<<0)
|
||||
#define PROGRAM_LAPTOP (1<<1)
|
||||
#define PROGRAM_TABLET (1<<2)
|
||||
#define PROGRAM_ALL (~0)
|
||||
#define PROGRAM_CONSOLE (1<<0)
|
||||
#define PROGRAM_LAPTOP (1<<1)
|
||||
#define PROGRAM_TABLET (1<<2)
|
||||
//Program states
|
||||
#define PROGRAM_STATE_KILLED 0
|
||||
#define PROGRAM_STATE_BACKGROUND 1
|
||||
#define PROGRAM_STATE_ACTIVE 2
|
||||
//Program categories
|
||||
#define PROGRAM_CATEGORY_CREW "Crew"
|
||||
#define PROGRAM_CATEGORY_ENGI "Engineering"
|
||||
#define PROGRAM_CATEGORY_ROBO "Robotics"
|
||||
#define PROGRAM_CATEGORY_SUPL "Supply"
|
||||
#define PROGRAM_CATEGORY_MISC "Other"
|
||||
|
||||
#define FIREDOOR_OPEN 1
|
||||
#define FIREDOOR_CLOSED 2
|
||||
|
||||
+8
-13
@@ -323,6 +323,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define FIRST_DIAG_STEP 1
|
||||
#define SECOND_DIAG_STEP 2
|
||||
|
||||
#define DEADCHAT_ANNOUNCEMENT "announcement"
|
||||
#define DEADCHAT_ARRIVALRATTLE "arrivalrattle"
|
||||
#define DEADCHAT_DEATHRATTLE "deathrattle"
|
||||
#define DEADCHAT_REGULAR "regular-deadchat"
|
||||
@@ -344,18 +345,6 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
//TODO Move to a pref
|
||||
#define STATION_GOAL_BUDGET 1
|
||||
|
||||
//Luma coefficients suggested for HDTVs. If you change these, make sure they add up to 1.
|
||||
#define LUMA_R 0.213
|
||||
#define LUMA_G 0.715
|
||||
#define LUMA_B 0.072
|
||||
|
||||
//different types of atom colorations
|
||||
#define ADMIN_COLOUR_PRIORITY 1 //only used by rare effects like greentext coloring mobs and when admins varedit color
|
||||
#define TEMPORARY_COLOUR_PRIORITY 2 //e.g. purple effect of the revenant on a mob, black effect when mob electrocuted
|
||||
#define WASHABLE_COLOUR_PRIORITY 3 //color splashed onto an atom (e.g. paint on turf)
|
||||
#define FIXED_COLOUR_PRIORITY 4 //color inherent to the atom (e.g. blob color)
|
||||
#define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are.
|
||||
|
||||
//Endgame Results
|
||||
#define NUKE_NEAR_MISS 1
|
||||
#define NUKE_MISS_STATION 2
|
||||
@@ -379,7 +368,8 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define CLOCK_SILICONS 22
|
||||
#define CLOCK_PROSELYTIZATION 23
|
||||
#define SHUTTLE_HIJACK 24
|
||||
#define GANG_VICTORY 25
|
||||
#define GANG_DESTROYED 25
|
||||
#define GANG_OPERATING 26
|
||||
|
||||
#define FIELD_TURF 1
|
||||
#define FIELD_EDGE 2
|
||||
@@ -567,3 +557,8 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define SHOES_KNOTTED 2
|
||||
|
||||
#define WANTED_FILE "wanted_message.json"
|
||||
|
||||
// Notification action types
|
||||
#define NOTIFY_JUMP "jump"
|
||||
#define NOTIFY_ATTACK "attack"
|
||||
#define NOTIFY_ORBIT "orbit"
|
||||
|
||||
@@ -295,7 +295,7 @@
|
||||
#define APPRENTICE_AGE_MIN 29 // youngest an apprentice can be
|
||||
#define SHOES_SLOWDOWN 0 // How much shoes slow you down by default. Negative values speed you up
|
||||
#define SHOES_SPEED_SLIGHT SHOES_SLOWDOWN - 1 // slightest speed boost to movement
|
||||
#define POCKET_STRIP_DELAY 40 // time taken (in deciseconds) to search somebody's pockets
|
||||
#define POCKET_STRIP_DELAY (4 SECONDS) //time taken to search somebody's pockets
|
||||
#define DOOR_CRUSH_DAMAGE 15 // the amount of damage that airlocks deal when they crush you
|
||||
|
||||
#define HUNGER_FACTOR 0.1 // factor at which mob nutrition decreases
|
||||
|
||||
@@ -34,12 +34,6 @@
|
||||
|
||||
#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO|CHAT_LOOC|CHAT_BANKCARD)
|
||||
|
||||
#define PARALLAX_INSANE -1 //for show offs
|
||||
#define PARALLAX_HIGH 0 //default.
|
||||
#define PARALLAX_MED 1
|
||||
#define PARALLAX_LOW 2
|
||||
#define PARALLAX_DISABLE 3 //this option must be the highest number
|
||||
|
||||
#define PIXEL_SCALING_AUTO 0
|
||||
#define PIXEL_SCALING_1X 1
|
||||
#define PIXEL_SCALING_1_2X 1.5
|
||||
@@ -50,10 +44,6 @@
|
||||
#define SCALING_METHOD_DISTORT "distort"
|
||||
#define SCALING_METHOD_BLUR "blur"
|
||||
|
||||
#define PARALLAX_DELAY_DEFAULT world.tick_lag
|
||||
#define PARALLAX_DELAY_MED 1
|
||||
#define PARALLAX_DELAY_LOW 2
|
||||
|
||||
#define SEC_DEPT_NONE "None"
|
||||
#define SEC_DEPT_RANDOM "Random"
|
||||
#define SEC_DEPT_ENGINEERING "Engineering"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#define NITRYL_FORMATION_ENERGY 100000
|
||||
#define TRITIUM_BURN_OXY_FACTOR 100
|
||||
#define TRITIUM_BURN_TRIT_FACTOR 10
|
||||
#define TRITIUM_BURN_RADIOACTIVITY_FACTOR 50000 //The neutrons gotta go somewhere. Completely arbitrary number.
|
||||
#define TRITIUM_BURN_RADIOACTIVITY_FACTOR 5000 //The neutrons gotta go somewhere. Completely arbitrary number.
|
||||
#define TRITIUM_MINIMUM_RADIATION_ENERGY 0.1 //minimum 0.01 moles trit or 10 moles oxygen to start producing rads
|
||||
#define SUPER_SATURATION_THRESHOLD 96
|
||||
#define STIMULUM_HEAT_SCALE 100000
|
||||
|
||||
@@ -60,11 +60,8 @@
|
||||
#define ANTAG_HUD_BROTHER 23
|
||||
#define ANTAG_HUD_BLOODSUCKER 24
|
||||
#define ANTAG_HUD_FUGITIVE 25
|
||||
#define ANTAG_HUD_HERETIC 26
|
||||
|
||||
// Notification action types
|
||||
#define NOTIFY_JUMP "jump"
|
||||
#define NOTIFY_ATTACK "attack"
|
||||
#define NOTIFY_ORBIT "orbit"
|
||||
#define ANTAG_HUD_HERETIC 26
|
||||
#define ANTAG_HUD_SPACECOP 27
|
||||
#define ANTAG_HUD_GANGSTER 28
|
||||
|
||||
#define ADD_HUD_TO_COOLDOWN 20 //cooldown for being shown the images for any particular data hud
|
||||
@@ -0,0 +1,13 @@
|
||||
#define PARALLAX_DELAY_DEFAULT world.tick_lag
|
||||
#define PARALLAX_DELAY_MED 1
|
||||
#define PARALLAX_DELAY_LOW 2
|
||||
|
||||
// WARNING - client.prefs uses this, if you change these make sure to update the code in preferences!
|
||||
#define PARALLAX_DISABLE 0
|
||||
#define PARALLAX_LOW 1
|
||||
#define PARALLAX_MED 2
|
||||
#define PARALLAX_HIGH 3
|
||||
#define PARALLAX_INSANE 4 // default
|
||||
|
||||
// keep this false until we can fix it being a seizure hazard/ugly as sin
|
||||
#define PARALLAX_ROTATION_ANIMATIONS FALSE
|
||||
@@ -73,4 +73,6 @@
|
||||
TECHWEB_POINT_TYPE_GENERIC = "General Research"\
|
||||
)
|
||||
|
||||
#define TECHWEB_BOMB_POINTCAP 50000 //Adjust as needed; Stops toxins from nullifying RND progression mechanics. Current Value Cap Radius: 100
|
||||
#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 200 // The shockwave radius required for a bomb to get TECHWEB_BOMB_MIDPOINT points.
|
||||
#define BOMB_SUB_TARGET_EXPONENT 2 // The power of the points curve below the target size. Higher = less points for worse bombs, below target.
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
#define ROLE_DEATHSQUAD "deathsquad"
|
||||
#define ROLE_LAVALAND "lavaland"
|
||||
#define ROLE_INTERNAL_AFFAIRS "internal affairs agent"
|
||||
#define ROLE_GANG "gangster"
|
||||
#define ROLE_FAMILIES "family boss"
|
||||
#define ROLE_FAMILY_HEAD_ASPIRANT "family head aspirant"
|
||||
#define ROLE_BLOODSUCKER "bloodsucker"
|
||||
#define ROLE_SPACE_DRAGON "Space Dragon"
|
||||
//#define ROLE_MONSTERHUNTER "monster hunter" Disabled for now
|
||||
@@ -72,9 +73,9 @@ GLOBAL_LIST_INIT(special_roles, list(
|
||||
ROLE_OVERTHROW = /datum/game_mode/overthrow,
|
||||
ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs,
|
||||
ROLE_SENTIENCE,
|
||||
ROLE_GANG = /datum/game_mode/gang,
|
||||
ROLE_HERETIC = /datum/game_mode/heretics,
|
||||
ROLE_BLOODSUCKER = /datum/game_mode/bloodsucker,
|
||||
ROLE_FAMILIES = /datum/game_mode/gang,
|
||||
ROLE_SPACE_DRAGON
|
||||
//ROLE_MONSTERHUNTER Disabled for now
|
||||
))
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
|
||||
#define SHUTTLE_TRANSIT_BORDER 10
|
||||
|
||||
#define PARALLAX_LOOP_TIME 25
|
||||
#define HYPERSPACE_END_TIME 5
|
||||
|
||||
#define HYPERSPACE_WARMUP 1
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#define span_greenannounce(str) ("<span class='greenannounce'>" + str + "</span>")
|
||||
#define span_greenteamradio(str) ("<span class='greenteamradio'>" + str + "</span>")
|
||||
#define span_greentext(str) ("<span class='greentext'>" + str + "</span>")
|
||||
#define span_gangradio(str) ("<span class='gangradio'>" + str + "</span>")
|
||||
#define span_hear(str) ("<span class='hear'>" + str + "</span>")
|
||||
#define span_hidden(str) ("<span class='hidden'>" + str + "</span>")
|
||||
#define span_hierophant(str) ("<span class='hierophant'>" + str + "</span>")
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#define SPECIES_ABDUCTOR "abductor"
|
||||
#define SPECIES_ANDROID "android"
|
||||
#define SPECIES_ANGEL "angel"
|
||||
#define SPECIES_MAMMAL "mammal"
|
||||
#define SPECIES_MAMMAL_SYNTHETIC "mammal_synthetic"
|
||||
#define SPECIES_ARACHNID "arachnid"
|
||||
@@ -53,3 +52,14 @@
|
||||
#define SPECIES_CATEGORY_SHADOW "shadow"
|
||||
#define SPECIES_CATEGORY_SKELETON "skeleton"
|
||||
#define SPECIES_CATEGORY_UNDEAD "undead"
|
||||
|
||||
|
||||
//Species Wing Type Defines ----------------------
|
||||
#define SPECIES_WINGS_ANGEL list("Angel")
|
||||
#define SPECIES_WINGS_DRAGON list("Dragon") //could also be considered demon wings or bat wings?
|
||||
#define SPECIES_WINGS_ROBOT list("Robotic")
|
||||
#define SPECIES_WINGS_INSECT list("Fly") //"hey when can we have something besides giant fly wings?" "when you sprite it!"
|
||||
#define SPECIES_WINGS_SKELETAL list("Skeleton")
|
||||
#define SPECIES_WINGS_MOTH list("Megamoth","Mothra")
|
||||
#define SPECIES_WINGS_JELLY list("Angel") //no actual slime wings present right now, but I'm making this in the event someone wants to sprite slime wings.
|
||||
#define SPECIES_WINGS_ALL list("Angel","Dragon","Robotic","Fly","Skeleton","Megamoth","Mothra") //keep this updated
|
||||
|
||||
@@ -136,6 +136,10 @@
|
||||
|
||||
#define STATUS_EFFECT_INLOVE /datum/status_effect/in_love //Displays you as being in love with someone else, and makes hearts appear around them.
|
||||
|
||||
#define STATUS_EFFECT_OFFERING /datum/status_effect/offering // you are offering up an item to people
|
||||
|
||||
#define STATUS_EFFECT_HANDSHAKE /datum/status_effect/offering/secret_handshake // you are attempting to perform a secret Family handshake
|
||||
|
||||
/////////////
|
||||
// SLIME //
|
||||
/////////////
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// All of these must be matched in StripMenu.js.
|
||||
#define STRIPPABLE_ITEM_HEAD "head"
|
||||
#define STRIPPABLE_ITEM_BACK "back"
|
||||
#define STRIPPABLE_ITEM_MASK "mask"
|
||||
#define STRIPPABLE_ITEM_NECK "neck"
|
||||
#define STRIPPABLE_ITEM_EYES "eyes"
|
||||
#define STRIPPABLE_ITEM_EARS "ears"
|
||||
#define STRIPPABLE_ITEM_JUMPSUIT "jumpsuit"
|
||||
#define STRIPPABLE_ITEM_SUIT "suit"
|
||||
#define STRIPPABLE_ITEM_GLOVES "gloves"
|
||||
#define STRIPPABLE_ITEM_FEET "shoes"
|
||||
#define STRIPPABLE_ITEM_SUIT_STORAGE "suit_storage"
|
||||
#define STRIPPABLE_ITEM_ID "id"
|
||||
#define STRIPPABLE_ITEM_BELT "belt"
|
||||
#define STRIPPABLE_ITEM_LPOCKET "left_pocket"
|
||||
#define STRIPPABLE_ITEM_RPOCKET "right_pocket"
|
||||
#define STRIPPABLE_ITEM_LHAND "left_hand"
|
||||
#define STRIPPABLE_ITEM_RHAND "right_hand"
|
||||
#define STRIPPABLE_ITEM_HANDCUFFS "handcuffs"
|
||||
#define STRIPPABLE_ITEM_LEGCUFFS "legcuffs"
|
||||
#define STRIPPABLE_ITEM_CORGI_COLLAR "corgi_collar"
|
||||
#define STRIPPABLE_ITEM_PARROT_HEADSET "parrot_headset"
|
||||
|
||||
/// This slot is not obscured.
|
||||
#define STRIPPABLE_OBSCURING_NONE 0
|
||||
|
||||
/// This slot is completely obscured, and cannot be accessed.
|
||||
#define STRIPPABLE_OBSCURING_COMPLETELY 1
|
||||
|
||||
/// This slot can't be seen, but can be accessed.
|
||||
#define STRIPPABLE_OBSCURING_HIDDEN 2
|
||||
@@ -29,10 +29,10 @@
|
||||
* if the arguments to addtimer are the same as an existing timer, it doesn't create a new timer,
|
||||
* and returns the id of the existing timer
|
||||
*/
|
||||
#define TIMER_UNIQUE (1<<0)
|
||||
#define TIMER_UNIQUE (1<<0)
|
||||
|
||||
///For unique timers: Replace the old timer rather then not start this one
|
||||
#define TIMER_OVERRIDE (1<<1)
|
||||
#define TIMER_OVERRIDE (1<<1)
|
||||
|
||||
/**
|
||||
* Timing should be based on how timing progresses on clients, not the server.
|
||||
@@ -41,20 +41,23 @@
|
||||
* should only be used in conjuction with things that have to progress client side, such as
|
||||
* animate() or sound()
|
||||
*/
|
||||
#define TIMER_CLIENT_TIME (1<<2)
|
||||
#define TIMER_CLIENT_TIME (1<<2)
|
||||
|
||||
///Timer can be stopped using deltimer()
|
||||
#define TIMER_STOPPABLE (1<<3)
|
||||
#define TIMER_STOPPABLE (1<<3)
|
||||
|
||||
///prevents distinguishing identical timers with the wait variable
|
||||
///
|
||||
///To be used with TIMER_UNIQUE
|
||||
#define TIMER_NO_HASH_WAIT (1<<4)
|
||||
#define TIMER_NO_HASH_WAIT (1<<4)
|
||||
|
||||
///Loops the timer repeatedly until qdeleted
|
||||
///
|
||||
///In most cases you want a subsystem instead, so don't use this unless you have a good reason
|
||||
#define TIMER_LOOP (1<<5)
|
||||
#define TIMER_LOOP (1<<5)
|
||||
|
||||
///Delete the timer on parent datum Destroy() and when deltimer'd
|
||||
#define TIMER_DELETE_ME (1<<6)
|
||||
|
||||
///Empty ID define
|
||||
#define TIMER_ID_NULL -1
|
||||
@@ -188,6 +191,7 @@
|
||||
#define FIRE_PRIORITY_CALLBACKS 600
|
||||
// #define FIRE_PRIORITY_EXPLOSIONS 666
|
||||
#define FIRE_PRIORITY_TIMER 700
|
||||
#define FIRE_PRIORITY_SOUND_LOOPS 800
|
||||
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
|
||||
|
||||
// SS runlevels
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/// Prepares a text to be used for maptext. Use this so it doesn't look hideous.
|
||||
#define MAPTEXT(text) {"<span class='maptext'>[##text]</span>"}
|
||||
|
||||
/// Macro from Lummox used to get height from a MeasureText proc
|
||||
#define WXH_TO_HEIGHT(x) text2num(copytext(x, findtextEx(x, "x") + 1))
|
||||
@@ -104,6 +104,7 @@
|
||||
#define TRAIT_RESISTCOLD "resist_cold"
|
||||
#define TRAIT_RESISTHIGHPRESSURE "resist_high_pressure"
|
||||
#define TRAIT_RESISTLOWPRESSURE "resist_low_pressure"
|
||||
#define TRAIT_LOWPRESSURECOOLING "low_pressure_cooling"
|
||||
#define TRAIT_BOMBIMMUNE "bomb_immunity"
|
||||
#define TRAIT_RADIMMUNE "rad_immunity"
|
||||
#define TRAIT_GENELESS "geneless"
|
||||
@@ -121,6 +122,7 @@
|
||||
#define TRAIT_ROBOTIC_ORGANISM "robotic_organism"
|
||||
#define TRAIT_ROBOT_RADSHIELDING "robot_radshielding"
|
||||
#define TRAIT_NOBREATH "no_breath"
|
||||
#define TRAIT_AUXILIARY_LUNGS "auxiliary_lungs" //Lungs not neccessary required due to nobreath, but provides some other helpful function.
|
||||
#define TRAIT_ANTIMAGIC "anti_magic"
|
||||
#define TRAIT_HOLY "holy"
|
||||
#define TRAIT_DEPRESSION "depression"
|
||||
@@ -200,6 +202,7 @@
|
||||
#define TRAIT_FRIENDLY "friendly"
|
||||
#define TRAIT_SNOB "snob"
|
||||
#define TRAIT_MULTILINGUAL "multilingual"
|
||||
#define TRAIT_HEARING_SENSITIVE "hearing_sensitive"
|
||||
#define TRAIT_CULT_EYES "cult_eyes"
|
||||
#define TRAIT_AUTO_CATCH_ITEM "auto_catch_item"
|
||||
#define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman.
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// These are used in uplink_devices.dm to determine whether or not an item is purchasable.
|
||||
|
||||
/// This item is purchasable to traitors
|
||||
#define UPLINK_TRAITORS (1 << 0)
|
||||
|
||||
/// This item is purchasable to nuke ops
|
||||
#define UPLINK_NUKE_OPS (1 << 1)
|
||||
|
||||
/// This item is purchasable to clown ops
|
||||
#define UPLINK_CLOWN_OPS (1 << 2)
|
||||
+100
-50
@@ -1,17 +1,18 @@
|
||||
/*
|
||||
* Holds procs to help with list operations
|
||||
* Contains groups:
|
||||
* Misc
|
||||
* Sorting
|
||||
* Misc
|
||||
* Sorting
|
||||
*/
|
||||
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
|
||||
#define LAZYINITLIST(L) if (!L) L = list()
|
||||
#define LAZYINITLIST(L) if (!L) { L = list(); }
|
||||
#define UNSETEMPTY(L) if (L && !length(L)) L = null
|
||||
#define LAZYCOPY(L) (L ? L.Copy() : list() )
|
||||
///Like LAZYCOPY - copies an input list if the list has entries, If it doesn't the assigned list is nulled
|
||||
#define LAZYLISTDUPLICATE(L) (L ? L.Copy() : null )
|
||||
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!length(L)) { L = null; } }
|
||||
//ambition start
|
||||
#define LAZYCUT(L, S, E) if((length(L) >= S) && (E == 0 || length(L) >= (E - 1))) { L.Cut(S, E); if(!length(L)) { L = null; } }
|
||||
@@ -19,17 +20,31 @@
|
||||
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
|
||||
#define LAZYOR(L, I) if(!L) { L = list(); } L |= I;
|
||||
#define LAZYFIND(L, V) (L ? L.Find(V) : 0)
|
||||
///returns L[I] if L exists and I is a valid index of L, runtimes if L is not a list
|
||||
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null)
|
||||
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
|
||||
#define LAZYLEN(L) length(L)
|
||||
///This is used to add onto lazy assoc list when the value you're adding is a /list/. This one has extra safety over lazyaddassoc because the value could be null (and thus cant be used to += objects)
|
||||
#define LAZYADDASSOCLIST(L, K, V) if(!L) { L = list(); } L[K] += list(V);
|
||||
//Sets a list to null
|
||||
#define LAZYNULL(L) L = null
|
||||
#define LAZYCLEARLIST(L) if(L) L.Cut()
|
||||
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
|
||||
#define reverseList(L) reverseRange(L.Copy())
|
||||
#define LAZYADDASSOC_TG(L, K, V) if(!L) { L = list(); } L[K] += V;
|
||||
///This is used to add onto lazy assoc list when the value you're adding is a /list/. This one has extra safety over lazyaddassoc because the value could be null (and thus cant be used to += objects)
|
||||
#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += list(V);
|
||||
#define LAZYREMOVEASSOC(L, K, V) if(L) { if(L[K]) { L[K] -= V; if(!length(L[K])) L -= K; } if(!length(L)) L = null; }
|
||||
#define LAZYACCESSASSOC(L, I, K) L ? L[I] ? L[I][K] ? L[I][K] : null : null : null
|
||||
#define QDEL_LAZYLIST(L) for(var/I in L) qdel(I); L = null;
|
||||
//These methods don't null the list
|
||||
#define LAZYCOPY(L) (L ? L.Copy() : list() ) //Use LAZYLISTDUPLICATE instead if you want it to null with no entries
|
||||
#define LAZYCLEARLIST(L) if(L) L.Cut() // Consider LAZYNULL instead
|
||||
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
|
||||
#define reverseList(L) reverseRange(L.Copy())
|
||||
|
||||
/// Performs an insertion on the given lazy list with the given key and value. If the value already exists, a new one will not be made.
|
||||
#define LAZYORASSOCLIST(lazy_list, key, value) \
|
||||
LAZYINITLIST(lazy_list); \
|
||||
LAZYINITLIST(lazy_list[key]); \
|
||||
lazy_list[key] |= value;
|
||||
|
||||
/// Passed into BINARY_INSERT to compare keys
|
||||
#define COMPARE_KEY __BIN_LIST[__BIN_MID]
|
||||
@@ -72,7 +87,7 @@
|
||||
} while(FALSE)
|
||||
|
||||
//Returns a list in plain english as a string
|
||||
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
|
||||
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
|
||||
var/total = length(input)
|
||||
switch(total)
|
||||
if (0)
|
||||
@@ -95,6 +110,7 @@
|
||||
|
||||
/**
|
||||
* English_list but associative supporting. Higher overhead.
|
||||
* @depricated
|
||||
*/
|
||||
/proc/english_list_assoc(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
|
||||
var/total = length(input)
|
||||
@@ -122,6 +138,7 @@
|
||||
return "[output][and_text][input[index]]"
|
||||
|
||||
//Returns list element or null. Should prevent "index out of bounds" error.
|
||||
/// @depricated
|
||||
/proc/listgetindex(list/L, index)
|
||||
if(LAZYLEN(L))
|
||||
if(isnum(index) && ISINTEGER(index))
|
||||
@@ -132,17 +149,19 @@
|
||||
return
|
||||
|
||||
//Return either pick(list) or null if list is not of type /list or is empty
|
||||
/// @depricated
|
||||
/proc/safepick(list/L)
|
||||
if(LAZYLEN(L))
|
||||
return pick(L)
|
||||
|
||||
//Checks if the list is empty
|
||||
/// @depricated
|
||||
/proc/isemptylist(list/L)
|
||||
if(!L.len)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//Checks for specific types in a list
|
||||
//Checks for specific types in a listc
|
||||
/proc/is_type_in_list(atom/A, list/L)
|
||||
if(!LAZYLEN(L) || !A)
|
||||
return FALSE
|
||||
@@ -183,43 +202,45 @@
|
||||
/proc/typecache_filter_list_reverse(list/atoms, list/typecache)
|
||||
RETURN_TYPE(/list)
|
||||
. = list()
|
||||
for(var/atom/A as anything in atoms)
|
||||
if(!typecache[A.type])
|
||||
. += A
|
||||
for(var/atom/atom as anything in atoms)
|
||||
if(!typecache[atom.type])
|
||||
. += atom
|
||||
|
||||
/proc/typecache_filter_multi_list_exclusion(list/atoms, list/typecache_include, list/typecache_exclude)
|
||||
. = list()
|
||||
for(var/atom/A as anything in atoms)
|
||||
if(typecache_include[A.type] && !typecache_exclude[A.type])
|
||||
. += A
|
||||
for(var/atom/atom as anything in atoms)
|
||||
if(typecache_include[atom.type] && !typecache_exclude[atom.type])
|
||||
. += atom
|
||||
|
||||
//Like typesof() or subtypesof(), but returns a typecache instead of a list
|
||||
///Like typesof() or subtypesof(), but returns a typecache instead of a list
|
||||
/proc/typecacheof(path, ignore_root_path, only_root_path = FALSE)
|
||||
if(ispath(path))
|
||||
var/list/types = list()
|
||||
var/list/types
|
||||
var/list/output = list()
|
||||
if(only_root_path)
|
||||
types = list(path)
|
||||
output[path] = TRUE
|
||||
else
|
||||
types = ignore_root_path ? subtypesof(path) : typesof(path)
|
||||
var/list/L = list()
|
||||
for(var/T in types)
|
||||
L[T] = TRUE
|
||||
return L
|
||||
for(var/T in types)
|
||||
output[T] = TRUE
|
||||
return output
|
||||
else if(islist(path))
|
||||
var/list/pathlist = path
|
||||
var/list/L = list()
|
||||
var/list/output = list()
|
||||
if(ignore_root_path)
|
||||
for(var/P in pathlist)
|
||||
for(var/T in subtypesof(P))
|
||||
L[T] = TRUE
|
||||
for(var/current_path in pathlist)
|
||||
for(var/subtype in subtypesof(current_path))
|
||||
output[subtype] = TRUE
|
||||
return output
|
||||
|
||||
if(only_root_path)
|
||||
for(var/current_path in pathlist)
|
||||
output[current_path] = TRUE
|
||||
else
|
||||
for(var/P in pathlist)
|
||||
if(only_root_path)
|
||||
L[P] = TRUE
|
||||
else
|
||||
for(var/T in typesof(P))
|
||||
L[T] = TRUE
|
||||
return L
|
||||
for(var/current_path in pathlist)
|
||||
for(var/subpath in typesof(current_path))
|
||||
output[subpath] = TRUE
|
||||
return output
|
||||
|
||||
/proc/typecacheof_assoc_list(list/pathlist, ignore_root_path = FALSE)
|
||||
. = list()
|
||||
@@ -278,9 +299,10 @@
|
||||
|
||||
//Picks a random element from a list based on a weighting system:
|
||||
//1. Adds up the total of weights for each element
|
||||
//2. Gets the total from 0% to 100% of previous total value.
|
||||
//2. Gets a number between 1 and that total
|
||||
//3. For each element in the list, subtracts its weighting from that number
|
||||
//4. If that makes the number 0 or less, return that element.
|
||||
//Will output null sometimes if you use decimals (e.g. 0.1 instead of 10) as rand() uses integers, not floats
|
||||
/proc/pickweight(list/L, base_weight = 1)
|
||||
var/total = 0
|
||||
var/item
|
||||
@@ -289,12 +311,14 @@
|
||||
L[item] = base_weight
|
||||
total += L[item]
|
||||
|
||||
total = rand() * total
|
||||
total = rand(base_weight, total)
|
||||
for (item in L)
|
||||
total -= L[item]
|
||||
total -=L [item]
|
||||
if (total <= 0)
|
||||
return item
|
||||
|
||||
return null
|
||||
|
||||
/proc/pickweightAllowZero(list/L) //The original pickweight proc will sometimes pick entries with zero weight. I'm not sure if changing the original will break anything, so I left it be.
|
||||
var/total = 0
|
||||
var/item
|
||||
@@ -366,13 +390,13 @@
|
||||
//Results will have a length of quality
|
||||
return results
|
||||
|
||||
//Pick a random element from the list and remove it from the list.
|
||||
/// Pick a random element from the list and remove it from the list.
|
||||
/proc/pick_n_take(list/L)
|
||||
RETURN_TYPE(L[_].type)
|
||||
if(L.len)
|
||||
var/picked = rand(1,L.len)
|
||||
. = L[picked]
|
||||
L.Cut(picked,picked+1) //Cut is far more efficient that Remove()
|
||||
L.Cut(picked,picked+1) //Cut is far more efficient that Remove()
|
||||
|
||||
//Pick a random element from the list by weight and remove it from the list.
|
||||
//Result is returned as a list in the format list(key, value)
|
||||
@@ -468,7 +492,7 @@
|
||||
|
||||
//uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
|
||||
/proc/sortNames(list/L, order=1)
|
||||
return sortTim(L, order >= 0 ? /proc/cmp_name_asc : /proc/cmp_name_dsc)
|
||||
return sortTim(L.Copy(), order >= 0 ? /proc/cmp_name_asc : /proc/cmp_name_dsc)
|
||||
|
||||
|
||||
//Converts a bitfield to a list of numbers (or words if a wordlist is provided)
|
||||
@@ -504,10 +528,12 @@
|
||||
if (L[i] == val)
|
||||
.++
|
||||
|
||||
/// Returns datum/data/record
|
||||
/proc/find_record(field, value, list/L)
|
||||
for(var/datum/data/record/R in L)
|
||||
if(R.fields[field] == value)
|
||||
return R
|
||||
return null
|
||||
|
||||
|
||||
//Move a single element from position fromIndex within a list, to position toIndex
|
||||
@@ -517,10 +543,10 @@
|
||||
//fromIndex and toIndex must be in the range [1,L.len+1]
|
||||
//This will preserve associations ~Carnie
|
||||
/proc/moveElement(list/L, fromIndex, toIndex)
|
||||
if(fromIndex == toIndex || fromIndex+1 == toIndex) //no need to move
|
||||
if(fromIndex == toIndex || fromIndex+1 == toIndex) //no need to move
|
||||
return
|
||||
if(fromIndex > toIndex)
|
||||
++fromIndex //since a null will be inserted before fromIndex, the index needs to be nudged right by one
|
||||
++fromIndex //since a null will be inserted before fromIndex, the index needs to be nudged right by one
|
||||
|
||||
L.Insert(toIndex, null)
|
||||
L.Swap(fromIndex, toIndex)
|
||||
@@ -532,10 +558,10 @@
|
||||
//This will preserve associations ~Carnie
|
||||
/proc/moveRange(list/L, fromIndex, toIndex, len=1)
|
||||
var/distance = abs(toIndex - fromIndex)
|
||||
if(len >= distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going. The result being, our range we are moving is shifted left or right by dist elements
|
||||
if(len >= distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going. The result being, our range we are moving is shifted left or right by dist elements
|
||||
if(fromIndex <= toIndex)
|
||||
return //no need to move
|
||||
fromIndex += len //we want to shift left instead of right
|
||||
return //no need to move
|
||||
fromIndex += len //we want to shift left instead of right
|
||||
|
||||
for(var/i=0, i<distance, ++i)
|
||||
L.Insert(fromIndex, null)
|
||||
@@ -555,7 +581,7 @@
|
||||
//Note: if the two ranges overlap, only the destination order will be preserved fully, since some elements will be within both ranges ~Carnie
|
||||
/proc/swapRange(list/L, fromIndex, toIndex, len=1)
|
||||
var/distance = abs(toIndex - fromIndex)
|
||||
if(len > distance) //there is an overlap, therefore swapping each element will require more swaps than inserting new elements
|
||||
if(len > distance) //there is an overlap, therefore swapping each element will require more swaps than inserting new elements
|
||||
if(fromIndex < toIndex)
|
||||
toIndex += len
|
||||
else
|
||||
@@ -601,6 +627,12 @@
|
||||
if(D.vars[varname] == value)
|
||||
return D
|
||||
|
||||
//remove all nulls from a list
|
||||
/proc/removeNullsFromList(list/L)
|
||||
while(L.Remove(null))
|
||||
continue
|
||||
return L
|
||||
|
||||
//Copies a list, and all lists inside it recusively
|
||||
//Does not copy any other reference type
|
||||
/proc/deepCopyList(list/l)
|
||||
@@ -633,11 +665,6 @@
|
||||
used_key_list[input_key] = 1
|
||||
return input_key
|
||||
|
||||
#if DM_VERSION > 514
|
||||
#error Remie said that lummox was adding a way to get a lists
|
||||
#error contents via list.values, if that is true remove this
|
||||
#error otherwise, update the version and bug lummox
|
||||
#endif
|
||||
//Flattens a keyed list into a list of it's contents
|
||||
/proc/flatten_list(list/key_list)
|
||||
if(!islist(key_list))
|
||||
@@ -714,6 +741,29 @@
|
||||
ret += key
|
||||
return ret
|
||||
|
||||
/proc/compare_list(list/l,list/d)
|
||||
if(!islist(l) || !islist(d))
|
||||
return FALSE
|
||||
|
||||
if(l.len != d.len)
|
||||
return FALSE
|
||||
|
||||
for(var/i in 1 to l.len)
|
||||
if(l[i] != d[i])
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
#define LAZY_LISTS_OR(left_list, right_list)\
|
||||
( length(left_list)\
|
||||
? length(right_list)\
|
||||
? (left_list | right_list)\
|
||||
: left_list.Copy()\
|
||||
: length(right_list)\
|
||||
? right_list.Copy()\
|
||||
: null\
|
||||
)
|
||||
|
||||
/proc/is_type_in_ref_list(path, list/L)
|
||||
if(!ispath(path))//not a path
|
||||
return
|
||||
|
||||
@@ -88,6 +88,19 @@
|
||||
if (CONFIG_GET(flag/log_access))
|
||||
WRITE_LOG(GLOB.world_game_log, "ACCESS: [text]")
|
||||
|
||||
/**
|
||||
* Writes to a special log file if the log_suspicious_login config flag is set,
|
||||
* which is intended to contain all logins that failed under suspicious circumstances.
|
||||
*
|
||||
* Mirrors this log entry to log_access when access_log_mirror is TRUE, so this proc
|
||||
* doesn't need to be used alongside log_access and can replace it where appropriate.
|
||||
*/
|
||||
/proc/log_suspicious_login(text, access_log_mirror = TRUE)
|
||||
if (CONFIG_GET(flag/log_suspicious_login))
|
||||
WRITE_LOG(GLOB.world_suspicious_login_log, "SUSPICIOUS_ACCESS: [text]")
|
||||
if(access_log_mirror)
|
||||
log_access(text)
|
||||
|
||||
/proc/log_law(text)
|
||||
if (CONFIG_GET(flag/log_law))
|
||||
WRITE_LOG(GLOB.world_game_log, "LAW: [text]")
|
||||
|
||||
@@ -396,12 +396,16 @@
|
||||
/proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480)
|
||||
if(!isobj(O))
|
||||
O = new /atom/movable/screen/text()
|
||||
O.maptext = maptext
|
||||
O.maptext = MAPTEXT(maptext)
|
||||
O.maptext_height = maptext_height
|
||||
O.maptext_width = maptext_width
|
||||
O.screen_loc = screen_loc
|
||||
return O
|
||||
|
||||
/// Removes an image from a client's `.images`. Useful as a callback.
|
||||
/proc/remove_image_from_client(image/image, client/remove_from)
|
||||
remove_from?.images -= image
|
||||
|
||||
/proc/remove_images_from_clients(image/I, list/show_to)
|
||||
for(var/client/C in show_to)
|
||||
C.images -= I
|
||||
|
||||
@@ -86,16 +86,6 @@
|
||||
// Keybindings
|
||||
init_keybindings()
|
||||
|
||||
//Uplink Items
|
||||
for(var/path in subtypesof(/datum/uplink_item))
|
||||
var/datum/uplink_item/I = path
|
||||
if(!initial(I.item)) //We add categories to a separate list.
|
||||
GLOB.uplink_categories |= initial(I.category)
|
||||
continue
|
||||
GLOB.uplink_items += path
|
||||
//(sub)typesof entries are listed by the order they are loaded in the code, so we'll have to rearrange them here.
|
||||
GLOB.uplink_items = sortList(GLOB.uplink_items, /proc/cmp_uplink_items_dsc)
|
||||
|
||||
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
|
||||
|
||||
INVOKE_ASYNC(GLOBAL_PROC, /proc/init_ref_coin_values) //so the current procedure doesn't sleep because of UNTIL()
|
||||
|
||||
@@ -992,7 +992,7 @@ world
|
||||
letter = lowertext(letter)
|
||||
|
||||
var/image/text_image = new(loc = A)
|
||||
text_image.maptext = "<font size = 4>[letter]</font>"
|
||||
text_image.maptext = MAPTEXT("<font size = 4>[letter]</font>")
|
||||
text_image.pixel_x = 7
|
||||
text_image.pixel_y = 5
|
||||
qdel(atom_icon)
|
||||
|
||||
@@ -1,85 +1,3 @@
|
||||
/matrix/proc/TurnTo(old_angle, new_angle)
|
||||
. = new_angle - old_angle
|
||||
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
|
||||
|
||||
/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3, parallel = TRUE)
|
||||
if(!segments)
|
||||
return
|
||||
var/segment = 360/segments
|
||||
if(!clockwise)
|
||||
segment = -segment
|
||||
var/list/matrices = list()
|
||||
for(var/i in 1 to segments-1)
|
||||
var/matrix/M = matrix(transform)
|
||||
M.Turn(segment*i)
|
||||
matrices += M
|
||||
var/matrix/last = matrix(transform)
|
||||
matrices += last
|
||||
|
||||
speed /= segments
|
||||
|
||||
if(parallel)
|
||||
animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
|
||||
else
|
||||
animate(src, transform = matrices[1], time = speed, loops)
|
||||
|
||||
for(var/i in 2 to segments) //2 because 1 is covered above
|
||||
animate(transform = matrices[i], time = speed)
|
||||
//doesn't have an object argument because this is "Stacking" with the animate call above
|
||||
//3 billion% intentional
|
||||
|
||||
//Dumps the matrix data in format a-f
|
||||
/matrix/proc/tolist()
|
||||
. = list()
|
||||
. += a
|
||||
. += b
|
||||
. += c
|
||||
. += d
|
||||
. += e
|
||||
. += f
|
||||
|
||||
//Dumps the matrix data in a matrix-grid format
|
||||
/*
|
||||
a d 0
|
||||
b e 0
|
||||
c f 1
|
||||
*/
|
||||
/matrix/proc/togrid()
|
||||
. = list()
|
||||
. += a
|
||||
. += d
|
||||
. += 0
|
||||
. += b
|
||||
. += e
|
||||
. += 0
|
||||
. += c
|
||||
. += f
|
||||
. += 1
|
||||
|
||||
//The X pixel offset of this matrix
|
||||
/matrix/proc/get_x_shift()
|
||||
. = c
|
||||
|
||||
//The Y pixel offset of this matrix
|
||||
/matrix/proc/get_y_shift()
|
||||
. = f
|
||||
|
||||
/matrix/proc/get_x_skew()
|
||||
. = b
|
||||
|
||||
/matrix/proc/get_y_skew()
|
||||
. = d
|
||||
|
||||
//Skews a matrix in a particular direction
|
||||
//Missing arguments are treated as no skew in that direction
|
||||
|
||||
//As Rotation is defined as a scale+skew, these procs will break any existing rotation
|
||||
//Unless the result is multiplied against the current matrix
|
||||
/matrix/proc/set_skew(x = 0, y = 0)
|
||||
b = x
|
||||
d = y
|
||||
|
||||
|
||||
/////////////////////
|
||||
// COLOUR MATRICES //
|
||||
/////////////////////
|
||||
@@ -114,12 +32,64 @@ list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0
|
||||
|
||||
return list(R + value,R,R,0, G,G + value,G,0, B,B,B + value,0, 0,0,0,1, 0,0,0,0)
|
||||
|
||||
/**
|
||||
* Exxagerates or removes colors
|
||||
*/
|
||||
/proc/color_matrix_saturation_percent(percent)
|
||||
if(percent == 0)
|
||||
return color_matrix_identity()
|
||||
percent = clamp(percent, -100, 100)
|
||||
if(percent > 0)
|
||||
percent *= 3
|
||||
var/x = 1 + percent / 100
|
||||
var/inv = 1 - x
|
||||
var/R = LUMA_R * inv
|
||||
var/G = LUMA_G * inv
|
||||
var/B = LUMA_B * inv
|
||||
|
||||
return list(R + x,R,R, G,G + x,G, B,B,B + x)
|
||||
|
||||
//Changes distance colors have from rgb(127,127,127) grey
|
||||
//1 is identity. 0 makes everything grey >1 blows out colors and greys
|
||||
/proc/color_matrix_contrast(value)
|
||||
var/add = (1 - value) / 2
|
||||
return list(value,0,0,0, 0,value,0,0, 0,0,value,0, 0,0,0,1, add,add,add,0)
|
||||
|
||||
/**
|
||||
* Exxagerates or removes brightness
|
||||
*/
|
||||
/proc/color_matrix_contrast_percent(percent)
|
||||
var/static/list/delta_index = list(
|
||||
0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11,
|
||||
0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24,
|
||||
0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42,
|
||||
0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68,
|
||||
0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98,
|
||||
1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54,
|
||||
1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25,
|
||||
2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8,
|
||||
4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0,
|
||||
7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8,
|
||||
10.0)
|
||||
percent = clamp(percent, -100, 100)
|
||||
if(percent == 0)
|
||||
return color_matrix_identity()
|
||||
|
||||
var/x = 0
|
||||
if (percent < 0)
|
||||
x = 127 + percent / 100 * 127;
|
||||
else
|
||||
x = percent % 1
|
||||
if(x == 0)
|
||||
x = delta_index[percent]
|
||||
else
|
||||
x = delta_index[percent] * (1-x) + delta_index[percent+1] * x//use linear interpolation for more granularity.
|
||||
x = x * 127 + 127
|
||||
|
||||
var/mult = x / 127
|
||||
var/add = 0.5 * (127-x) / 255
|
||||
return list(mult,0,0, 0,mult,0, 0,0,mult, add,add,add)
|
||||
|
||||
//Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting greys
|
||||
//0 is identity, 120 moves reds to greens, 240 moves reds to blues
|
||||
/proc/color_matrix_rotate_hue(angle)
|
||||
@@ -134,6 +104,26 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro
|
||||
0,0,0,1,
|
||||
0,0,0,0)
|
||||
|
||||
/**
|
||||
* Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting whites
|
||||
* TODO: Need a version that only affects one color (ie shift red to blue but leave greens and blues alone)
|
||||
*/
|
||||
/proc/color_matrix_rotation(angle)
|
||||
if(angle == 0)
|
||||
return color_matrix_identity()
|
||||
angle = clamp(angle, -180, 180)
|
||||
var/cos = cos(angle)
|
||||
var/sin = sin(angle)
|
||||
|
||||
var/constA = 0.143
|
||||
var/constB = 0.140
|
||||
var/constC = -0.283
|
||||
return list(
|
||||
LUMA_R + cos * (1-LUMA_R) + sin * -LUMA_R, LUMA_R + cos * -LUMA_R + sin * constA, LUMA_R + cos * -LUMA_R + sin * -(1-LUMA_R),
|
||||
LUMA_G + cos * -LUMA_G + sin * -LUMA_G, LUMA_G + cos * (1-LUMA_G) + sin * constB, LUMA_G + cos * -LUMA_G + sin * LUMA_G,
|
||||
LUMA_B + cos * -LUMA_B + sin * (1-LUMA_B), LUMA_B + cos * -LUMA_B + sin * constC, LUMA_B + cos * (1-LUMA_B) + sin * LUMA_B
|
||||
)
|
||||
|
||||
//These next three rotate values about one axis only
|
||||
//x is the red axis, y is the green axis, z is the blue axis.
|
||||
/proc/color_matrix_rotate_x(angle)
|
||||
@@ -183,3 +173,9 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro
|
||||
*/
|
||||
/proc/rgb_construct_color_matrix(rr = 1, rg, rb, gr, gg = 1, gb, br, bg, bb = 1, cr, cg, cb)
|
||||
return list(rr, rg, rb, gr, gg, gb, br, bg, bb, cr, cg, cb)
|
||||
|
||||
/**
|
||||
* Assembles a color matrix, defaulting to identity
|
||||
*/
|
||||
/proc/rgba_construct_color_matrix(rr = 1, rg, rb, ra, gr, gg = 1, gb, ga, br, bg, bb = 1, ba, ar, ag, ab, aa = 1, cr, cg, cb, ca)
|
||||
return list(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, cr, cg, cb, ca)
|
||||
@@ -0,0 +1,86 @@
|
||||
/matrix/proc/TurnTo(old_angle, new_angle)
|
||||
. = new_angle - old_angle
|
||||
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
|
||||
|
||||
/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3, parallel = TRUE)
|
||||
if(!segments)
|
||||
return
|
||||
var/segment = 360/segments
|
||||
if(!clockwise)
|
||||
segment = -segment
|
||||
var/list/matrices = list()
|
||||
for(var/i in 1 to segments-1)
|
||||
var/matrix/M = matrix(transform)
|
||||
M.Turn(segment*i)
|
||||
matrices += M
|
||||
var/matrix/last = matrix(transform)
|
||||
matrices += last
|
||||
|
||||
speed /= segments
|
||||
|
||||
if(parallel)
|
||||
animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
|
||||
else
|
||||
animate(src, transform = matrices[1], time = speed, loops)
|
||||
|
||||
for(var/i in 2 to segments) //2 because 1 is covered above
|
||||
animate(transform = matrices[i], time = speed)
|
||||
//doesn't have an object argument because this is "Stacking" with the animate call above
|
||||
//3 billion% intentional
|
||||
|
||||
//Dumps the matrix data in format a-f
|
||||
/matrix/proc/tolist()
|
||||
. = list()
|
||||
. += a
|
||||
. += b
|
||||
. += c
|
||||
. += d
|
||||
. += e
|
||||
. += f
|
||||
|
||||
//Dumps the matrix data in a matrix-grid format
|
||||
/*
|
||||
a d 0
|
||||
b e 0
|
||||
c f 1
|
||||
*/
|
||||
/matrix/proc/togrid()
|
||||
. = list()
|
||||
. += a
|
||||
. += d
|
||||
. += 0
|
||||
. += b
|
||||
. += e
|
||||
. += 0
|
||||
. += c
|
||||
. += f
|
||||
. += 1
|
||||
|
||||
//The X pixel offset of this matrix
|
||||
/matrix/proc/get_x_shift()
|
||||
. = c
|
||||
|
||||
//The Y pixel offset of this matrix
|
||||
/matrix/proc/get_y_shift()
|
||||
. = f
|
||||
|
||||
/matrix/proc/get_x_skew()
|
||||
. = b
|
||||
|
||||
/matrix/proc/get_y_skew()
|
||||
. = d
|
||||
|
||||
//Skews a matrix in a particular direction
|
||||
//Missing arguments are treated as no skew in that direction
|
||||
|
||||
//As Rotation is defined as a scale+skew, these procs will break any existing rotation
|
||||
//Unless the result is multiplied against the current matrix
|
||||
/matrix/proc/set_skew(x = 0, y = 0)
|
||||
b = x
|
||||
d = y
|
||||
|
||||
/**
|
||||
* constructs a transform matrix, defaulting to identity
|
||||
*/
|
||||
/proc/transform_matrix_construct(a = 1, b, c, d = 1, e, f)
|
||||
return matrix(a, b, c, d, e, f)
|
||||
@@ -458,6 +458,21 @@ GLOBAL_LIST_EMPTY(species_datums)
|
||||
if(!HAS_TRAIT(L, TRAIT_PASSTABLE))
|
||||
L.pass_flags &= ~PASSTABLE
|
||||
|
||||
/proc/dance_rotate(atom/movable/AM, datum/callback/callperrotate, set_original_dir=FALSE)
|
||||
set waitfor = FALSE
|
||||
var/originaldir = AM.dir
|
||||
for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH))
|
||||
if(!AM)
|
||||
return
|
||||
AM.setDir(i)
|
||||
callperrotate?.Invoke()
|
||||
sleep(1)
|
||||
if(set_original_dir)
|
||||
AM.setDir(originaldir)
|
||||
|
||||
/// Gets the client of the mob, allowing for mocking of the client.
|
||||
/// You only need to use this if you know you're going to be mocking clients somewhere else.
|
||||
#define GET_CLIENT(mob) (##mob.client || ##mob.mock_client)
|
||||
|
||||
//check if the person is dead, not sure where to put this
|
||||
#define IS_DEAD_OR_INCAP(source) (source.incapacitated() || source.stat)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/proc/priority_announce(text, title = "", sound = "attention", type , sender_override)
|
||||
/proc/priority_announce(text, title = "", sound, type , sender_override, has_important_message)
|
||||
if(!text)
|
||||
return
|
||||
|
||||
var/announcement
|
||||
if(!sound)
|
||||
sound = "attention"
|
||||
|
||||
if(type == "Priority")
|
||||
announcement += "<h1 class='alert'>Priority Announcement</h1>"
|
||||
@@ -26,7 +28,11 @@
|
||||
else
|
||||
GLOB.news_network.SubmitArticle(title + "<br><br>" + text, "Central Command", "Station Announcements", null)
|
||||
|
||||
announcement += "<br><span class='alert'>[html_encode(text)]</span><br>"
|
||||
///If the announcer overrides alert messages, use that message.
|
||||
// if(SSstation.announcer.custom_alert_message && !has_important_message)
|
||||
// announcement += SSstation.announcer.custom_alert_message
|
||||
// else
|
||||
announcement += "<br>[span_alert("[html_encode(text)]")]<br>"
|
||||
announcement += "<br>"
|
||||
|
||||
var/s = sound(get_announcer_sound(sound))
|
||||
@@ -127,12 +133,44 @@
|
||||
if("welcome")
|
||||
. = 'sound/announcer/medibot/welcome.ogg'
|
||||
|
||||
/**
|
||||
* Summon the crew for an emergency meeting
|
||||
*
|
||||
* Teleports the crew to a specified area, and tells everyone (via an announcement) who called the meeting. Should only be used during april fools!
|
||||
* Arguments:
|
||||
* * user - Mob who called the meeting
|
||||
* * button_zone - Area where the meeting was called and where everyone will get teleported to
|
||||
*/
|
||||
/proc/call_emergency_meeting(mob/living/user, area/button_zone)
|
||||
var/meeting_sound = sound('sound/misc/emergency_meeting.ogg')
|
||||
var/announcement
|
||||
announcement += "<h1 class='alert'>Captain Alert</h1>"
|
||||
announcement += "<br>[span_alert("[user] has called an Emergency Meeting!")]<br><br>"
|
||||
|
||||
for(var/mob/mob_to_teleport in GLOB.player_list) //gotta make sure the whole crew's here!
|
||||
if(isnewplayer(mob_to_teleport) || iscameramob(mob_to_teleport))
|
||||
continue
|
||||
to_chat(mob_to_teleport, announcement)
|
||||
SEND_SOUND(mob_to_teleport, meeting_sound) //no preferences here, you must hear the funny sound
|
||||
mob_to_teleport.overlay_fullscreen("emergency_meeting", /atom/movable/screen/fullscreen/scaled/emergency_meeting, 1)
|
||||
addtimer(CALLBACK(mob_to_teleport, /mob/.proc/clear_fullscreen, "emergency_meeting"), 3 SECONDS)
|
||||
|
||||
if (is_station_level(mob_to_teleport.z)) //teleport the mob to the crew meeting
|
||||
var/turf/target
|
||||
var/list/turf_list = get_area_turfs(button_zone)
|
||||
while (!target && turf_list.len)
|
||||
target = pick_n_take(turf_list)
|
||||
if (isclosedturf(target))
|
||||
target = null
|
||||
continue
|
||||
mob_to_teleport.forceMove(target)
|
||||
|
||||
/proc/print_command_report(text = "", title = null, announce=TRUE)
|
||||
if(!title)
|
||||
title = "Classified [command_name()] Update"
|
||||
|
||||
if(announce)
|
||||
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport")
|
||||
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport", has_important_message = TRUE)
|
||||
|
||||
var/datum/comm_message/M = new
|
||||
M.title = title
|
||||
@@ -140,13 +178,17 @@
|
||||
|
||||
SScommunications.send_message(M)
|
||||
|
||||
/proc/minor_announce(message, title = "Attention:", alert)
|
||||
/proc/minor_announce(message, title = "Attention:", alert, html_encode = TRUE)
|
||||
if(!message)
|
||||
return
|
||||
|
||||
if (html_encode)
|
||||
title = html_encode(title)
|
||||
message = html_encode(message)
|
||||
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(!isnewplayer(M) && M.can_hear())
|
||||
to_chat(M, "<span class='big bold'><font color = red>[html_encode(title)]</font color><BR>[html_encode(message)]</span><BR>")
|
||||
to_chat(M, "[span_minorannounce("<font color = red>[title]</font color><BR>[message]")]<BR>")
|
||||
if(M.client.prefs.toggles & SOUND_ANNOUNCEMENTS)
|
||||
if(alert)
|
||||
SEND_SOUND(M, sound('sound/misc/notice1.ogg'))
|
||||
|
||||
+17
-3
@@ -1,4 +1,4 @@
|
||||
// Ensure the frequency is within bounds of what it should be sending/receiving at
|
||||
/// Ensure the frequency is within bounds of what it should be sending/receiving at
|
||||
/proc/sanitize_frequency(frequency, free = FALSE)
|
||||
frequency = round(frequency)
|
||||
if(free)
|
||||
@@ -8,12 +8,26 @@
|
||||
if(!(. % 2)) // Ensure the last digit is an odd number
|
||||
. += 1
|
||||
|
||||
// Format frequency by moving the decimal.
|
||||
/// Format frequency by moving the decimal.
|
||||
/proc/format_frequency(frequency)
|
||||
frequency = text2num(frequency)
|
||||
return "[round(frequency / 10)].[frequency % 10]"
|
||||
|
||||
//Opposite of format, returns as a number
|
||||
///Opposite of format, returns as a number
|
||||
/proc/unformat_frequency(frequency)
|
||||
frequency = text2num(frequency)
|
||||
return frequency * 10
|
||||
|
||||
///returns a random unused frequency between MIN_FREE_FREQ & MAX_FREE_FREQ if free = TRUE, and MIN_FREQ & MAX_FREQ if FALSE
|
||||
/proc/return_unused_frequency(free = FALSE)
|
||||
var/start = free ? MIN_FREE_FREQ : MIN_FREQ
|
||||
var/end = free ? MAX_FREE_FREQ : MAX_FREQ
|
||||
|
||||
var/freq_to_check = 0
|
||||
do
|
||||
freq_to_check = rand(start, end)
|
||||
if(!(freq_to_check % 2)) // Ensure the last digit is an odd number
|
||||
freq_to_check++
|
||||
while((freq_to_check == 0) || ("[freq_to_check]" in GLOB.reverseradiochannels))
|
||||
|
||||
return freq_to_check
|
||||
|
||||
@@ -590,8 +590,8 @@
|
||||
var/list/all_teams = list()
|
||||
var/list/all_antagonists = list()
|
||||
|
||||
// for(var/datum/team/A in GLOB.antagonist_teams)
|
||||
// all_teams |= A
|
||||
for(var/datum/team/A in GLOB.antagonist_teams)
|
||||
all_teams |= A
|
||||
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
if(!A.owner)
|
||||
|
||||
@@ -591,9 +591,9 @@
|
||||
switch(child)
|
||||
if(/datum)
|
||||
return null
|
||||
if(/obj || /mob)
|
||||
if(/obj, /mob)
|
||||
return /atom/movable
|
||||
if(/area || /turf)
|
||||
if(/area, /turf)
|
||||
return /atom
|
||||
else
|
||||
return /datum
|
||||
|
||||
@@ -663,10 +663,10 @@ Turf and target are separate in case you want to teleport some distance from a t
|
||||
return locate(final_x, final_y, T.z)
|
||||
|
||||
//Finds the distance between two atoms, in pixels
|
||||
//centered = 0 counts from turf edge to edge
|
||||
//centered = 1 counts from turf center to turf center
|
||||
//centered = FALSE counts from turf edge to edge
|
||||
//centered = TRUE counts from turf center to turf center
|
||||
//of course mathematically this is just adding world.icon_size on again
|
||||
/proc/getPixelDistance(atom/A, atom/B, centered = 1)
|
||||
/proc/getPixelDistance(atom/A, atom/B, centered = TRUE)
|
||||
if(!istype(A)||!istype(B))
|
||||
return 0
|
||||
. = bounds_dist(A, B) + sqrt((((A.pixel_x+B.pixel_x)**2) + ((A.pixel_y+B.pixel_y)**2)))
|
||||
|
||||
@@ -216,7 +216,13 @@ GLOBAL_LIST_INIT(jumpsuitlist, list(PREF_SUIT, PREF_SKIRT))
|
||||
#define UPLINK_PDA "PDA"
|
||||
#define UPLINK_RADIO "Radio"
|
||||
#define UPLINK_PEN "Pen" //like a real spy!
|
||||
GLOBAL_LIST_INIT(uplink_spawn_loc_list, list(UPLINK_PDA, UPLINK_RADIO, UPLINK_PEN))
|
||||
#define UPLINK_IMPLANT "Implant"
|
||||
#define UPLINK_IMPLANT_WITH_PRICE "[UPLINK_IMPLANT] (-[UPLINK_IMPLANT_TELECRYSTAL_COST] TC)"
|
||||
// What we show to the user
|
||||
GLOBAL_LIST_INIT(uplink_spawn_loc_list, list(UPLINK_PDA, UPLINK_RADIO, UPLINK_PEN, UPLINK_IMPLANT_WITH_PRICE))
|
||||
// What is actually saved; if the uplink implant price changes, it won't affect save files then
|
||||
GLOBAL_LIST_INIT(uplink_spawn_loc_list_save, list(UPLINK_PDA, UPLINK_RADIO, UPLINK_PEN, UPLINK_IMPLANT))
|
||||
|
||||
|
||||
//List of cached alpha masked icons.
|
||||
GLOBAL_LIST_EMPTY(alpha_masked_worn_icons)
|
||||
|
||||
@@ -52,6 +52,8 @@ GLOBAL_LIST_EMPTY(current_observers_list)
|
||||
|
||||
//Dynamic Port
|
||||
GLOBAL_LIST_EMPTY(new_player_list) //all /mob/dead/new_player, in theory all should have clients and those that don't are in the process of spawning and get deleted when done.
|
||||
//Family Port
|
||||
GLOBAL_LIST_EMPTY(pre_setup_antags) //minds that have been picked as antag by the gamemode. removed as antag datums are set.
|
||||
|
||||
/proc/update_config_movespeed_type_lookup(update_mobs = TRUE)
|
||||
// NOTE: This is entirely based on the fact that byond typesof/subtypesof gets longer/deeper paths before shallower ones.
|
||||
|
||||
@@ -19,7 +19,6 @@ GLOBAL_LIST(chemical_reactions_list) //list of all /datum/chemical_reaction d
|
||||
GLOBAL_LIST(chemical_reagents_list) //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
|
||||
GLOBAL_LIST_EMPTY(tech_list) //list of all /datum/tech datums indexed by id.
|
||||
GLOBAL_LIST_EMPTY(surgeries_list) //list of all surgeries by name, associated with their path.
|
||||
GLOBAL_LIST_EMPTY(uplink_items) //list of all uplink item typepaths, ascendingly sorted by their initial name.
|
||||
GLOBAL_LIST_EMPTY(uplink_categories) //list of all uplink categories, listed by the order they are loaded in code. Be careful.
|
||||
GLOBAL_LIST_EMPTY(crafting_recipes) //list of all table craft recipes
|
||||
GLOBAL_LIST_EMPTY(rcd_list) //list of Rapid Construction Devices.
|
||||
|
||||
@@ -2,6 +2,9 @@ GLOBAL_VAR(log_directory)
|
||||
GLOBAL_PROTECT(log_directory)
|
||||
GLOBAL_VAR(world_game_log)
|
||||
GLOBAL_PROTECT(world_game_log)
|
||||
/// Log associated with [/proc/log_suspicious_login()] - Intended to hold all logins that failed due to suspicious circumstances such as ban detection, CID randomisation etc.
|
||||
GLOBAL_VAR(world_suspicious_login_log)
|
||||
GLOBAL_PROTECT(world_suspicious_login_log)
|
||||
GLOBAL_VAR(world_runtime_log)
|
||||
GLOBAL_PROTECT(world_runtime_log)
|
||||
GLOBAL_VAR(world_qdel_log)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
GLOBAL_DATUM(changelog_tgui, /datum/changelog)
|
||||
@@ -38,6 +38,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_RESISTCOLD" = TRAIT_RESISTCOLD,
|
||||
"TRAIT_RESISTHIGHPRESSURE" = TRAIT_RESISTHIGHPRESSURE,
|
||||
"TRAIT_RESISTLOWPRESSURE" = TRAIT_RESISTLOWPRESSURE,
|
||||
"TRAIT_LOWPRESSURECOOLING" = TRAIT_LOWPRESSURECOOLING,
|
||||
"TRAIT_BOMBIMMUNE" = TRAIT_BOMBIMMUNE,
|
||||
"TRAIT_RADIMMUNE" = TRAIT_RADIMMUNE,
|
||||
"TRAIT_GENELESS" = TRAIT_GENELESS,
|
||||
@@ -55,6 +56,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_ROBOTIC_ORGANISM" = TRAIT_ROBOTIC_ORGANISM,
|
||||
"TRAIT_ROBOT_RADSHIELDING" = TRAIT_ROBOT_RADSHIELDING,
|
||||
"TRAIT_NOBREATH" = TRAIT_NOBREATH,
|
||||
"TRAIT_AUXILIARY_LUNGS" = TRAIT_AUXILIARY_LUNGS,
|
||||
"TRAIT_ANTIMAGIC" = TRAIT_ANTIMAGIC,
|
||||
"TRAIT_HOLY" = TRAIT_HOLY,
|
||||
"TRAIT_DEPRESSION" = TRAIT_DEPRESSION,
|
||||
|
||||
@@ -470,51 +470,6 @@
|
||||
else
|
||||
setDir(WEST, ismousemovement)
|
||||
|
||||
//debug
|
||||
/atom/movable/screen/proc/scale_to(x1,y1)
|
||||
if(!y1)
|
||||
y1 = x1
|
||||
var/matrix/M = new
|
||||
M.Scale(x1,y1)
|
||||
transform = M
|
||||
|
||||
/atom/movable/screen/click_catcher
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "catcher"
|
||||
plane = CLICKCATCHER_PLANE
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
screen_loc = "CENTER"
|
||||
|
||||
#define MAX_SAFE_BYOND_ICON_SCALE_TILES (MAX_SAFE_BYOND_ICON_SCALE_PX / world.icon_size)
|
||||
#define MAX_SAFE_BYOND_ICON_SCALE_PX (33 * 32) //Not using world.icon_size on purpose.
|
||||
|
||||
/atom/movable/screen/click_catcher/proc/UpdateGreed(view_size_x = 15, view_size_y = 15)
|
||||
var/icon/newicon = icon('icons/mob/screen_gen.dmi', "catcher")
|
||||
var/ox = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_x)
|
||||
var/oy = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_y)
|
||||
var/px = view_size_x * world.icon_size
|
||||
var/py = view_size_y * world.icon_size
|
||||
var/sx = min(MAX_SAFE_BYOND_ICON_SCALE_PX, px)
|
||||
var/sy = min(MAX_SAFE_BYOND_ICON_SCALE_PX, py)
|
||||
newicon.Scale(sx, sy)
|
||||
icon = newicon
|
||||
screen_loc = "CENTER-[(ox-1)*0.5],CENTER-[(oy-1)*0.5]"
|
||||
var/matrix/M = new
|
||||
M.Scale(px/sx, py/sy)
|
||||
transform = M
|
||||
|
||||
/atom/movable/screen/click_catcher/Click(location, control, params)
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["middle"] && iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
C.swap_hand()
|
||||
else
|
||||
var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr.client ? usr.client.eye : usr), usr.client)
|
||||
params += "&catcher=1"
|
||||
if(T)
|
||||
T.Click(location, control, params)
|
||||
. = 1
|
||||
|
||||
/* MouseWheelOn */
|
||||
|
||||
/mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params)
|
||||
|
||||
@@ -176,9 +176,6 @@
|
||||
#define ui_ghost_mafia "SOUTH: 6, CENTER+2:24"
|
||||
#define ui_ghost_spawners "SOUTH: 6, CENTER+1:24" // LEGACY. SAME LOC AS PAI
|
||||
|
||||
// #define ui_wanted_lvl "NORTH,11"
|
||||
|
||||
|
||||
//UI position overrides for 1:1 screen layout. (default is 7:5)
|
||||
#define ui_stamina "EAST-1:28,CENTER:17" // replacing internals button
|
||||
#define ui_overridden_resist "EAST-3:24,SOUTH+1:7"
|
||||
@@ -190,3 +187,5 @@
|
||||
#define ui_boxarea "EAST-4:6,SOUTH+1:6"
|
||||
#define ui_boxlang "EAST-5:22,SOUTH+1:6"
|
||||
#define ui_boxvore "EAST-5:22,SOUTH+1:6"
|
||||
|
||||
#define ui_wanted_lvl "NORTH,11"
|
||||
|
||||
+130
-45
@@ -2,9 +2,6 @@
|
||||
|
||||
//PUBLIC - call these wherever you want
|
||||
|
||||
|
||||
/mob/proc/throw_alert(category, type, severity, obj/new_master, override = FALSE)
|
||||
|
||||
/* Proc to create or update an alert. Returns the alert if the alert is new or updated, 0 if it was thrown already
|
||||
category is a text string. Each mob may only have one alert per category; the previous one will be replaced
|
||||
path is a type path of the actual alert type to throw
|
||||
@@ -14,6 +11,7 @@
|
||||
Clicks are forwarded to master
|
||||
Override makes it so the alert is not replaced until cleared by a clear_alert with clear_override, and it's used for hallucinations.
|
||||
*/
|
||||
/mob/proc/throw_alert(category, type, severity, obj/new_master, override = FALSE)
|
||||
|
||||
if(!category || QDELETED(src))
|
||||
return
|
||||
@@ -42,7 +40,7 @@
|
||||
thealert.override_alerts = override
|
||||
if(override)
|
||||
thealert.timeout = null
|
||||
thealert.mob_viewer = src
|
||||
thealert.owner = src
|
||||
|
||||
if(new_master)
|
||||
var/old_layer = new_master.layer
|
||||
@@ -97,8 +95,10 @@
|
||||
var/severity = 0
|
||||
var/alerttooltipstyle = ""
|
||||
var/override_alerts = FALSE //If it is overriding other alerts of the same type
|
||||
var/mob/mob_viewer //the mob viewing this alert
|
||||
var/mob/owner //Alert owner
|
||||
|
||||
/// Boolean. If TRUE, the Click() proc will attempt to Click() on the master first if there is a master.
|
||||
var/click_master = TRUE
|
||||
|
||||
/atom/movable/screen/alert/MouseEntered(location,control,params)
|
||||
if(!QDELETED(src))
|
||||
@@ -251,6 +251,8 @@ or something covering your eyes."
|
||||
|
||||
/atom/movable/screen/alert/mind_control/Click()
|
||||
var/mob/living/L = usr
|
||||
if(L != owner)
|
||||
return
|
||||
to_chat(L, "<span class='mind_control'>[command]</span>")
|
||||
|
||||
/atom/movable/screen/alert/hypnosis
|
||||
@@ -271,7 +273,7 @@ If you're feeling frisky, examine yourself and click the underlined item to pull
|
||||
icon_state = "embeddedobject"
|
||||
|
||||
/atom/movable/screen/alert/embeddedobject/Click()
|
||||
if(isliving(usr))
|
||||
if(isliving(usr) && usr == owner)
|
||||
var/mob/living/carbon/M = usr
|
||||
return M.help_shake_act(M)
|
||||
|
||||
@@ -300,7 +302,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
|
||||
/atom/movable/screen/alert/fire/Click()
|
||||
var/mob/living/L = usr
|
||||
if(!istype(L) || !L.can_resist())
|
||||
if(!istype(L) || !L.can_resist() || L != owner)
|
||||
return
|
||||
L.MarkResistTime()
|
||||
if(CHECK_MOBILITY(L, MOBILITY_MOVE))
|
||||
@@ -308,37 +310,110 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
|
||||
/atom/movable/screen/alert/give // information set when the give alert is made
|
||||
icon_state = "default"
|
||||
var/mob/living/carbon/giver
|
||||
var/mob/living/carbon/offerer
|
||||
var/obj/item/receiving
|
||||
|
||||
/**
|
||||
* Handles assigning most of the variables for the alert that pops up when an item is offered
|
||||
*
|
||||
* Handles setting the name, description and icon of the alert and tracking the person giving
|
||||
* and the item being offered, also registers a signal that removes the alert from anyone who moves away from the giver
|
||||
* Arguments:
|
||||
* * taker - The person receiving the alert
|
||||
* * giver - The person giving the alert and item
|
||||
* * receiving - The item being given by the giver
|
||||
*/
|
||||
/atom/movable/screen/alert/give/proc/setup(mob/living/carbon/taker, mob/living/carbon/giver, obj/item/receiving)
|
||||
name = "[giver] is offering [receiving]"
|
||||
desc = "[giver] is offering [receiving]. Click this alert to take it."
|
||||
* Handles assigning most of the variables for the alert that pops up when an item is offered
|
||||
*
|
||||
* Handles setting the name, description and icon of the alert and tracking the person giving
|
||||
* and the item being offered, also registers a signal that removes the alert from anyone who moves away from the offerer
|
||||
* Arguments:
|
||||
* * taker - The person receiving the alert
|
||||
* * offerer - The person giving the alert and item
|
||||
* * receiving - The item being given by the offerer
|
||||
*/
|
||||
/atom/movable/screen/alert/give/proc/setup(mob/living/carbon/taker, mob/living/carbon/offerer, obj/item/receiving)
|
||||
name = "[offerer] is offering [receiving]"
|
||||
desc = "[offerer] is offering [receiving]. Click this alert to take it."
|
||||
icon_state = "template"
|
||||
cut_overlays()
|
||||
add_overlay(receiving)
|
||||
src.receiving = receiving
|
||||
src.giver = giver
|
||||
RegisterSignal(taker, COMSIG_MOVABLE_MOVED, .proc/removeAlert)
|
||||
|
||||
/atom/movable/screen/alert/give/proc/removeAlert()
|
||||
to_chat(usr, "<span class='warning'>You moved out of range of [giver]!</span>")
|
||||
usr.clear_alert("[giver]")
|
||||
src.offerer = offerer
|
||||
RegisterSignal(taker, COMSIG_MOVABLE_MOVED, .proc/check_in_range, override = TRUE) //Override to prevent runtimes when people offer a item multiple times
|
||||
|
||||
/atom/movable/screen/alert/give/Click(location, control, params)
|
||||
. = ..()
|
||||
var/mob/living/carbon/C = usr
|
||||
C.take(giver, receiving)
|
||||
if(!.)
|
||||
return
|
||||
if(!iscarbon(usr))
|
||||
CRASH("User for [src] is of type \[[usr.type]\]. This should never happen.")
|
||||
handle_transfer()
|
||||
|
||||
/// An overrideable proc used simply to hand over the item when claimed, this is a proc so that high-fives can override them since nothing is actually transferred
|
||||
/atom/movable/screen/alert/give/proc/handle_transfer()
|
||||
var/mob/living/carbon/taker = owner
|
||||
taker.take(offerer, receiving)
|
||||
|
||||
/// Simply checks if the other person is still in range
|
||||
/atom/movable/screen/alert/give/proc/check_in_range(atom/taker)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!offerer.CanReach(taker))
|
||||
to_chat(owner, span_warning("You moved out of range of [offerer]!"))
|
||||
owner.clear_alert("[offerer]")
|
||||
|
||||
/atom/movable/screen/alert/give/highfive/setup(mob/living/carbon/taker, mob/living/carbon/offerer, obj/item/receiving)
|
||||
. = ..()
|
||||
name = "[offerer] is offering a high-five!"
|
||||
desc = "[offerer] is offering a high-five! Click this alert to slap it."
|
||||
RegisterSignal(offerer, COMSIG_PARENT_EXAMINE_MORE, .proc/check_fake_out)
|
||||
|
||||
/atom/movable/screen/alert/give/highfive/handle_transfer()
|
||||
var/mob/living/carbon/taker = owner
|
||||
if(receiving && (receiving in offerer.held_items))
|
||||
receiving.on_offer_taken(offerer, taker)
|
||||
return
|
||||
too_slow_p1()
|
||||
|
||||
/// If the person who offered the high five no longer has it when we try to accept it, we get pranked hard
|
||||
/atom/movable/screen/alert/give/highfive/proc/too_slow_p1()
|
||||
var/mob/living/carbon/rube = owner
|
||||
if(!rube || !offerer)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
offerer.visible_message(span_notice("[rube] rushes in to high-five [offerer], but-"), span_nicegreen("[rube] falls for your trick just as planned, lunging for a high-five that no longer exists! Classic!"), ignored_mobs=rube)
|
||||
to_chat(rube, span_nicegreen("You go in for [offerer]'s high-five, but-"))
|
||||
addtimer(CALLBACK(src, .proc/too_slow_p2, offerer, rube), 0.5 SECONDS)
|
||||
|
||||
/// Part two of the ultimate prank
|
||||
/atom/movable/screen/alert/give/highfive/proc/too_slow_p2()
|
||||
var/mob/living/carbon/rube = owner
|
||||
if(!rube || !offerer)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
offerer.visible_message(span_danger("[offerer] pulls away from [rube]'s slap at the last second, dodging the high-five entirely!"), span_nicegreen("[rube] fails to make contact with your hand, making an utter fool of [rube.p_them()]self!"), span_hear("You hear a disappointing sound of flesh not hitting flesh!"), ignored_mobs=rube)
|
||||
var/all_caps_for_emphasis = uppertext("NO! [offerer] PULLS [offerer.p_their()] HAND AWAY FROM YOURS! YOU'RE TOO SLOW!")
|
||||
to_chat(rube, span_userdanger("[all_caps_for_emphasis]"))
|
||||
playsound(offerer, 'sound/weapons/thudswoosh.ogg', 100, TRUE, 1)
|
||||
rube.Knockdown(1 SECONDS)
|
||||
SEND_SIGNAL(offerer, COMSIG_ADD_MOOD_EVENT, "high_five", /datum/mood_event/down_low)
|
||||
SEND_SIGNAL(rube, COMSIG_ADD_MOOD_EVENT, "high_five", /datum/mood_event/too_slow)
|
||||
qdel(src)
|
||||
|
||||
/// If someone examine_more's the offerer while they're trying to pull a too-slow, it'll tip them off to the offerer's trickster ways
|
||||
/atom/movable/screen/alert/give/highfive/proc/check_fake_out(datum/source, mob/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!receiving)
|
||||
examine_list += "[span_warning("[offerer]'s arm appears tensed up, as if [offerer.p_they()] plan on pulling it back suddenly...")]\n"
|
||||
|
||||
/// Families handshakes
|
||||
/atom/movable/screen/alert/give/secret_handshake
|
||||
icon_state = "default"
|
||||
|
||||
/atom/movable/screen/alert/give/secret_handshake/setup(mob/living/carbon/taker, mob/living/carbon/offerer, obj/item/receiving)
|
||||
name = "[offerer] is offering a Handshake"
|
||||
desc = "[offerer] wants to teach you the Secret Handshake for their Family and induct you! Click on this alert to accept."
|
||||
icon_state = "template"
|
||||
cut_overlays()
|
||||
add_overlay(receiving)
|
||||
src.receiving = receiving
|
||||
src.offerer = offerer
|
||||
RegisterSignal(taker, COMSIG_MOVABLE_MOVED, .proc/check_in_range, override = TRUE) //Override to prevent runtimes when people offer a item multiple times
|
||||
|
||||
//ALIENS
|
||||
|
||||
@@ -393,10 +468,10 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
/atom/movable/screen/alert/bloodsense/process()
|
||||
var/atom/blood_target
|
||||
|
||||
if(!mob_viewer.mind)
|
||||
if(!owner.mind)
|
||||
return
|
||||
|
||||
var/datum/antagonist/cult/antag = mob_viewer.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
|
||||
var/datum/antagonist/cult/antag = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
|
||||
if(!antag?.cult_team)
|
||||
return
|
||||
var/datum/objective/sacrifice/sac_objective = locate() in antag.cult_team.objectives
|
||||
@@ -433,7 +508,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
add_overlay(narnar)
|
||||
return
|
||||
var/turf/P = get_turf(blood_target)
|
||||
var/turf/Q = get_turf(mob_viewer)
|
||||
var/turf/Q = get_turf(owner)
|
||||
if(!P || !Q || (P.z != Q.z)) //The target is on a different Z level, we cannot sense that far.
|
||||
icon_state = "runed_sense2"
|
||||
desc = "You can no longer sense your target's presence."
|
||||
@@ -497,7 +572,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
for(var/mob/living/L in GLOB.alive_mob_list)
|
||||
if(is_servant_of_ratvar(L))
|
||||
servants++
|
||||
var/datum/antagonist/clockcult/C = mob_viewer.mind.has_antag_datum(/datum/antagonist/clockcult,TRUE)
|
||||
var/datum/antagonist/clockcult/C = owner.mind.has_antag_datum(/datum/antagonist/clockcult,TRUE)
|
||||
if(C && C.clock_team)
|
||||
textlist += "[C.clock_team.eminence ? "There is an Eminence." : "<b>There is no Eminence! Get one ASAP!</b>"]<br>"
|
||||
textlist += "There are currently <b>[servants]</b> servant[servants > 1 ? "s" : ""] of Ratvar.<br>"
|
||||
@@ -595,7 +670,7 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
var/atom/target = null
|
||||
|
||||
/atom/movable/screen/alert/hackingapc/Click()
|
||||
if(!usr || !usr.client)
|
||||
if(!usr || !usr.client || usr != owner)
|
||||
return
|
||||
if(!target)
|
||||
return
|
||||
@@ -621,7 +696,7 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
timeout = 300
|
||||
|
||||
/atom/movable/screen/alert/notify_cloning/Click()
|
||||
if(!usr || !usr.client)
|
||||
if(!usr || !usr.client || usr != owner)
|
||||
return
|
||||
var/mob/dead/observer/G = usr
|
||||
G.reenter_corpse()
|
||||
@@ -635,7 +710,7 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
var/action = NOTIFY_JUMP
|
||||
|
||||
/atom/movable/screen/alert/notify_action/Click()
|
||||
if(!usr || !usr.client)
|
||||
if(!usr || !usr.client || usr != owner)
|
||||
return
|
||||
if(!target)
|
||||
return
|
||||
@@ -669,14 +744,14 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
|
||||
/atom/movable/screen/alert/restrained/Click()
|
||||
var/mob/living/L = usr
|
||||
if(!istype(L) || !L.can_resist())
|
||||
if(!istype(L) || !L.can_resist() || L != owner)
|
||||
return
|
||||
L.MarkResistTime()
|
||||
return L.resist_restraints()
|
||||
|
||||
/atom/movable/screen/alert/restrained/buckled/Click()
|
||||
var/mob/living/L = usr
|
||||
if(!istype(L) || !L.can_resist())
|
||||
if(!istype(L) || !L.can_resist() || L != owner)
|
||||
return
|
||||
L.MarkResistTime()
|
||||
return L.resist_buckle()
|
||||
@@ -693,7 +768,7 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
|
||||
/atom/movable/screen/alert/shoes/Click()
|
||||
var/mob/living/carbon/C = usr
|
||||
if(!istype(C) || !C.can_resist() || C != mob_viewer || !C.shoes)
|
||||
if(!istype(C) || !C.can_resist() || C != owner || !C.shoes)
|
||||
return
|
||||
C.MarkResistTime()
|
||||
C.shoes.handle_tying(C)
|
||||
@@ -701,11 +776,14 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
// PRIVATE = only edit, use, or override these if you're editing the system as a whole
|
||||
|
||||
// Re-render all alerts - also called in /datum/hud/show_hud() because it's needed there
|
||||
/datum/hud/proc/reorganize_alerts()
|
||||
/datum/hud/proc/reorganize_alerts(mob/viewmob)
|
||||
var/mob/screenmob = viewmob || mymob
|
||||
if(!screenmob.client)
|
||||
return
|
||||
var/list/alerts = mymob.alerts
|
||||
if(!hud_shown)
|
||||
for(var/i = 1, i <= alerts.len, i++)
|
||||
mymob.client.screen -= alerts[alerts[i]]
|
||||
screenmob.client.screen -= alerts[alerts[i]]
|
||||
return 1
|
||||
for(var/i = 1, i <= alerts.len, i++)
|
||||
var/atom/movable/screen/alert/alert = alerts[alerts[i]]
|
||||
@@ -725,22 +803,29 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
else
|
||||
. = ""
|
||||
alert.screen_loc = .
|
||||
mymob.client.screen |= alert
|
||||
screenmob.client.screen |= alert
|
||||
if(!viewmob)
|
||||
for(var/M in mymob.observers)
|
||||
reorganize_alerts(M)
|
||||
return 1
|
||||
|
||||
/atom/movable/screen/alert/Click(location, control, params)
|
||||
if(!usr || !usr.client)
|
||||
return
|
||||
return FALSE
|
||||
if(usr != owner)
|
||||
return FALSE
|
||||
var/paramslist = params2list(params)
|
||||
if(paramslist["shift"]) // screen objects don't do the normal Click() stuff so we'll cheat
|
||||
to_chat(usr, "<span class='boldnotice'>[name]</span> - <span class='info'>[desc]</span>")
|
||||
return
|
||||
if(master)
|
||||
return FALSE
|
||||
if(master && click_master)
|
||||
return usr.client.Click(master, location, control, params)
|
||||
|
||||
return TRUE
|
||||
|
||||
/atom/movable/screen/alert/Destroy()
|
||||
. = ..()
|
||||
severity = 0
|
||||
master = null
|
||||
mob_viewer = null
|
||||
owner = null
|
||||
screen_loc = ""
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
icon = I
|
||||
parent = P
|
||||
icon_state = credited
|
||||
maptext = credited
|
||||
maptext = MAPTEXT(credited)
|
||||
maptext_x = world.icon_size + 8
|
||||
maptext_y = (world.icon_size / 2) - 4
|
||||
maptext_width = world.icon_size * 3
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/atom/movable/screen/wanted
|
||||
name = "Space Police Alertness"
|
||||
desc = "Shows the current level of hostility the space police is planning to rain down on you. Better be careful."
|
||||
icon = 'icons/obj/gang/wanted_160x32.dmi'
|
||||
icon_state = "wanted_0"
|
||||
screen_loc = ui_wanted_lvl
|
||||
/// Wanted level, affects the hud icon. Level 0 is default, and the level 0 icon is blank, so in case of no families gamemode (and thus no wanted level), this HUD element will never appear.
|
||||
level = 2
|
||||
/// Boolean, have the cops arrived? If so, the icon stops changing and remains the same.
|
||||
var/cops_arrived = 0
|
||||
|
||||
/atom/movable/screen/wanted/New()
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/wanted/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/atom/movable/screen/wanted/MouseEntered(location,control,params)
|
||||
openToolTip(usr,src,params,title = name,content = desc, theme = "alerttooltipstyle")
|
||||
|
||||
/atom/movable/screen/wanted/MouseExited()
|
||||
closeToolTip(usr)
|
||||
|
||||
/atom/movable/screen/wanted/update_icon_state()
|
||||
. = ..()
|
||||
icon_state = "wanted_[level][cops_arrived ? "_active" : ""]"
|
||||
@@ -1,186 +0,0 @@
|
||||
/mob/proc/overlay_fullscreen(category, type, severity)
|
||||
var/atom/movable/screen/fullscreen/screen = screens[category]
|
||||
if (!screen || screen.type != type)
|
||||
// needs to be recreated
|
||||
clear_fullscreen(category, FALSE)
|
||||
screens[category] = screen = new type()
|
||||
else if ((!severity || severity == screen.severity) && (!client || screen.screen_loc != "CENTER-7,CENTER-7" || screen.view == client.view))
|
||||
// doesn't need to be updated
|
||||
return screen
|
||||
|
||||
screen.icon_state = "[initial(screen.icon_state)][severity]"
|
||||
screen.severity = severity
|
||||
if (client && screen.should_show_to(src))
|
||||
screen.update_for_view(client.view)
|
||||
client.screen += screen
|
||||
|
||||
return screen
|
||||
|
||||
/mob/proc/clear_fullscreen(category, animated = 10)
|
||||
var/atom/movable/screen/fullscreen/screen = screens[category]
|
||||
if(!screen)
|
||||
return
|
||||
|
||||
screens -= category
|
||||
|
||||
if(animated)
|
||||
animate(screen, alpha = 0, time = animated)
|
||||
addtimer(CALLBACK(src, .proc/clear_fullscreen_after_animate, screen), animated, TIMER_CLIENT_TIME)
|
||||
else
|
||||
if(client)
|
||||
client.screen -= screen
|
||||
qdel(screen)
|
||||
|
||||
/mob/proc/clear_fullscreen_after_animate(atom/movable/screen/fullscreen/screen)
|
||||
if(client)
|
||||
client.screen -= screen
|
||||
qdel(screen)
|
||||
|
||||
/mob/proc/clear_fullscreens()
|
||||
for(var/category in screens)
|
||||
clear_fullscreen(category)
|
||||
|
||||
/mob/proc/hide_fullscreens()
|
||||
if(client)
|
||||
for(var/category in screens)
|
||||
client.screen -= screens[category]
|
||||
|
||||
/mob/proc/reload_fullscreen()
|
||||
if(client)
|
||||
var/atom/movable/screen/fullscreen/screen
|
||||
for(var/category in screens)
|
||||
screen = screens[category]
|
||||
if(screen.should_show_to(src))
|
||||
screen.update_for_view(client.view)
|
||||
client.screen |= screen
|
||||
else
|
||||
client.screen -= screen
|
||||
|
||||
/atom/movable/screen/fullscreen
|
||||
icon = 'icons/mob/screen_full.dmi'
|
||||
icon_state = "default"
|
||||
screen_loc = "CENTER-7,CENTER-7"
|
||||
layer = FULLSCREEN_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
var/view = 7
|
||||
var/severity = 0
|
||||
var/show_when_dead = FALSE
|
||||
|
||||
/atom/movable/screen/fullscreen/proc/update_for_view(client_view)
|
||||
if (screen_loc == "CENTER-7,CENTER-7" && view != client_view)
|
||||
var/list/actualview = getviewsize(client_view)
|
||||
view = client_view
|
||||
transform = matrix(actualview[1]/FULLSCREEN_OVERLAY_RESOLUTION_X, 0, 0, 0, actualview[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y, 0)
|
||||
|
||||
/atom/movable/screen/fullscreen/proc/should_show_to(mob/mymob)
|
||||
if(!show_when_dead && mymob.stat == DEAD)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/Destroy()
|
||||
severity = 0
|
||||
. = ..()
|
||||
|
||||
/atom/movable/screen/fullscreen/brute
|
||||
icon_state = "brutedamageoverlay"
|
||||
layer = UI_DAMAGE_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/oxy
|
||||
icon_state = "oxydamageoverlay"
|
||||
layer = UI_DAMAGE_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/crit
|
||||
icon_state = "passage"
|
||||
layer = CRIT_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/crit/vision
|
||||
icon_state = "oxydamageoverlay"
|
||||
layer = BLIND_LAYER
|
||||
|
||||
/atom/movable/screen/fullscreen/blind
|
||||
icon_state = "blackimageoverlay"
|
||||
layer = BLIND_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/curse
|
||||
icon_state = "curse"
|
||||
layer = CURSE_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/impaired
|
||||
icon_state = "impairedoverlay"
|
||||
|
||||
/atom/movable/screen/fullscreen/blurry
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "blurry"
|
||||
|
||||
/atom/movable/screen/fullscreen/flash
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "flash"
|
||||
|
||||
/atom/movable/screen/fullscreen/flash/static
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "noise"
|
||||
|
||||
/atom/movable/screen/fullscreen/high
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "druggy"
|
||||
|
||||
/atom/movable/screen/fullscreen/color_vision
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "flash"
|
||||
alpha = 80
|
||||
|
||||
/atom/movable/screen/fullscreen/color_vision/green
|
||||
color = "#00ff00"
|
||||
|
||||
/atom/movable/screen/fullscreen/color_vision/red
|
||||
color = "#ff0000"
|
||||
|
||||
/atom/movable/screen/fullscreen/color_vision/blue
|
||||
color = "#0000ff"
|
||||
|
||||
/atom/movable/screen/fullscreen/cinematic_backdrop
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "flash"
|
||||
plane = SPLASHSCREEN_PLANE
|
||||
layer = SPLASHSCREEN_LAYER - 1
|
||||
color = "#000000"
|
||||
show_when_dead = TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/lighting_backdrop
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "flash"
|
||||
transform = matrix(200, 0, 0, 0, 200, 0)
|
||||
plane = LIGHTING_PLANE
|
||||
blend_mode = BLEND_OVERLAY
|
||||
show_when_dead = TRUE
|
||||
|
||||
//Provides darkness to the back of the lighting plane
|
||||
/atom/movable/screen/fullscreen/lighting_backdrop/lit
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
layer = BACKGROUND_LAYER+21
|
||||
color = "#000"
|
||||
show_when_dead = TRUE
|
||||
|
||||
//Provides whiteness in case you don't see lights so everything is still visible
|
||||
/atom/movable/screen/fullscreen/lighting_backdrop/unlit
|
||||
layer = BACKGROUND_LAYER+20
|
||||
show_when_dead = TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/see_through_darkness
|
||||
icon_state = "nightvision"
|
||||
plane = LIGHTING_PLANE
|
||||
layer = LIGHTING_LAYER
|
||||
blend_mode = BLEND_ADD
|
||||
show_when_dead = TRUE
|
||||
@@ -93,3 +93,10 @@
|
||||
screenmob.client.screen -= static_inventory
|
||||
else
|
||||
screenmob.client.screen += static_inventory
|
||||
|
||||
//We should only see observed mob alerts.
|
||||
/datum/hud/ghost/reorganize_alerts(mob/viewmob)
|
||||
var/mob/dead/observer/O = mymob
|
||||
if (istype(O) && O.observetarget)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
@@ -35,6 +35,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
|
||||
var/atom/movable/screen/devil/soul_counter/devilsouldisplay
|
||||
|
||||
var/atom/movable/screen/synth/coolant_counter/coolant_display
|
||||
|
||||
var/atom/movable/screen/action_intent
|
||||
var/atom/movable/screen/zone_select
|
||||
var/atom/movable/screen/pull_icon
|
||||
@@ -58,6 +60,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
var/atom/movable/screen/healthdoll
|
||||
var/atom/movable/screen/internals
|
||||
|
||||
var/atom/movable/screen/wanted/wanted_lvl
|
||||
// subtypes can override this to force a specific UI style
|
||||
var/ui_style
|
||||
|
||||
@@ -80,6 +83,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
plane_masters["[instance.plane]"] = instance
|
||||
instance.backdrop(mymob)
|
||||
|
||||
|
||||
/datum/hud/Destroy()
|
||||
if(mymob.hud_used == src)
|
||||
mymob.hud_used = null
|
||||
@@ -100,6 +104,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
|
||||
healths = null
|
||||
healthdoll = null
|
||||
wanted_lvl = null
|
||||
internals = null
|
||||
lingchemdisplay = null
|
||||
devilsouldisplay = null
|
||||
@@ -131,7 +136,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
return FALSE
|
||||
|
||||
screenmob.client.screen = list()
|
||||
screenmob.client.apply_clickcatcher()
|
||||
screenmob.client.update_clickcatcher()
|
||||
|
||||
var/display_hud_version = version
|
||||
if(!display_hud_version) //If 0 or blank, display the next hud version
|
||||
@@ -191,8 +196,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
persistent_inventory_update(screenmob)
|
||||
screenmob.update_action_buttons(1)
|
||||
reorganize_alerts()
|
||||
screenmob.reload_fullscreen()
|
||||
update_parallax_pref(screenmob)
|
||||
|
||||
// ensure observers get an accurate and up-to-date view
|
||||
if (!viewmob)
|
||||
@@ -202,6 +205,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
else if (viewmob.hud_used)
|
||||
viewmob.hud_used.plane_masters_update()
|
||||
|
||||
screenmob.reload_rendering()
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/hud/proc/plane_masters_update()
|
||||
|
||||
@@ -80,9 +80,101 @@
|
||||
icon_state = "power_display"
|
||||
screen_loc = ui_lingchemdisplay
|
||||
|
||||
#define ui_coolant_display "EAST,SOUTH+3:15"
|
||||
|
||||
/atom/movable/screen/synth
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
|
||||
/atom/movable/screen/synth/proc/clear()
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
/atom/movable/screen/synth/proc/update_counter(mob/living/carbon/human/owner)
|
||||
invisibility = 0
|
||||
|
||||
/atom/movable/screen/synth/coolant_counter
|
||||
icon = 'icons/mob/screen_synth.dmi'
|
||||
name = "Coolant System Readout"
|
||||
icon_state = "coolant-3-1"
|
||||
screen_loc = ui_coolant_display
|
||||
var/jammed = 0
|
||||
|
||||
/atom/movable/screen/synth/coolant_counter/update_counter(mob/living/carbon/owner)
|
||||
..()
|
||||
var/valuecolor = "#ff2525"
|
||||
if(owner.stat == DEAD)
|
||||
maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='[valuecolor]'>ERR-0F</font></div>"
|
||||
icon_state = "coolant-3-1"
|
||||
return
|
||||
var/coolant_efficiency
|
||||
var/coolant
|
||||
if(!jammed)
|
||||
coolant_efficiency = owner.get_cooling_efficiency()
|
||||
coolant = owner.blood_volume
|
||||
else
|
||||
coolant_efficiency = rand(1, 15) / 10
|
||||
coolant = rand(1, 600)
|
||||
jammed--
|
||||
if(coolant > BLOOD_VOLUME_SAFE * owner.blood_ratio) //I unfortunately have to use this else-if stack because switch doesn't support variables.
|
||||
valuecolor = "#4bbd34"
|
||||
else if(coolant > BLOOD_VOLUME_OKAY * owner.blood_ratio)
|
||||
valuecolor = "#dabb0d"
|
||||
else if(coolant > BLOOD_VOLUME_BAD * owner.blood_ratio)
|
||||
valuecolor = "#dd8109"
|
||||
else if(coolant > BLOOD_VOLUME_SURVIVE * owner.blood_ratio)
|
||||
valuecolor = "#e7520d"
|
||||
maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='[valuecolor]'>[round((coolant / (BLOOD_VOLUME_NORMAL * owner.blood_ratio)) * 100, 1)]</font></div>"
|
||||
|
||||
var/efficiency_suffix
|
||||
var/state_suffix
|
||||
switch(coolant_efficiency)
|
||||
if(-INFINITY to 0.4)
|
||||
efficiency_suffix = "1"
|
||||
if(0.4 to 0.75)
|
||||
efficiency_suffix = "2"
|
||||
if(0.75 to 0.95)
|
||||
efficiency_suffix = "3"
|
||||
if(0.95 to 1.3)
|
||||
efficiency_suffix = "4"
|
||||
else
|
||||
efficiency_suffix = "5"
|
||||
var/obj/item/organ/lungs/ipc/L = owner.getorganslot(ORGAN_SLOT_LUNGS)
|
||||
if(istype(L) && L.is_cooling)
|
||||
state_suffix = "2"
|
||||
else
|
||||
state_suffix = "1"
|
||||
icon_state = "coolant-[efficiency_suffix]-[state_suffix]"
|
||||
|
||||
/atom/movable/screen/synth/coolant_counter/examine(mob/user)
|
||||
. = ..()
|
||||
var/mob/living/carbon/human/owner = hud.mymob
|
||||
if(owner.stat == DEAD)
|
||||
return
|
||||
var/coolant
|
||||
var/total_efficiency
|
||||
var/environ_efficiency
|
||||
var/suitlink_efficiency
|
||||
if(!jammed)
|
||||
coolant = owner.blood_volume
|
||||
total_efficiency = owner.get_cooling_efficiency()
|
||||
environ_efficiency = owner.get_environment_cooling_efficiency()
|
||||
suitlink_efficiency = owner.check_suitlinking()
|
||||
else
|
||||
coolant = rand(1, 600)
|
||||
total_efficiency = rand(1, 15) / 10
|
||||
environ_efficiency = rand(1, 20) / 10
|
||||
. += "<span class='notice'>Performing internal cooling system diagnostics:</span>"
|
||||
. += "<span class='notice'>Coolant level: [coolant] units, [round((coolant / (BLOOD_VOLUME_NORMAL * owner.blood_ratio)) * 100, 0.1)] percent</span>"
|
||||
. += "<span class='notice'>Current Cooling Efficiency: [round(total_efficiency * 100, 0.1)] percent, [suitlink_efficiency ? "<font color='green'>active suitlink detected</font>, guaranteeing <font color='green'>[suitlink_efficiency * 100]%</font> environmental cooling efficiency." : "environment viability: [round(environ_efficiency * 100, 0.1)] percent."]</span>"
|
||||
|
||||
/atom/movable/screen/synth/coolant_counter/proc/jam(amount, cap = 20)
|
||||
if(jammed > cap) //Preserve previous more impactful event.
|
||||
return
|
||||
jammed = min(jammed + amount, cap)
|
||||
|
||||
/datum/hud/human/New(mob/living/carbon/human/owner)
|
||||
..()
|
||||
owner.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/see_through_darkness)
|
||||
owner.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/special/see_through_darkness)
|
||||
|
||||
var/widescreenlayout = FALSE //CIT CHANGE - adds support for different hud layouts depending on widescreen pref
|
||||
if(owner.client && owner.client.prefs && owner.client.prefs.widescreenpref) //CIT CHANGE - ditto
|
||||
@@ -359,6 +451,10 @@
|
||||
sunlight_display.hud = src
|
||||
infodisplay += sunlight_display
|
||||
|
||||
coolant_display = new /atom/movable/screen/synth/coolant_counter //Coolant & cooling efficiency readouts for Synths.
|
||||
coolant_display.hud = src
|
||||
infodisplay += coolant_display
|
||||
|
||||
zone_select = new /atom/movable/screen/zone_sel()
|
||||
zone_select.icon = ui_style
|
||||
zone_select.hud = src
|
||||
|
||||
@@ -1,322 +0,0 @@
|
||||
|
||||
/datum/hud/proc/create_parallax(mob/viewmob)
|
||||
var/mob/screenmob = viewmob || mymob
|
||||
var/client/C = screenmob.client
|
||||
if (!apply_parallax_pref(viewmob)) //don't want shit computers to crash when specing someone with insane parallax, so use the viewer's pref
|
||||
return
|
||||
|
||||
if(!length(C.parallax_layers_cached))
|
||||
C.parallax_layers_cached = list()
|
||||
C.parallax_layers_cached += new /atom/movable/screen/parallax_layer/layer_1(null, C.view)
|
||||
C.parallax_layers_cached += new /atom/movable/screen/parallax_layer/layer_2(null, C.view)
|
||||
C.parallax_layers_cached += new /atom/movable/screen/parallax_layer/planet(null, C.view)
|
||||
if(SSparallax.random_layer)
|
||||
C.parallax_layers_cached += new SSparallax.random_layer
|
||||
C.parallax_layers_cached += new /atom/movable/screen/parallax_layer/layer_3(null, C.view)
|
||||
|
||||
C.parallax_layers = C.parallax_layers_cached.Copy()
|
||||
|
||||
if (length(C.parallax_layers) > C.parallax_layers_max)
|
||||
C.parallax_layers.len = C.parallax_layers_max
|
||||
|
||||
C.screen |= (C.parallax_layers)
|
||||
var/atom/movable/screen/plane_master/PM = screenmob.hud_used.plane_masters["[PLANE_SPACE]"]
|
||||
if(screenmob != mymob)
|
||||
C.screen -= locate(/atom/movable/screen/plane_master/parallax_white) in C.screen
|
||||
C.screen += PM
|
||||
PM.color = list(
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
1, 1, 1, 1,
|
||||
0, 0, 0, 0
|
||||
)
|
||||
|
||||
|
||||
/datum/hud/proc/remove_parallax(mob/viewmob)
|
||||
var/mob/screenmob = viewmob || mymob
|
||||
var/client/C = screenmob.client
|
||||
C.screen -= (C.parallax_layers_cached)
|
||||
var/atom/movable/screen/plane_master/PM = screenmob.hud_used.plane_masters["[PLANE_SPACE]"]
|
||||
if(screenmob != mymob)
|
||||
C.screen -= locate(/atom/movable/screen/plane_master/parallax_white) in C.screen
|
||||
C.screen += PM
|
||||
PM.color = initial(PM.color)
|
||||
C.parallax_layers = null
|
||||
|
||||
/datum/hud/proc/apply_parallax_pref(mob/viewmob)
|
||||
var/mob/screenmob = viewmob || mymob
|
||||
var/client/C = screenmob.client
|
||||
if(C.prefs)
|
||||
var/pref = C.prefs.parallax
|
||||
if (isnull(pref))
|
||||
pref = PARALLAX_HIGH
|
||||
switch(C.prefs.parallax)
|
||||
if (PARALLAX_INSANE)
|
||||
C.parallax_throttle = FALSE
|
||||
C.parallax_layers_max = 5
|
||||
return TRUE
|
||||
|
||||
if (PARALLAX_MED)
|
||||
C.parallax_throttle = PARALLAX_DELAY_MED
|
||||
C.parallax_layers_max = 3
|
||||
return TRUE
|
||||
|
||||
if (PARALLAX_LOW)
|
||||
C.parallax_throttle = PARALLAX_DELAY_LOW
|
||||
C.parallax_layers_max = 1
|
||||
return TRUE
|
||||
|
||||
if (PARALLAX_DISABLE)
|
||||
return FALSE
|
||||
|
||||
//This is high parallax.
|
||||
C.parallax_throttle = PARALLAX_DELAY_DEFAULT
|
||||
C.parallax_layers_max = 4
|
||||
return TRUE
|
||||
|
||||
/datum/hud/proc/update_parallax_pref(mob/viewmob)
|
||||
remove_parallax(viewmob)
|
||||
create_parallax(viewmob)
|
||||
update_parallax()
|
||||
|
||||
// This sets which way the current shuttle is moving (returns true if the shuttle has stopped moving so the caller can append their animation)
|
||||
/datum/hud/proc/set_parallax_movedir(new_parallax_movedir, skip_windups)
|
||||
. = FALSE
|
||||
var/client/C = mymob.client
|
||||
if(new_parallax_movedir == C.parallax_movedir)
|
||||
return
|
||||
var/animatedir = new_parallax_movedir
|
||||
if(new_parallax_movedir == FALSE)
|
||||
var/animate_time = 0
|
||||
for(var/thing in C.parallax_layers)
|
||||
var/atom/movable/screen/parallax_layer/L = thing
|
||||
L.icon_state = initial(L.icon_state)
|
||||
L.update_o(C.view)
|
||||
var/T = PARALLAX_LOOP_TIME / L.speed
|
||||
if (T > animate_time)
|
||||
animate_time = T
|
||||
C.dont_animate_parallax = world.time + min(animate_time, PARALLAX_LOOP_TIME)
|
||||
animatedir = C.parallax_movedir
|
||||
|
||||
var/matrix/newtransform
|
||||
switch(animatedir)
|
||||
if(NORTH)
|
||||
newtransform = matrix(1, 0, 0, 0, 1, 480)
|
||||
if(SOUTH)
|
||||
newtransform = matrix(1, 0, 0, 0, 1,-480)
|
||||
if(EAST)
|
||||
newtransform = matrix(1, 0, 480, 0, 1, 0)
|
||||
if(WEST)
|
||||
newtransform = matrix(1, 0,-480, 0, 1, 0)
|
||||
|
||||
var/shortesttimer
|
||||
if(!skip_windups)
|
||||
for(var/thing in C.parallax_layers)
|
||||
var/atom/movable/screen/parallax_layer/L = thing
|
||||
|
||||
var/T = PARALLAX_LOOP_TIME / L.speed
|
||||
if (isnull(shortesttimer))
|
||||
shortesttimer = T
|
||||
if (T < shortesttimer)
|
||||
shortesttimer = T
|
||||
L.transform = newtransform
|
||||
animate(L, transform = matrix(), time = T, easing = QUAD_EASING | (new_parallax_movedir ? EASE_IN : EASE_OUT), flags = ANIMATION_END_NOW)
|
||||
if (new_parallax_movedir)
|
||||
L.transform = newtransform
|
||||
animate(transform = matrix(), time = T) //queue up another animate so lag doesn't create a shutter
|
||||
|
||||
C.parallax_movedir = new_parallax_movedir
|
||||
if (C.parallax_animate_timer)
|
||||
deltimer(C.parallax_animate_timer)
|
||||
var/datum/callback/CB = CALLBACK(src, .proc/update_parallax_motionblur, C, animatedir, new_parallax_movedir, newtransform)
|
||||
if(skip_windups)
|
||||
CB.InvokeAsync()
|
||||
else
|
||||
C.parallax_animate_timer = addtimer(CB, min(shortesttimer, PARALLAX_LOOP_TIME), TIMER_CLIENT_TIME|TIMER_STOPPABLE)
|
||||
|
||||
|
||||
/datum/hud/proc/update_parallax_motionblur(client/C, animatedir, new_parallax_movedir, matrix/newtransform)
|
||||
if(!C)
|
||||
return
|
||||
C.parallax_animate_timer = FALSE
|
||||
for(var/thing in C.parallax_layers)
|
||||
var/atom/movable/screen/parallax_layer/L = thing
|
||||
if (!new_parallax_movedir)
|
||||
animate(L)
|
||||
continue
|
||||
|
||||
var/newstate = initial(L.icon_state)
|
||||
var/T = PARALLAX_LOOP_TIME / L.speed
|
||||
|
||||
if (newstate in icon_states(L.icon))
|
||||
L.icon_state = newstate
|
||||
L.update_o(C.view)
|
||||
|
||||
L.transform = newtransform
|
||||
|
||||
animate(L, transform = matrix(), time = T, loop = -1, flags = ANIMATION_END_NOW)
|
||||
|
||||
/datum/hud/proc/update_parallax()
|
||||
var/client/C = mymob.client
|
||||
var/turf/posobj = get_turf(C.eye)
|
||||
if(!posobj)
|
||||
return
|
||||
var/area/areaobj = posobj.loc
|
||||
|
||||
// Update the movement direction of the parallax if necessary (for shuttles)
|
||||
set_parallax_movedir(areaobj.parallax_movedir, FALSE)
|
||||
|
||||
var/force
|
||||
if(!C.previous_turf || (C.previous_turf.z != posobj.z))
|
||||
C.previous_turf = posobj
|
||||
force = TRUE
|
||||
|
||||
if (!force && world.time < C.last_parallax_shift+C.parallax_throttle)
|
||||
return
|
||||
|
||||
//Doing it this way prevents parallax layers from "jumping" when you change Z-Levels.
|
||||
var/offset_x = posobj.x - C.previous_turf.x
|
||||
var/offset_y = posobj.y - C.previous_turf.y
|
||||
|
||||
if(!offset_x && !offset_y && !force)
|
||||
return
|
||||
|
||||
var/last_delay = world.time - C.last_parallax_shift
|
||||
last_delay = min(last_delay, C.parallax_throttle)
|
||||
C.previous_turf = posobj
|
||||
C.last_parallax_shift = world.time
|
||||
|
||||
for(var/thing in C.parallax_layers)
|
||||
var/atom/movable/screen/parallax_layer/L = thing
|
||||
L.update_status(mymob)
|
||||
if (L.view_sized != C.view)
|
||||
L.update_o(C.view)
|
||||
|
||||
var/change_x
|
||||
var/change_y
|
||||
|
||||
if(L.absolute)
|
||||
L.offset_x = -(posobj.x - SSparallax.planet_x_offset) * L.speed
|
||||
L.offset_y = -(posobj.y - SSparallax.planet_y_offset) * L.speed
|
||||
else
|
||||
change_x = offset_x * L.speed
|
||||
L.offset_x -= change_x
|
||||
change_y = offset_y * L.speed
|
||||
L.offset_y -= change_y
|
||||
|
||||
if(L.offset_x > 240)
|
||||
L.offset_x -= 480
|
||||
if(L.offset_x < -240)
|
||||
L.offset_x += 480
|
||||
if(L.offset_y > 240)
|
||||
L.offset_y -= 480
|
||||
if(L.offset_y < -240)
|
||||
L.offset_y += 480
|
||||
|
||||
|
||||
if(!areaobj.parallax_movedir && C.dont_animate_parallax <= world.time && (offset_x || offset_y) && abs(offset_x) <= max(C.parallax_throttle/world.tick_lag+1,1) && abs(offset_y) <= max(C.parallax_throttle/world.tick_lag+1,1) && (round(abs(change_x)) > 1 || round(abs(change_y)) > 1))
|
||||
L.transform = matrix(1, 0, offset_x*L.speed, 0, 1, offset_y*L.speed)
|
||||
animate(L, transform=matrix(), time = last_delay)
|
||||
|
||||
L.screen_loc = "CENTER-7:[round(L.offset_x,1)],CENTER-7:[round(L.offset_y,1)]"
|
||||
|
||||
/atom/movable/proc/update_parallax_contents()
|
||||
if(length(client_mobs_in_contents))
|
||||
for(var/thing in client_mobs_in_contents)
|
||||
var/mob/M = thing
|
||||
if(M?.client && M.hud_used && length(M.client.parallax_layers))
|
||||
M.hud_used.update_parallax()
|
||||
|
||||
/mob/proc/update_parallax_teleport() //used for arrivals shuttle
|
||||
if(client?.eye && hud_used && length(client.parallax_layers))
|
||||
var/area/areaobj = get_area(client.eye)
|
||||
hud_used.set_parallax_movedir(areaobj.parallax_movedir, TRUE)
|
||||
|
||||
/atom/movable/screen/parallax_layer
|
||||
icon = 'icons/effects/parallax.dmi'
|
||||
var/speed = 1
|
||||
var/offset_x = 0
|
||||
var/offset_y = 0
|
||||
var/view_sized
|
||||
var/absolute = FALSE
|
||||
blend_mode = BLEND_ADD
|
||||
plane = PLANE_SPACE_PARALLAX
|
||||
screen_loc = "CENTER-7,CENTER-7"
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
|
||||
/atom/movable/screen/parallax_layer/Initialize(mapload, view)
|
||||
. = ..()
|
||||
if (!view)
|
||||
view = world.view
|
||||
update_o(view)
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/update_o(view)
|
||||
if (!view)
|
||||
view = world.view
|
||||
|
||||
var/list/viewscales = getviewsize(view)
|
||||
var/countx = CEILING((viewscales[1]/2)/(480/world.icon_size), 1)+1
|
||||
var/county = CEILING((viewscales[2]/2)/(480/world.icon_size), 1)+1
|
||||
var/list/new_overlays = new
|
||||
for(var/x in -countx to countx)
|
||||
for(var/y in -county to county)
|
||||
if(x == 0 && y == 0)
|
||||
continue
|
||||
var/mutable_appearance/texture_overlay = mutable_appearance(icon, icon_state)
|
||||
texture_overlay.transform = matrix(1, 0, x*480, 0, 1, y*480)
|
||||
new_overlays += texture_overlay
|
||||
cut_overlays()
|
||||
add_overlay(new_overlays)
|
||||
view_sized = view
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/update_status(mob/M)
|
||||
return
|
||||
|
||||
/atom/movable/screen/parallax_layer/layer_1
|
||||
icon_state = "layer1"
|
||||
speed = 0.6
|
||||
layer = 1
|
||||
|
||||
/atom/movable/screen/parallax_layer/layer_2
|
||||
icon_state = "layer2"
|
||||
speed = 1
|
||||
layer = 2
|
||||
|
||||
/atom/movable/screen/parallax_layer/layer_3
|
||||
icon_state = "layer3"
|
||||
speed = 1.4
|
||||
layer = 3
|
||||
|
||||
/atom/movable/screen/parallax_layer/random
|
||||
blend_mode = BLEND_OVERLAY
|
||||
speed = 3
|
||||
layer = 3
|
||||
|
||||
/atom/movable/screen/parallax_layer/random/space_gas
|
||||
icon_state = "space_gas"
|
||||
|
||||
/atom/movable/screen/parallax_layer/random/space_gas/Initialize(mapload, view)
|
||||
. = ..()
|
||||
src.add_atom_colour(SSparallax.random_parallax_color, ADMIN_COLOUR_PRIORITY)
|
||||
|
||||
/atom/movable/screen/parallax_layer/random/asteroids
|
||||
icon_state = "asteroids"
|
||||
|
||||
/atom/movable/screen/parallax_layer/planet
|
||||
icon_state = "planet"
|
||||
blend_mode = BLEND_OVERLAY
|
||||
absolute = TRUE //Status of seperation
|
||||
speed = 3
|
||||
layer = 30
|
||||
|
||||
/atom/movable/screen/parallax_layer/planet/update_status(mob/M)
|
||||
var/client/C = M.client
|
||||
var/turf/posobj = get_turf(C.eye)
|
||||
if(!posobj)
|
||||
return
|
||||
invisibility = is_station_level(posobj.z) ? 0 : INVISIBILITY_ABSTRACT
|
||||
|
||||
/atom/movable/screen/parallax_layer/planet/update_o()
|
||||
return //Shit won't move
|
||||
@@ -124,8 +124,8 @@
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
/atom/movable/screen/plane_master/lighting/backdrop(mob/mymob)
|
||||
mymob.overlay_fullscreen("lighting_backdrop_lit", /atom/movable/screen/fullscreen/lighting_backdrop/lit)
|
||||
mymob.overlay_fullscreen("lighting_backdrop_unlit", /atom/movable/screen/fullscreen/lighting_backdrop/unlit)
|
||||
mymob.overlay_fullscreen("lighting_backdrop_lit", /atom/movable/screen/fullscreen/special/lighting_backdrop/lit)
|
||||
mymob.overlay_fullscreen("lighting_backdrop_unlit", /atom/movable/screen/fullscreen/special/lighting_backdrop/unlit)
|
||||
|
||||
/*!
|
||||
* This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers.
|
||||
@@ -143,7 +143,6 @@
|
||||
add_filter("emissives", 1, alpha_mask_filter(render_source = EMISSIVE_RENDER_TARGET, flags = MASK_INVERSE))
|
||||
add_filter("object_lighting", 2, alpha_mask_filter(render_source = O_LIGHTING_VISUAL_RENDER_TARGET, flags = MASK_INVERSE))
|
||||
|
||||
|
||||
/**
|
||||
* Handles emissive overlays and emissive blockers.
|
||||
*/
|
||||
@@ -163,9 +162,10 @@
|
||||
plane = PLANE_SPACE_PARALLAX
|
||||
blend_mode = BLEND_MULTIPLY
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
render_target = PLANE_SPACE_PARALLAX_RENDER_TARGET
|
||||
|
||||
/atom/movable/screen/plane_master/parallax_white
|
||||
name = "parallax whitifier plane master"
|
||||
name = "parallax backdrop/space turf plane master"
|
||||
plane = PLANE_SPACE
|
||||
|
||||
/atom/movable/screen/plane_master/camera_static
|
||||
@@ -174,7 +174,6 @@
|
||||
appearance_flags = PLANE_MASTER
|
||||
blend_mode = BLEND_OVERLAY
|
||||
|
||||
|
||||
//Reserved to chat messages, so they are still displayed above the field of vision masking.
|
||||
/atom/movable/screen/plane_master/chat_messages
|
||||
name = "runechat plane master"
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
/atom/movable/screen
|
||||
name = ""
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
layer = HUD_LAYER
|
||||
plane = HUD_PLANE
|
||||
animate_movement = SLIDE_STEPS
|
||||
speech_span = SPAN_ROBOT
|
||||
@@ -56,16 +55,12 @@
|
||||
maptext_width = 480
|
||||
|
||||
/atom/movable/screen/swap_hand
|
||||
layer = HUD_LAYER
|
||||
plane = HUD_PLANE
|
||||
name = "swap hand"
|
||||
|
||||
/atom/movable/screen/swap_hand/Click()
|
||||
// At this point in client Click() code we have passed the 1/10 sec check and little else
|
||||
// We don't even know if it's a middle click
|
||||
// if(world.time <= usr.next_move)
|
||||
// return 1
|
||||
|
||||
if(usr.incapacitated())
|
||||
return 1
|
||||
|
||||
@@ -74,6 +69,17 @@
|
||||
M.swap_hand()
|
||||
return 1
|
||||
|
||||
// /atom/movable/screen/skills
|
||||
// name = "skills"
|
||||
// icon = 'icons/mob/screen_midnight.dmi'
|
||||
// icon_state = "skills"
|
||||
// screen_loc = ui_skill_menu
|
||||
|
||||
// /atom/movable/screen/skills/Click()
|
||||
// if(ishuman(usr))
|
||||
// var/mob/living/carbon/human/H = usr
|
||||
// H.mind.print_levels(H)
|
||||
|
||||
/atom/movable/screen/craft
|
||||
name = "crafting menu"
|
||||
icon = 'icons/mob/screen_midnight.dmi'
|
||||
@@ -91,7 +97,7 @@
|
||||
return TRUE
|
||||
var/area/A = get_area(usr)
|
||||
if(!A.outdoors)
|
||||
to_chat(usr, "<span class='warning'>There is already a defined structure here.</span>")
|
||||
to_chat(usr, span_warning("There is already a defined structure here."))
|
||||
return TRUE
|
||||
create_area(usr)
|
||||
|
||||
@@ -114,15 +120,12 @@
|
||||
/// Icon when contains an item. For now used only by humans.
|
||||
var/icon_full
|
||||
/// The overlay when hovering over with an item in your hand
|
||||
var/list/object_overlays = list()
|
||||
layer = HUD_LAYER
|
||||
var/image/object_overlay
|
||||
plane = HUD_PLANE
|
||||
|
||||
/atom/movable/screen/inventory/Click(location, control, params)
|
||||
// At this point in client Click() code we have passed the 1/10 sec check and little else
|
||||
// We don't even know if it's a middle click
|
||||
// if(world.time <= usr.next_move)
|
||||
// return TRUE
|
||||
|
||||
if(usr.incapacitated()) // ignore_stasis = TRUE
|
||||
return TRUE
|
||||
@@ -138,42 +141,23 @@
|
||||
usr.update_inv_hands()
|
||||
return TRUE
|
||||
|
||||
/atom/movable/screen/inventory/MouseEntered()
|
||||
..()
|
||||
/atom/movable/screen/inventory/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
add_overlays()
|
||||
//Apply the outline affect
|
||||
add_stored_outline()
|
||||
|
||||
/atom/movable/screen/inventory/MouseExited()
|
||||
..()
|
||||
cut_overlay(object_overlays)
|
||||
object_overlays.Cut()
|
||||
remove_stored_outline()
|
||||
|
||||
/atom/movable/screen/inventory/proc/add_stored_outline()
|
||||
if(hud?.mymob && slot_id)
|
||||
var/obj/item/inv_item = hud.mymob.get_item_by_slot(slot_id)
|
||||
if(inv_item)
|
||||
if(hud?.mymob.incapacitated() || (slot_id in hud?.mymob.check_obscured_slots()) || !hud?.mymob.canUnEquip(inv_item))
|
||||
inv_item.apply_outline(_size = 3)
|
||||
else
|
||||
inv_item.apply_outline()
|
||||
|
||||
/atom/movable/screen/inventory/proc/remove_stored_outline()
|
||||
if(hud?.mymob && slot_id)
|
||||
var/obj/item/inv_item = hud.mymob.get_item_by_slot(slot_id)
|
||||
if(inv_item)
|
||||
inv_item.remove_outline()
|
||||
cut_overlay(object_overlay)
|
||||
QDEL_NULL(object_overlay)
|
||||
|
||||
/atom/movable/screen/inventory/update_icon_state()
|
||||
if(!icon_empty)
|
||||
icon_empty = icon_state
|
||||
|
||||
if(hud?.mymob && slot_id && icon_full)
|
||||
if(hud.mymob.get_item_by_slot(slot_id))
|
||||
icon_state = icon_full
|
||||
else
|
||||
icon_state = icon_empty
|
||||
if(!hud?.mymob || !slot_id || !icon_full)
|
||||
return ..()
|
||||
icon_state = hud.mymob.get_item_by_slot(slot_id) ? icon_full : icon_empty
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/inventory/proc/add_overlays()
|
||||
var/mob/user = hud?.mymob
|
||||
@@ -189,14 +173,14 @@
|
||||
var/image/item_overlay = image(holding)
|
||||
item_overlay.alpha = 92
|
||||
|
||||
if(!user.can_equip(holding, slot_id, TRUE, TRUE))
|
||||
if(!user.can_equip(holding, slot_id, disable_warning = TRUE, bypass_equip_delay_self = TRUE))
|
||||
item_overlay.color = "#FF0000"
|
||||
else
|
||||
item_overlay.color = "#00ff00"
|
||||
|
||||
cut_overlay(object_overlays)
|
||||
// object_overlay = item_overlay
|
||||
add_overlay(object_overlays)
|
||||
cut_overlay(object_overlay)
|
||||
object_overlay = item_overlay
|
||||
add_overlay(object_overlay)
|
||||
|
||||
/atom/movable/screen/inventory/hand
|
||||
var/mutable_appearance/handcuff_overlay
|
||||
@@ -232,8 +216,6 @@
|
||||
var/mob/user = hud?.mymob
|
||||
if(usr != user)
|
||||
return TRUE
|
||||
// if(world.time <= user.next_move)
|
||||
// return TRUE
|
||||
if(user.incapacitated())
|
||||
return TRUE
|
||||
if (ismecha(user.loc)) // stops inventory actions in a mech
|
||||
@@ -247,12 +229,24 @@
|
||||
user.swap_hand(held_index)
|
||||
return TRUE
|
||||
|
||||
// /atom/movable/screen/close
|
||||
// name = "close"
|
||||
// plane = ABOVE_HUD_PLANE
|
||||
// icon_state = "backpack_close"
|
||||
|
||||
// /atom/movable/screen/close/Initialize(mapload, new_master)
|
||||
// . = ..()
|
||||
// master = new_master
|
||||
|
||||
// /atom/movable/screen/close/Click()
|
||||
// var/datum/component/storage/S = master
|
||||
// S.hide_from(usr)
|
||||
// return TRUE
|
||||
|
||||
/atom/movable/screen/drop
|
||||
name = "drop"
|
||||
icon = 'icons/mob/screen_midnight.dmi'
|
||||
icon_state = "act_drop"
|
||||
layer = HUD_LAYER
|
||||
plane = HUD_PLANE
|
||||
|
||||
/atom/movable/screen/drop/Click()
|
||||
@@ -308,12 +302,12 @@
|
||||
|
||||
if(C.internal)
|
||||
C.internal = null
|
||||
to_chat(C, "<span class='notice'>You are no longer running on internals.</span>")
|
||||
to_chat(C, span_notice("You are no longer running on internals."))
|
||||
icon_state = "internal0"
|
||||
else
|
||||
if(!C.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
if(HAS_TRAIT(C, TRAIT_NO_INTERNALS))
|
||||
to_chat(C, "<span class='warning'>Due to cumbersome equipment or anatomy, you are currently unable to use internals!</span>")
|
||||
to_chat(C, span_warning("Due to cumbersome equipment or anatomy, you are currently unable to use internals!"))
|
||||
return
|
||||
var/obj/item/clothing/check
|
||||
var/internals = FALSE
|
||||
@@ -326,37 +320,37 @@
|
||||
if((check.clothing_flags & ALLOWINTERNALS))
|
||||
internals = TRUE
|
||||
if(!internals)
|
||||
to_chat(C, "<span class='warning'>You are not wearing an internals mask!</span>")
|
||||
to_chat(C, span_warning("You are not wearing an internals mask!"))
|
||||
return
|
||||
|
||||
var/obj/item/I = C.is_holding_item_of_type(/obj/item/tank)
|
||||
if(I)
|
||||
to_chat(C, "<span class='notice'>You are now running on internals from [I] in your [C.get_held_index_name(C.get_held_index_of_item(I))].</span>")
|
||||
to_chat(C, span_notice("You are now running on internals from [I] in your [C.get_held_index_name(C.get_held_index_of_item(I))]."))
|
||||
C.internal = I
|
||||
else if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(istype(H.s_store, /obj/item/tank))
|
||||
to_chat(H, "<span class='notice'>You are now running on internals from [H.s_store] on your [H.wear_suit.name].</span>")
|
||||
to_chat(H, span_notice("You are now running on internals from [H.s_store] on your [H.wear_suit.name]."))
|
||||
H.internal = H.s_store
|
||||
else if(istype(H.belt, /obj/item/tank))
|
||||
to_chat(H, "<span class='notice'>You are now running on internals from [H.belt] on your belt.</span>")
|
||||
to_chat(H, span_notice("You are now running on internals from [H.belt] on your belt."))
|
||||
H.internal = H.belt
|
||||
else if(istype(H.l_store, /obj/item/tank))
|
||||
to_chat(H, "<span class='notice'>You are now running on internals from [H.l_store] in your left pocket.</span>")
|
||||
to_chat(H, span_notice("You are now running on internals from [H.l_store] in your left pocket."))
|
||||
H.internal = H.l_store
|
||||
else if(istype(H.r_store, /obj/item/tank))
|
||||
to_chat(H, "<span class='notice'>You are now running on internals from [H.r_store] in your right pocket.</span>")
|
||||
to_chat(H, span_notice("You are now running on internals from [H.r_store] in your right pocket."))
|
||||
H.internal = H.r_store
|
||||
|
||||
//Separate so CO2 jetpacks are a little less cumbersome.
|
||||
if(!C.internal && istype(C.back, /obj/item/tank))
|
||||
to_chat(C, "<span class='notice'>You are now running on internals from [C.back] on your back.</span>")
|
||||
to_chat(C, span_notice("You are now running on internals from [C.back] on your back."))
|
||||
C.internal = C.back
|
||||
|
||||
if(C.internal)
|
||||
icon_state = "internal1"
|
||||
else
|
||||
to_chat(C, "<span class='warning'>You don't have an oxygen tank!</span>")
|
||||
to_chat(C, span_warning("You don't have an oxygen tank!"))
|
||||
return
|
||||
C.update_action_buttons_icon()
|
||||
|
||||
@@ -378,6 +372,7 @@
|
||||
icon_state = CONFIG_GET(flag/sprint_enabled)? "walking" : "walking_nosprint"
|
||||
if(MOVE_INTENT_RUN)
|
||||
icon_state = CONFIG_GET(flag/sprint_enabled)? "running" : "running_nosprint"
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/mov_intent/proc/toggle(mob/user)
|
||||
if(isobserver(user))
|
||||
@@ -399,12 +394,12 @@
|
||||
icon_state = "pull"
|
||||
else
|
||||
icon_state = "pull0"
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/resist
|
||||
name = "resist"
|
||||
icon = 'icons/mob/screen_midnight.dmi'
|
||||
icon_state = "act_resist"
|
||||
layer = HUD_LAYER
|
||||
plane = HUD_PLANE
|
||||
|
||||
/atom/movable/screen/resist/Click()
|
||||
@@ -416,7 +411,6 @@
|
||||
name = "rest"
|
||||
icon = 'icons/mob/screen_midnight.dmi'
|
||||
icon_state = "act_rest"
|
||||
layer = HUD_LAYER
|
||||
plane = HUD_PLANE
|
||||
|
||||
/atom/movable/screen/rest/Click()
|
||||
@@ -427,11 +421,12 @@
|
||||
/atom/movable/screen/rest/update_icon_state()
|
||||
var/mob/living/user = hud?.mymob
|
||||
if(!istype(user))
|
||||
return
|
||||
return ..()
|
||||
if(!user.resting)
|
||||
icon_state = "act_rest"
|
||||
else
|
||||
icon_state = "act_rest0"
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/throw_catch
|
||||
name = "throw/catch"
|
||||
@@ -455,9 +450,9 @@
|
||||
if(isobserver(usr))
|
||||
return
|
||||
|
||||
var/list/PL = params2list(params)
|
||||
var/icon_x = text2num(PL["icon-x"])
|
||||
var/icon_y = text2num(PL["icon-y"])
|
||||
var/list/modifiers = params2list(params)
|
||||
var/icon_x = text2num(LAZYACCESS(modifiers, "icon-x"))
|
||||
var/icon_y = text2num(LAZYACCESS(modifiers, "icon-y"))
|
||||
var/choice = get_zone_at(icon_x, icon_y)
|
||||
if (!choice)
|
||||
return 1
|
||||
@@ -465,15 +460,16 @@
|
||||
return set_selected_zone(choice, usr)
|
||||
|
||||
/atom/movable/screen/zone_sel/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
MouseMove(location, control, params)
|
||||
|
||||
/atom/movable/screen/zone_sel/MouseMove(location, control, params)
|
||||
if(isobserver(usr))
|
||||
return
|
||||
|
||||
var/list/PL = params2list(params)
|
||||
var/icon_x = text2num(PL["icon-x"])
|
||||
var/icon_y = text2num(PL["icon-y"])
|
||||
var/list/modifiers = params2list(params)
|
||||
var/icon_x = text2num(LAZYACCESS(modifiers, "icon-x"))
|
||||
var/icon_y = text2num(LAZYACCESS(modifiers, "icon-y"))
|
||||
var/choice = get_zone_at(icon_x, icon_y)
|
||||
|
||||
if(hovering == choice)
|
||||
@@ -493,7 +489,6 @@
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
alpha = 128
|
||||
anchored = TRUE
|
||||
layer = ABOVE_HUD_LAYER
|
||||
plane = ABOVE_HUD_PLANE
|
||||
|
||||
/atom/movable/screen/zone_sel/MouseExited(location, control, params)
|
||||
@@ -545,7 +540,7 @@
|
||||
|
||||
if(choice != hud.mymob.zone_selected)
|
||||
hud.mymob.zone_selected = choice
|
||||
update_icon()
|
||||
update_appearance()
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -562,7 +557,6 @@
|
||||
/atom/movable/screen/zone_sel/robot
|
||||
icon = 'icons/mob/screen_cyborg.dmi'
|
||||
|
||||
|
||||
/atom/movable/screen/flash
|
||||
name = "flash"
|
||||
icon_state = "blank"
|
||||
@@ -651,6 +645,11 @@
|
||||
name = "health doll"
|
||||
screen_loc = ui_healthdoll
|
||||
|
||||
/atom/movable/screen/healthdoll/Click()
|
||||
if (iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
C.check_self_for_injuries()
|
||||
|
||||
/atom/movable/screen/healthdoll/living
|
||||
icon_state = "fullhealth0"
|
||||
screen_loc = ui_living_healthdoll
|
||||
@@ -661,6 +660,9 @@
|
||||
icon_state = "mood5"
|
||||
screen_loc = ui_mood
|
||||
|
||||
/atom/movable/screen/mood/attack_tk()
|
||||
return
|
||||
|
||||
/atom/movable/screen/splash
|
||||
icon = 'icons/blank_title.png'
|
||||
icon_state = ""
|
||||
@@ -671,6 +673,8 @@
|
||||
|
||||
/atom/movable/screen/splash/New(client/C, visible, use_previous_title) //TODO: Make this use INITIALIZE_IMMEDIATE, except its not easy
|
||||
. = ..()
|
||||
if(!istype(C))
|
||||
return
|
||||
|
||||
holder = C
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
// Otherwise jump
|
||||
else if(A.loc)
|
||||
forceMove(get_turf(A))
|
||||
update_parallax_contents()
|
||||
|
||||
/mob/dead/observer/ClickOn(var/atom/A, var/params)
|
||||
if(check_click_intercept(params,A))
|
||||
|
||||
@@ -124,9 +124,3 @@ GLOBAL_LIST_INIT(huds, list(
|
||||
|
||||
/mob/dead/new_player/reload_huds()
|
||||
return
|
||||
|
||||
/mob/proc/add_click_catcher()
|
||||
client.screen += client.void
|
||||
|
||||
/mob/dead/new_player/add_click_catcher()
|
||||
return
|
||||
@@ -0,0 +1,74 @@
|
||||
/atom/movable/screen/click_catcher
|
||||
icon = 'icons/screen/clickcatcher.dmi'
|
||||
icon_state = "catcher"
|
||||
appearance_flags = TILE_BOUND | NO_CLIENT_COLOR | RESET_TRANSFORM | RESET_COLOR | RESET_ALPHA
|
||||
plane = CLICKCATCHER_PLANE
|
||||
plane = CLICKCATCHER_PLANE
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
screen_loc = "CENTER"
|
||||
|
||||
/*
|
||||
#define MAX_SAFE_BYOND_ICON_SCALE_TILES (MAX_SAFE_BYOND_ICON_SCALE_PX / world.icon_size)
|
||||
#define MAX_SAFE_BYOND_ICON_SCALE_PX (33 * 32) //Not using world.icon_size on purpose.
|
||||
|
||||
/atom/movable/screen/click_catcher/proc/UpdateFill(view_size_x = 15, view_size_y = 15)
|
||||
var/icon/newicon = icon('icons/mob/screen_gen.dmi', "catcher")
|
||||
var/ox = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_x)
|
||||
var/oy = min(MAX_SAFE_BYOND_ICON_SCALE_TILES, view_size_y)
|
||||
var/px = view_size_x * world.icon_size
|
||||
var/py = view_size_y * world.icon_size
|
||||
var/sx = min(MAX_SAFE_BYOND_ICON_SCALE_PX, px)
|
||||
var/sy = min(MAX_SAFE_BYOND_ICON_SCALE_PX, py)
|
||||
newicon.Scale(sx, sy)
|
||||
icon = newicon
|
||||
screen_loc = "CENTER-[(ox-1)*0.5],CENTER-[(oy-1)*0.5]"
|
||||
var/matrix/M = new
|
||||
M.Scale(px/sx, py/sy)
|
||||
transform = M
|
||||
|
||||
#undef MAX_SAFE_BYOND_ICON_SCALE_TILES
|
||||
#undef MAX_SAFE_BYOND_ICON_SCALE_PX
|
||||
*/
|
||||
|
||||
/atom/movable/screen/click_catcher/proc/UpdateFill(view_size_x, view_size_y)
|
||||
screen_loc = "1,1 to [view_size_x],[view_size_y]"
|
||||
|
||||
/atom/movable/screen/click_catcher/Click(location, control, params)
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["middle"] && iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
C.swap_hand()
|
||||
else
|
||||
var/turf/T = Parse(modifiers["screen-loc"], get_turf(usr.client?.eye || usr), usr.client)
|
||||
params += "&catcher=1"
|
||||
if(T)
|
||||
T.Click(location, control, params)
|
||||
return TRUE
|
||||
|
||||
/atom/movable/screen/click_catcher/proc/Parse(scr_loc, turf/origin, client/C)
|
||||
// screen-loc: Pixel coordinates in screen_loc format ("[tile_x]:[pixel_x],[tile_y]:[pixel_y]")
|
||||
if(!scr_loc)
|
||||
return null
|
||||
var/tX = splittext(scr_loc, ",")
|
||||
var/tY = splittext(tX[2], ":")
|
||||
var/tZ = origin.z
|
||||
tY = tY[1]
|
||||
tX = splittext(tX[1], ":")
|
||||
tX = tX[1]
|
||||
var/list/actual_view = getviewsize(C ? C.view : world.view)
|
||||
tX = clamp(origin.x + text2num(tX) - round(actual_view[1] / 2) - 1, 1, world.maxx)
|
||||
tY = clamp(origin.y + text2num(tY) - round(actual_view[2] / 2) - 1, 1, world.maxy)
|
||||
return locate(tX, tY, tZ)
|
||||
|
||||
/**
|
||||
* Makes a clickcatcher if necessary, and ensures it's fit to our size.
|
||||
*/
|
||||
/client/proc/update_clickcatcher(list/view_override)
|
||||
if(!click_catcher)
|
||||
click_catcher = new
|
||||
screen |= click_catcher
|
||||
if(view_override)
|
||||
click_catcher.UpdateFill(view_override[1], view_override[2])
|
||||
else
|
||||
var/list/view_list = getviewsize(view)
|
||||
click_catcher.UpdateFill(view_list[1], view_list[2])
|
||||
@@ -0,0 +1,234 @@
|
||||
/**
|
||||
* Adds a fullscreen overlay
|
||||
*
|
||||
* @params
|
||||
* - category - string - must exist. will overwrite any other screen in this category. defaults to type.
|
||||
* - type - the typepath of the screen
|
||||
* - severity - severity - different screen objects have differing severities
|
||||
*/
|
||||
/mob/proc/overlay_fullscreen(category, type, severity)
|
||||
ASSERT(type)
|
||||
if(!category)
|
||||
category = type
|
||||
var/atom/movable/screen/fullscreen/screen = fullscreens[category]
|
||||
if (!screen || screen.type != type)
|
||||
// needs to be recreated
|
||||
clear_fullscreen(category, 0)
|
||||
fullscreens[category] = screen = new type
|
||||
screen.SetSeverity(severity)
|
||||
if(client && screen.ShouldShow(src))
|
||||
screen.SetView(client.view)
|
||||
client.screen += screen
|
||||
return screen
|
||||
|
||||
/**
|
||||
* Wipes a fullscreen of a certain category
|
||||
*
|
||||
* Second argument is for animation delay.
|
||||
*/
|
||||
/mob/proc/clear_fullscreen(category, animated = 10)
|
||||
if(!fullscreens)
|
||||
return
|
||||
var/atom/movable/screen/fullscreen/screen = fullscreens[category]
|
||||
fullscreens -= category
|
||||
if(!screen)
|
||||
return
|
||||
if(animated > 0)
|
||||
animate(screen, alpha = 0, time = animated)
|
||||
addtimer(CALLBACK(src, .proc/_remove_fullscreen_direct, screen), animated, TIMER_CLIENT_TIME)
|
||||
else
|
||||
if(client)
|
||||
client.screen -= screen
|
||||
qdel(screen)
|
||||
|
||||
/mob/proc/_remove_fullscreen_direct(atom/movable/screen/fullscreen/screen)
|
||||
if(client)
|
||||
client.screen -= screen
|
||||
qdel(screen)
|
||||
|
||||
/**
|
||||
* Wipes all fullscreens
|
||||
*/
|
||||
/mob/proc/wipe_fullscreens()
|
||||
for(var/category in fullscreens)
|
||||
clear_fullscreen(category)
|
||||
|
||||
/**
|
||||
* Removes fullscreens from client but not the mob
|
||||
*/
|
||||
/mob/proc/hide_fullscreens()
|
||||
if(client)
|
||||
for(var/category in fullscreens)
|
||||
client.screen -= fullscreens[category]
|
||||
|
||||
/**
|
||||
* Ensures all fullscreens are on client.
|
||||
*/
|
||||
/mob/proc/reload_fullscreen()
|
||||
if(client)
|
||||
var/atom/movable/screen/fullscreen/screen
|
||||
for(var/category in fullscreens)
|
||||
screen = fullscreens[category]
|
||||
if(screen.ShouldShow(src))
|
||||
screen.SetView(client.view)
|
||||
client.screen |= screen
|
||||
else
|
||||
client.screen -= screen
|
||||
|
||||
/atom/movable/screen/fullscreen
|
||||
icon = 'icons/screen/fullscreen_15x15.dmi'
|
||||
icon_state = "default"
|
||||
screen_loc = "CENTER-7,CENTER-7"
|
||||
layer = FULLSCREEN_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
/// current view we're adapted to
|
||||
var/view_current
|
||||
/// min severity
|
||||
var/severity_min = 0
|
||||
/// max severity
|
||||
var/severity_max = INFINITY
|
||||
/// current severity
|
||||
var/severity = 0
|
||||
/// show this while dead
|
||||
var/show_when_dead = FALSE
|
||||
|
||||
/atom/movable/screen/fullscreen/proc/SetSeverity(severity)
|
||||
src.severity = clamp(severity, severity_min, severity_max)
|
||||
icon_state = "[initial(icon_state)][severity]"
|
||||
|
||||
/atom/movable/screen/fullscreen/proc/SetView(client_view)
|
||||
view_current = client_view
|
||||
|
||||
/atom/movable/screen/fullscreen/proc/ShouldShow(mob/M)
|
||||
if(!show_when_dead && M.stat == DEAD)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/Destroy()
|
||||
SetSeverity(0)
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled
|
||||
icon = 'icons/screen/fullscreen_15x15.dmi'
|
||||
screen_loc = "CENTER-7,CENTER-7"
|
||||
/// size of sprite in tiles
|
||||
var/size_x = 15
|
||||
/// size of sprite in tiles
|
||||
var/size_y = 15
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled/SetView(client_view)
|
||||
if(view_current != client_view)
|
||||
var/list/actualview = getviewsize(client_view)
|
||||
view_current = client_view
|
||||
transform = matrix(actualview[1] / size_x, 0, 0, 0, actualview[2] / size_y, 0)
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled/brute
|
||||
icon_state = "brutedamageoverlay"
|
||||
layer = UI_DAMAGE_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled/oxy
|
||||
icon_state = "oxydamageoverlay"
|
||||
layer = UI_DAMAGE_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled/crit
|
||||
icon_state = "passage"
|
||||
layer = CRIT_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled/crit/vision
|
||||
icon_state = "oxydamageoverlay"
|
||||
layer = BLIND_LAYER
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled/blind
|
||||
icon_state = "blackimageoverlay"
|
||||
layer = BLIND_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled/curse
|
||||
icon_state = "curse"
|
||||
layer = CURSE_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled/impaired
|
||||
icon_state = "impairedoverlay"
|
||||
|
||||
/atom/movable/screen/fullscreen/scaled/emergency_meeting
|
||||
icon_state = "emergency_meeting"
|
||||
show_when_dead = TRUE
|
||||
layer = CURSE_LAYER
|
||||
plane = SPLASHSCREEN_PLANE
|
||||
|
||||
/atom/movable/screen/fullscreen/tiled/blurry
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "cloudy"
|
||||
|
||||
/atom/movable/screen/fullscreen/tiled/flash
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "flash"
|
||||
|
||||
/atom/movable/screen/fullscreen/tiled/flash/static
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "noise"
|
||||
|
||||
/atom/movable/screen/fullscreen/tiled/high
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "druggy"
|
||||
|
||||
/atom/movable/screen/fullscreen/tiled/color_vision
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "flash"
|
||||
alpha = 80
|
||||
|
||||
/atom/movable/screen/fullscreen/tiled/color_vision/green
|
||||
color = "#00ff00"
|
||||
|
||||
/atom/movable/screen/fullscreen/tiled/color_vision/red
|
||||
color = "#ff0000"
|
||||
|
||||
/atom/movable/screen/fullscreen/tiled/color_vision/blue
|
||||
color = "#0000ff"
|
||||
|
||||
/atom/movable/screen/fullscreen/tiled/cinematic_backdrop
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "flash"
|
||||
plane = SPLASHSCREEN_PLANE
|
||||
layer = SPLASHSCREEN_LAYER - 1
|
||||
color = "#000000"
|
||||
show_when_dead = TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/special/lighting_backdrop
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "flash"
|
||||
transform = matrix(200, 0, 0, 0, 200, 0)
|
||||
plane = LIGHTING_PLANE
|
||||
blend_mode = BLEND_OVERLAY
|
||||
show_when_dead = TRUE
|
||||
|
||||
//Provides darkness to the back of the lighting plane
|
||||
/atom/movable/screen/fullscreen/special/lighting_backdrop/lit
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
layer = BACKGROUND_LAYER+21
|
||||
color = "#000"
|
||||
show_when_dead = TRUE
|
||||
|
||||
//Provides whiteness in case you don't see lights so everything is still visible
|
||||
/atom/movable/screen/fullscreen/special/lighting_backdrop/unlit
|
||||
layer = BACKGROUND_LAYER+20
|
||||
show_when_dead = TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/special/see_through_darkness
|
||||
icon_state = "nightvision"
|
||||
plane = LIGHTING_PLANE
|
||||
layer = LIGHTING_LAYER
|
||||
blend_mode = BLEND_ADD
|
||||
show_when_dead = TRUE
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* initializes screen rendering. call on mob new
|
||||
*/
|
||||
/mob/proc/init_rendering()
|
||||
|
||||
/**
|
||||
* loads screen rendering. call on mob login
|
||||
*/
|
||||
/mob/proc/reload_rendering()
|
||||
if(!client.parallax_holder)
|
||||
client.CreateParallax()
|
||||
else
|
||||
client.parallax_holder.Reset(force = TRUE)
|
||||
client.update_clickcatcher()
|
||||
reload_fullscreen()
|
||||
|
||||
/**
|
||||
* destroys screen rendering. call on mob del
|
||||
*/
|
||||
/mob/proc/dispose_rendering()
|
||||
wipe_fullscreens()
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Holds parallax information.
|
||||
*/
|
||||
/datum/parallax
|
||||
/// List of parallax objects - these are cloned to a parallax holder using Clone on each.
|
||||
var/list/atom/movable/screen/parallax_layer/objects
|
||||
/// Parallax layers
|
||||
var/layers = 0
|
||||
|
||||
/datum/parallax/New(create_objects = TRUE)
|
||||
if(create_objects)
|
||||
objects = CreateObjects()
|
||||
layers = objects.len
|
||||
|
||||
/datum/parallax/Destroy()
|
||||
QDEL_LIST(objects)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Gets a new version of the objects inside - used when applying to a holder.
|
||||
*/
|
||||
/datum/parallax/proc/GetObjects()
|
||||
. = list()
|
||||
for(var/atom/movable/screen/parallax_layer/layer in objects)
|
||||
. += layer.Clone()
|
||||
|
||||
/datum/parallax/proc/CreateObjects()
|
||||
. = objects = list()
|
||||
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
* # Parallax holders
|
||||
*
|
||||
* Holds all the information about a client's parallax
|
||||
*
|
||||
* Not on mob because parallax is area based, not mob based.
|
||||
*
|
||||
* How parallax works:
|
||||
* - Layers - normal layers, scroll with movement to relative position, can scroll
|
||||
* - Absolute - absolute layers, scroll with movement to absolute position, cannot scroll
|
||||
* - Vis - vis_contents-like model - things in this are directly applied and get no processing whatsoever. Things like overmap ships can use this.
|
||||
*/
|
||||
/datum/parallax_holder
|
||||
/// Client that owns us
|
||||
var/client/owner
|
||||
/// The parallax object we're currently rendering
|
||||
var/datum/parallax/parallax
|
||||
/// Eye we were last anchored to - used to detect eye changes
|
||||
var/atom/cached_eye
|
||||
/// force this eye as the "real" eye - useful for secondary maps
|
||||
var/atom/forced_eye
|
||||
/// last turf loc
|
||||
var/turf/last
|
||||
/// last area - for parallax scrolling/loop animations
|
||||
var/area/last_area
|
||||
/// Holder object for vis
|
||||
var/atom/movable/screen/parallax_vis/vis_holder
|
||||
/// are we not on the main map? if so, put map id here
|
||||
var/secondary_map
|
||||
/// all layers
|
||||
var/list/atom/movable/screen/parallax_layer/layers
|
||||
/// vis contents
|
||||
var/list/atom/movable/vis
|
||||
/// currently scrolling?
|
||||
var/scrolling = FALSE
|
||||
/// current scroll speed in DS per scroll
|
||||
var/scroll_speed
|
||||
/// current scroll turn - applied after angle. if angle is 0 (picture moving north) and turn is 90, it would be like if you turned your viewport 90 deg clockwise.
|
||||
var/scroll_turn
|
||||
/// override planemaster we manipulate for turning and other effects
|
||||
var/atom/movable/screen/plane_master/parallax/planemaster_override
|
||||
|
||||
/datum/parallax_holder/New(client/C, secondary_map, forced_eye, planemaster_override)
|
||||
owner = C
|
||||
if(!owner)
|
||||
CRASH("No client")
|
||||
src.secondary_map = secondary_map
|
||||
src.forced_eye = forced_eye
|
||||
src.planemaster_override = planemaster_override
|
||||
Reset()
|
||||
|
||||
/datum/parallax_holder/Destroy()
|
||||
if(owner)
|
||||
if(owner.parallax_holder == src)
|
||||
owner.parallax_holder = null
|
||||
Remove()
|
||||
HardResetAnimations()
|
||||
QDEL_NULL(vis_holder)
|
||||
QDEL_NULL(parallax)
|
||||
layers = null
|
||||
vis = null
|
||||
last = null
|
||||
forced_eye = cached_eye = null
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/datum/parallax_holder/proc/Reset(auto_z_change, force)
|
||||
if(!(cached_eye = Eye()))
|
||||
// if no eye, tear down
|
||||
last = cached_eye = last_area = null
|
||||
SetParallax(null, null, auto_z_change)
|
||||
return
|
||||
// first, check loc
|
||||
var/turf/T = get_turf(cached_eye)
|
||||
if(!T)
|
||||
// if in nullspace, tear down
|
||||
last = cached_eye = last_area = null
|
||||
SetParallax(null, null, auto_z_change)
|
||||
return
|
||||
// set last loc and eye
|
||||
last = T
|
||||
last_area = T.loc
|
||||
// rebuild parallax
|
||||
SetParallax(SSparallax.get_parallax_datum(T.z), null, auto_z_change, force)
|
||||
// hard reset positions to correct positions
|
||||
for(var/atom/movable/screen/parallax_layer/L in layers)
|
||||
L.ResetPosition(T.x, T.y)
|
||||
|
||||
// better updates via client_mobs_in_contents can be created again when important recursive contents is ported!
|
||||
/datum/parallax_holder/proc/Update(full)
|
||||
if(!full && !cached_eye || (get_turf(cached_eye) == last))
|
||||
return
|
||||
if(!owner) // why are we here
|
||||
if(!QDELETED(src))
|
||||
qdel(src)
|
||||
return
|
||||
if(cached_eye != Eye())
|
||||
// eye mismatch, reset
|
||||
Reset()
|
||||
return
|
||||
var/turf/T = get_turf(cached_eye)
|
||||
if(!last || T.z != last.z)
|
||||
// z mismatch, reset
|
||||
Reset()
|
||||
return
|
||||
// get rel offsets
|
||||
var/rel_x = T.x - last.x
|
||||
var/rel_y = T.y - last.y
|
||||
// set last
|
||||
last = T
|
||||
// move
|
||||
for(var/atom/movable/screen/parallax_layer/L in layers)
|
||||
L.RelativePosition(T.x, T.y, rel_x, rel_y)
|
||||
// process scrolling/movedir
|
||||
if(last_area != T.loc)
|
||||
last_area = T.loc
|
||||
UpdateMotion()
|
||||
|
||||
/**
|
||||
* Gets the eye we should be centered on
|
||||
*/
|
||||
/datum/parallax_holder/proc/Eye()
|
||||
return forced_eye || owner?.eye
|
||||
|
||||
/**
|
||||
* Gets the base parallax planemaster for things like turning
|
||||
*/
|
||||
/datum/parallax_holder/proc/GetPlaneMaster()
|
||||
return planemaster_override || (owner && (locate(/atom/movable/screen/plane_master/parallax) in owner?.screen))
|
||||
|
||||
/**
|
||||
* Syncs us to our parallax objects. Does NOT check if we should have those objects, that's Reset()'s job.
|
||||
*
|
||||
* Doesn't move/update positions/screen locs either.
|
||||
*
|
||||
* Also ensures movedirs are correct for the eye's pos.
|
||||
*/
|
||||
/datum/parallax_holder/proc/Sync(auto_z_change, force)
|
||||
layers = list()
|
||||
for(var/atom/movable/screen/parallax_layer/L in parallax.objects)
|
||||
layers += L
|
||||
L.map_id = secondary_map
|
||||
if(!istype(vis_holder))
|
||||
vis_holder = new /atom/movable/screen/parallax_vis
|
||||
var/turf/T = get_turf(cached_eye)
|
||||
vis_holder.vis_contents = vis = T? SSparallax.get_parallax_vis_contents(T.z) : list()
|
||||
UpdateMotion(auto_z_change, force)
|
||||
|
||||
/**
|
||||
* Updates motion if needed
|
||||
*/
|
||||
/datum/parallax_holder/proc/UpdateMotion(auto_z_change, force)
|
||||
var/turf/T = get_turf(cached_eye)
|
||||
if(!T)
|
||||
if(scroll_speed || scroll_turn)
|
||||
HardResetAnimations()
|
||||
return
|
||||
var/list/ret = SSparallax.get_parallax_motion(T.z)
|
||||
if(ret)
|
||||
Animation(ret[1], ret[2], auto_z_change? 0 : ret[3], auto_z_change? 0 : ret[4], force)
|
||||
else
|
||||
var/area/A = T.loc
|
||||
Animation(A.parallax_move_speed, A.parallax_move_angle, auto_z_change? 0 : null, auto_z_change? 0 : null, force)
|
||||
|
||||
/datum/parallax_holder/proc/Apply(client/C = owner)
|
||||
if(QDELETED(C))
|
||||
return
|
||||
. = list()
|
||||
for(var/atom/movable/screen/parallax_layer/L in layers)
|
||||
if(L.parallax_intensity > owner.prefs.parallax)
|
||||
continue
|
||||
if(!L.ShouldSee(C, last))
|
||||
continue
|
||||
L.SetView(C.view, TRUE)
|
||||
. |= L
|
||||
C.screen |= .
|
||||
if(!secondary_map && (owner.prefs.parallax != PARALLAX_DISABLE))
|
||||
var/atom/movable/screen/plane_master/parallax_white/PM = locate() in C.screen
|
||||
if(PM)
|
||||
PM.color = list(
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
1, 1, 1, 1,
|
||||
0, 0, 0, 0
|
||||
)
|
||||
|
||||
/datum/parallax_holder/proc/Remove(client/C = owner)
|
||||
if(QDELETED(C))
|
||||
return
|
||||
C.screen -= layers
|
||||
if(!secondary_map)
|
||||
var/atom/movable/screen/plane_master/parallax_white/PM = locate() in C.screen
|
||||
if(PM)
|
||||
PM.color = initial(PM.color)
|
||||
|
||||
/datum/parallax_holder/proc/SetParallaxType(path)
|
||||
if(!ispath(path, /datum/parallax))
|
||||
CRASH("Invalid path")
|
||||
SetParallax(new path)
|
||||
|
||||
/datum/parallax_holder/proc/SetParallax(datum/parallax/P, delete_old = TRUE, auto_z_change, force)
|
||||
if(P == parallax)
|
||||
return
|
||||
Remove()
|
||||
if(delete_old && istype(parallax) && !QDELETED(parallax))
|
||||
qdel(parallax)
|
||||
HardResetAnimations()
|
||||
parallax = P
|
||||
if(!parallax)
|
||||
return
|
||||
Sync(auto_z_change, force)
|
||||
Apply()
|
||||
|
||||
/**
|
||||
* Runs a modifier to parallax as an animation.
|
||||
*
|
||||
* @params
|
||||
* speed - ds per loop
|
||||
* turn - angle clockwise from north to turn the motion to
|
||||
* windup - ds to spend on windups. 0 for immediate.
|
||||
* turn_speed - ds to spend on turning. 0 for immediate.
|
||||
*/
|
||||
/datum/parallax_holder/proc/Animation(speed = 25, turn = 0, windup = speed, turn_speed = speed, force)
|
||||
// Parallax doesn't currently use this method of rotating.
|
||||
|
||||
// #if !PARALLAX_ROTATION_ANIMATIONS
|
||||
// turn_speed = 0
|
||||
// #endif
|
||||
|
||||
if(speed == 0)
|
||||
StopScrolling(turn = turn, time = windup)
|
||||
return
|
||||
// if(turn != scroll_turn && GetPlaneMaster())
|
||||
// // first handle turn. we turn the planemaster
|
||||
// var/matrix/turn_transform = matrix()
|
||||
// turn_transform.Turn(turn)
|
||||
// scroll_turn = turn
|
||||
// animate(GetPlaneMaster(), transform = turn_transform, time = turn_speed, easing = QUAD_EASING | EASE_IN, flags = ANIMATION_END_NOW | ANIMATION_LINEAR_TRANSFORM)
|
||||
if(scroll_speed == speed && !force)
|
||||
// we're done
|
||||
return
|
||||
// speed diff?
|
||||
scroll_speed = speed
|
||||
scrolling = TRUE
|
||||
// always scroll from north; turn handles everything
|
||||
for(var/atom/movable/screen/parallax_layer/P in layers)
|
||||
if(P.absolute)
|
||||
continue
|
||||
var/matrix/translate_matrix = matrix()
|
||||
translate_matrix.Translate(cos(turn) * 480, sin(turn) * 480)
|
||||
var/matrix/target_matrix = matrix()
|
||||
var/move_speed = speed * P.speed
|
||||
// do the first segment by shifting down one screen
|
||||
P.transform = translate_matrix
|
||||
animate(P, transform = target_matrix, time = move_speed, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_END_NOW)
|
||||
// queue up another incase lag makes QueueLoop not fire on time, this time by shifting up
|
||||
animate(transform = translate_matrix, time = 0)
|
||||
animate(transform = target_matrix, time = move_speed)
|
||||
P.QueueLoop(move_speed, speed * P.speed, translate_matrix, target_matrix)
|
||||
|
||||
/**
|
||||
* Smoothly stops the animation, turning to a certain angle as needed.
|
||||
*/
|
||||
/datum/parallax_holder/proc/StopScrolling(turn = 0, time = 30)
|
||||
// reset turn
|
||||
if(turn != scroll_turn && GetPlaneMaster())
|
||||
var/matrix/turn_transform = matrix()
|
||||
turn_transform.Turn(turn)
|
||||
scroll_turn = turn
|
||||
animate(GetPlaneMaster(), transform = turn_transform, time = time, easing = QUAD_EASING | EASE_OUT, flags = ANIMATION_END_NOW | ANIMATION_LINEAR_TRANSFORM)
|
||||
if(scroll_speed == 0)
|
||||
// we're done
|
||||
scrolling = FALSE
|
||||
scroll_speed = 0
|
||||
return
|
||||
scrolling = FALSE
|
||||
scroll_speed = 0
|
||||
// someone can do the math for "stop after a smooth iteration" later.
|
||||
for(var/atom/movable/screen/parallax_layer/P in layers)
|
||||
if(P.absolute)
|
||||
continue
|
||||
P.CancelAnimation()
|
||||
var/matrix/translate_matrix = matrix()
|
||||
translate_matrix.Translate(cos(turn) * 480, sin(turn) * 480)
|
||||
P.transform = translate_matrix
|
||||
animate(P, transform = matrix(), time = time, easing = QUAD_EASING | EASE_OUT)
|
||||
|
||||
/**
|
||||
* fully resets animation state
|
||||
*/
|
||||
/datum/parallax_holder/proc/HardResetAnimations()
|
||||
// reset vars
|
||||
scroll_turn = 0
|
||||
scroll_speed = 0
|
||||
scrolling = FALSE
|
||||
// reset turn
|
||||
if(GetPlaneMaster())
|
||||
animate(GetPlaneMaster(), transform = matrix(), time = 0, flags = ANIMATION_END_NOW)
|
||||
// reset objects
|
||||
for(var/atom/movable/screen/parallax_layer/P in layers)
|
||||
if(P.absolute)
|
||||
continue
|
||||
P.CancelAnimation()
|
||||
animate(P, transform = matrix(), time = 0, flags = ANIMATION_END_NOW)
|
||||
|
||||
/client/proc/CreateParallax()
|
||||
if(!parallax_holder)
|
||||
parallax_holder = new(src)
|
||||
/atom/movable/screen/parallax_vis
|
||||
screen_loc = "CENTER,CENTER"
|
||||
@@ -0,0 +1,137 @@
|
||||
|
||||
/atom/movable/screen/parallax_layer
|
||||
icon = 'icons/screen/parallax.dmi'
|
||||
blend_mode = BLEND_ADD
|
||||
plane = PLANE_SPACE_PARALLAX
|
||||
screen_loc = "CENTER-7,CENTER-7"
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
appearance_flags = PIXEL_SCALE | KEEP_TOGETHER
|
||||
|
||||
// notice - all parallax layers are 15x15 tiles. They roll over every 240 pixels.
|
||||
/// pixel x/y shift per real x/y
|
||||
var/speed = 1
|
||||
/// current cached offset x
|
||||
var/offset_x = 0
|
||||
/// current cached offset y
|
||||
var/offset_y = 0
|
||||
/// normal centered x
|
||||
var/center_x = 0
|
||||
/// normal centered y
|
||||
var/center_y = 0
|
||||
/// absolute - always determine shift x/y as a function of real x/y instead of allowing for relative scroll.
|
||||
var/absolute = FALSE
|
||||
/// parallax level required to see this
|
||||
var/parallax_intensity = PARALLAX_INSANE
|
||||
/// current view we're adapted to
|
||||
var/view_current
|
||||
/// dynamic self tile - tile to our view size. set this to false for static parallax layers.
|
||||
var/dynamic_self_tile = TRUE
|
||||
/// map id
|
||||
var/map_id
|
||||
/// queued animation timerid
|
||||
var/queued_animation
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/ResetPosition(x, y)
|
||||
// remember that our offsets/directiosn are relative to the player's viewport
|
||||
// this means we need to scroll reverse to them.
|
||||
offset_x = -(center_x + speed * x)
|
||||
offset_y = -(center_y + speed * y)
|
||||
if(!absolute)
|
||||
if(offset_x > 240)
|
||||
offset_x -= 480
|
||||
if(offset_x < -240)
|
||||
offset_x += 480
|
||||
if(offset_y > 240)
|
||||
offset_y -= 480
|
||||
if(offset_y < -240)
|
||||
offset_y += 480
|
||||
screen_loc = "[map_id && "[map_id]:"]CENTER-7:[round(offset_x,1)],CENTER-7:[round(offset_y,1)]"
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/RelativePosition(x, y, rel_x, rel_y)
|
||||
if(absolute)
|
||||
return ResetPosition(x, y)
|
||||
offset_x -= rel_x * speed
|
||||
offset_y -= rel_y * speed
|
||||
if(offset_x > 240)
|
||||
offset_x -= 480
|
||||
if(offset_x < -240)
|
||||
offset_x += 480
|
||||
if(offset_y > 240)
|
||||
offset_y -= 480
|
||||
if(offset_y < -240)
|
||||
offset_y += 480
|
||||
screen_loc = "[map_id && "[map_id]:"]CENTER-7:[round(offset_x,1)],CENTER-7:[round(offset_y,1)]"
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/SetView(client_view = world.view, force_update = FALSE)
|
||||
if(view_current == client_view && !force_update)
|
||||
return
|
||||
view_current = client_view
|
||||
if(!dynamic_self_tile)
|
||||
return
|
||||
var/list/real_view = getviewsize(client_view)
|
||||
var/count_x = CEILING((real_view[1] / 2) / 15, 1) + 1
|
||||
var/count_y = CEILING((real_view[2] / 2) / 15, 1) + 1
|
||||
var/list/new_overlays = GetOverlays()
|
||||
for(var/x in -count_x to count_x)
|
||||
for(var/y in -count_y to count_y)
|
||||
if(!x && !y)
|
||||
continue
|
||||
var/mutable_appearance/clone = new
|
||||
// appearance clone
|
||||
clone.icon = icon
|
||||
clone.icon_state = icon_state
|
||||
clone.overlays = GetOverlays()
|
||||
// do NOT inherit our overlays! parallax layers should never have overlays,
|
||||
// because if it inherited us it'll result in exponentially increasing overlays
|
||||
// due to cut_overlays() above over there being a queue operation and not instant!
|
||||
// clone.overlays = list()
|
||||
// currently instantly using overlays =.
|
||||
// clone.blend_mode = blend_mode
|
||||
// clone.mouse_opacity = mouse_opacity
|
||||
// clone.plane = plane
|
||||
// clone.layer = layer
|
||||
// shift to position
|
||||
clone.transform = matrix(1, 0, x * 480, 0, 1, y * 480)
|
||||
new_overlays += clone
|
||||
overlays = new_overlays
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/ShouldSee(client/C, atom/location)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Return "natural" overlays, as we're goin to do some fuckery to overlays above.
|
||||
*/
|
||||
/atom/movable/screen/parallax_layer/proc/GetOverlays()
|
||||
return list()
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/Clone()
|
||||
var/atom/movable/screen/parallax_layer/layer = new type
|
||||
layer.speed = speed
|
||||
layer.offset_x = offset_x
|
||||
layer.offset_y = offset_y
|
||||
layer.absolute = absolute
|
||||
layer.parallax_intensity = parallax_intensity
|
||||
layer.view_current = view_current
|
||||
layer.appearance = appearance
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/default_x()
|
||||
return center_x
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/default_y()
|
||||
return center_y
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/QueueLoop(delay, speed, matrix/translate_matrix, matrix/target_matrix)
|
||||
if(queued_animation)
|
||||
CancelAnimation()
|
||||
queued_animation = addtimer(CALLBACK(src, .proc/_loop, speed, translate_matrix, target_matrix), delay, TIMER_STOPPABLE)
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/_loop(speed, matrix/translate_matrix = matrix(1, 0, 0, 0, 1, 480), matrix/target_matrix = matrix())
|
||||
transform = translate_matrix
|
||||
animate(src, transform = target_matrix, time = speed, loop = -1)
|
||||
animate(transform = translate_matrix, time = 0)
|
||||
queued_animation = null
|
||||
|
||||
/atom/movable/screen/parallax_layer/proc/CancelAnimation()
|
||||
if(queued_animation)
|
||||
deltimer(queued_animation)
|
||||
queued_animation = null
|
||||
@@ -0,0 +1,66 @@
|
||||
/datum/parallax/space
|
||||
var/static/planet_offset_x = rand(100, 160)
|
||||
var/static/planet_offset_y = rand(100, 160)
|
||||
var/static/random_layer = pickweightAllowZero(list(
|
||||
/atom/movable/screen/parallax_layer/space/random/asteroids = 35,
|
||||
/atom/movable/screen/parallax_layer/space/random/space_gas = 35,
|
||||
null = 30
|
||||
))
|
||||
var/static/random_gas_color = pick(COLOR_TEAL, COLOR_GREEN, COLOR_YELLOW, COLOR_CYAN, COLOR_ORANGE, COLOR_PURPLE)
|
||||
|
||||
/datum/parallax/space/CreateObjects()
|
||||
. = ..()
|
||||
. += new /atom/movable/screen/parallax_layer/space/layer_1
|
||||
. += new /atom/movable/screen/parallax_layer/space/layer_2
|
||||
. += new /atom/movable/screen/parallax_layer/space/layer_3
|
||||
var/atom/movable/screen/parallax_layer/space/planet/P = new
|
||||
P.pixel_x = planet_offset_x
|
||||
P.pixel_y = planet_offset_y
|
||||
. += P
|
||||
if(random_layer)
|
||||
. += new random_layer
|
||||
if(ispath(random_layer, /atom/movable/screen/parallax_layer/space/random/space_gas))
|
||||
var/atom/movable/screen/parallax_layer/space/random/space_gas/SG = locate(random_layer) in objects
|
||||
SG.add_atom_colour(random_gas_color, ADMIN_COLOUR_PRIORITY)
|
||||
|
||||
/atom/movable/screen/parallax_layer/space/layer_1
|
||||
icon_state = "layer1"
|
||||
speed = 0.6
|
||||
layer = 1
|
||||
parallax_intensity = PARALLAX_LOW
|
||||
|
||||
/atom/movable/screen/parallax_layer/space/layer_2
|
||||
icon_state = "layer2"
|
||||
speed = 1
|
||||
layer = 2
|
||||
parallax_intensity = PARALLAX_MED
|
||||
|
||||
/atom/movable/screen/parallax_layer/space/layer_3
|
||||
icon_state = "layer3"
|
||||
speed = 1.4
|
||||
layer = 3
|
||||
parallax_intensity = PARALLAX_HIGH
|
||||
|
||||
/atom/movable/screen/parallax_layer/space/random
|
||||
blend_mode = BLEND_OVERLAY
|
||||
speed = 3
|
||||
layer = 3
|
||||
parallax_intensity = PARALLAX_INSANE
|
||||
|
||||
/atom/movable/screen/parallax_layer/space/random/space_gas
|
||||
icon_state = "space_gas"
|
||||
|
||||
/atom/movable/screen/parallax_layer/space/random/asteroids
|
||||
icon_state = "asteroids"
|
||||
|
||||
/atom/movable/screen/parallax_layer/space/planet
|
||||
icon_state = "planet"
|
||||
blend_mode = BLEND_OVERLAY
|
||||
absolute = TRUE //Status of seperation
|
||||
speed = 3
|
||||
layer = 30
|
||||
dynamic_self_tile = FALSE
|
||||
|
||||
/atom/movable/screen/parallax_layer/space/planet/ShouldSee(client/C, atom/location)
|
||||
var/turf/T = get_turf(location)
|
||||
return ..() && T && is_station_level(T.z)
|
||||
@@ -348,6 +348,8 @@
|
||||
|
||||
/datum/config_entry/flag/dynamic_config_enabled
|
||||
|
||||
/datum/config_entry/flag/station_name_needs_approval
|
||||
|
||||
//ambition end
|
||||
config_entry_value = 5
|
||||
/datum/config_entry/number/max_ambitions // Maximum number of ambitions a mind can store.
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
/datum/config_entry/flag/log_access // log login/logout
|
||||
config_entry_value = TRUE
|
||||
|
||||
/// Config entry which special logging of failed logins under suspicious circumstances.
|
||||
/datum/config_entry/flag/log_suspicious_login
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_say // log client say
|
||||
config_entry_value = TRUE
|
||||
|
||||
|
||||
@@ -116,6 +116,11 @@ SUBSYSTEM_DEF(air)
|
||||
|
||||
/datum/controller/subsystem/air/proc/auxtools_update_reactions()
|
||||
|
||||
/datum/controller/subsystem/air/proc/add_reaction(datum/gas_reaction/r)
|
||||
gas_reactions += r
|
||||
sortTim(gas_reactions, /proc/cmp_gas_reaction)
|
||||
auxtools_update_reactions()
|
||||
|
||||
/proc/reset_all_air()
|
||||
SSair.can_fire = 0
|
||||
message_admins("Air reset begun.")
|
||||
|
||||
@@ -14,6 +14,9 @@ SUBSYSTEM_DEF(atoms)
|
||||
|
||||
var/list/BadInitializeCalls = list()
|
||||
|
||||
/// Atoms that will be deleted once the subsystem is initialized
|
||||
var/list/queued_deletions = list()
|
||||
|
||||
initialized = INITIALIZATION_INSSATOMS
|
||||
|
||||
/datum/controller/subsystem/atoms/Initialize(timeofday)
|
||||
@@ -62,6 +65,12 @@ SUBSYSTEM_DEF(atoms)
|
||||
testing("Late initialized [late_loaders.len] atoms")
|
||||
late_loaders.Cut()
|
||||
|
||||
for (var/queued_deletion in queued_deletions)
|
||||
qdel(queued_deletion)
|
||||
|
||||
testing("[queued_deletions.len] atoms were queued for deletion.")
|
||||
queued_deletions.Cut()
|
||||
|
||||
/// Init this specific atom
|
||||
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
|
||||
var/the_type = A.type
|
||||
@@ -151,6 +160,14 @@ SUBSYSTEM_DEF(atoms)
|
||||
if(fails & BAD_INIT_SLEPT)
|
||||
. += "- Slept during Initialize()\n"
|
||||
|
||||
/// Prepares an atom to be deleted once the atoms SS is initialized.
|
||||
/datum/controller/subsystem/atoms/proc/prepare_deletion(atom/target)
|
||||
if (initialized == INITIALIZATION_INNEW_REGULAR)
|
||||
// Atoms SS has already completed, just kill it now.
|
||||
qdel(target)
|
||||
else
|
||||
queued_deletions += WEAKREF(target)
|
||||
|
||||
/datum/controller/subsystem/atoms/Shutdown()
|
||||
var/initlog = InitLog()
|
||||
if(initlog)
|
||||
|
||||
@@ -1,33 +1,67 @@
|
||||
#define COMMUNICATION_COOLDOWN 300
|
||||
#define COMMUNICATION_COOLDOWN_AI 300
|
||||
#define COMMUNICATION_COOLDOWN (30 SECONDS)
|
||||
#define COMMUNICATION_COOLDOWN_AI (30 SECONDS)
|
||||
#define COMMUNICATION_COOLDOWN_MEETING (5 MINUTES)
|
||||
|
||||
SUBSYSTEM_DEF(communications)
|
||||
name = "Communications"
|
||||
flags = SS_NO_INIT | SS_NO_FIRE
|
||||
|
||||
var/silicon_message_cooldown
|
||||
var/nonsilicon_message_cooldown
|
||||
COOLDOWN_DECLARE(silicon_message_cooldown)
|
||||
COOLDOWN_DECLARE(nonsilicon_message_cooldown)
|
||||
COOLDOWN_DECLARE(emergency_meeting_cooldown)
|
||||
|
||||
/datum/controller/subsystem/communications/proc/can_announce(mob/living/user, is_silicon)
|
||||
if(is_silicon && silicon_message_cooldown > world.time)
|
||||
. = FALSE
|
||||
else if(!is_silicon && nonsilicon_message_cooldown > world.time)
|
||||
. = FALSE
|
||||
if(is_silicon && COOLDOWN_FINISHED(src, silicon_message_cooldown))
|
||||
return TRUE
|
||||
else if(!is_silicon && COOLDOWN_FINISHED(src, nonsilicon_message_cooldown))
|
||||
return TRUE
|
||||
else
|
||||
. = TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/controller/subsystem/communications/proc/make_announcement(mob/living/user, is_silicon, input)
|
||||
if(!can_announce(user, is_silicon))
|
||||
return FALSE
|
||||
if(is_silicon)
|
||||
minor_announce(html_decode(input),"[user.name] Announces:")
|
||||
silicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN_AI
|
||||
COOLDOWN_START(src, silicon_message_cooldown, COMMUNICATION_COOLDOWN_AI)
|
||||
else
|
||||
priority_announce(html_decode(user.treat_message(input)), null, 'sound/misc/announce.ogg', "Captain")
|
||||
nonsilicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN
|
||||
priority_announce(html_decode(user.treat_message(input)), null, 'sound/misc/announce.ogg', "Captain", has_important_message = TRUE)
|
||||
COOLDOWN_START(src, nonsilicon_message_cooldown, COMMUNICATION_COOLDOWN)
|
||||
user.log_talk(input, LOG_SAY, tag="priority announcement")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has made a priority announcement.")
|
||||
|
||||
/**
|
||||
* Check if a mob can call an emergency meeting
|
||||
*
|
||||
* Should only really happen during april fools.
|
||||
* Checks to see that it's been at least 5 minutes since the last emergency meeting call.
|
||||
* Arguments:
|
||||
* * user - Mob who called the meeting
|
||||
*/
|
||||
/datum/controller/subsystem/communications/proc/can_make_emergency_meeting(mob/living/user)
|
||||
if(!(SSevents.holidays && SSevents.holidays[APRIL_FOOLS]))
|
||||
return FALSE
|
||||
else if(COOLDOWN_FINISHED(src, emergency_meeting_cooldown))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Call an emergency meeting
|
||||
*
|
||||
* Communications subsystem wrapper for the call_emergency_meeting world proc.
|
||||
* Checks to make sure the proc can be called, and handles
|
||||
* relevant logging and timing. See that proc definition for more detail.
|
||||
* Arguments:
|
||||
* * user - Mob who called the meeting
|
||||
*/
|
||||
/datum/controller/subsystem/communications/proc/emergency_meeting(mob/living/user)
|
||||
if(!can_make_emergency_meeting(user))
|
||||
return FALSE
|
||||
call_emergency_meeting(user, get_area(user))
|
||||
COOLDOWN_START(src, emergency_meeting_cooldown, COMMUNICATION_COOLDOWN_MEETING)
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has called an emergency meeting.")
|
||||
|
||||
/datum/controller/subsystem/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE)
|
||||
for(var/obj/machinery/computer/communications/C in GLOB.machines)
|
||||
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
|
||||
@@ -40,7 +74,7 @@ SUBSYSTEM_DEF(communications)
|
||||
var/obj/item/paper/P = new /obj/item/paper(C.loc)
|
||||
P.name = "paper - '[sending.title]'"
|
||||
P.info = sending.content
|
||||
P.update_icon()
|
||||
P.update_appearance()
|
||||
|
||||
#undef COMMUNICATION_COOLDOWN
|
||||
#undef COMMUNICATION_COOLDOWN_AI
|
||||
|
||||
@@ -5,21 +5,6 @@ SUBSYSTEM_DEF(parallax)
|
||||
priority = FIRE_PRIORITY_PARALLAX
|
||||
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
|
||||
var/list/currentrun
|
||||
var/planet_x_offset = 128
|
||||
var/planet_y_offset = 128
|
||||
var/random_layer
|
||||
var/random_parallax_color
|
||||
|
||||
|
||||
//These are cached per client so needs to be done asap so people joining at roundstart do not miss these.
|
||||
/datum/controller/subsystem/parallax/PreInit()
|
||||
. = ..()
|
||||
if(prob(70)) //70% chance to pick a special extra layer
|
||||
random_layer = pick(/atom/movable/screen/parallax_layer/random/space_gas, /atom/movable/screen/parallax_layer/random/asteroids)
|
||||
random_parallax_color = pick(COLOR_TEAL, COLOR_GREEN, COLOR_YELLOW, COLOR_CYAN, COLOR_ORANGE, COLOR_PURPLE)//Special color for random_layer1. Has to be done here so everyone sees the same color. [COLOR_SILVER]
|
||||
planet_y_offset = rand(100, 160)
|
||||
planet_x_offset = rand(100, 160)
|
||||
|
||||
|
||||
/datum/controller/subsystem/parallax/fire(resumed = FALSE)
|
||||
if (!resumed)
|
||||
@@ -28,28 +13,82 @@ SUBSYSTEM_DEF(parallax)
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
|
||||
while(length(currentrun))
|
||||
var/client/processing_client = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if (QDELETED(processing_client) || !processing_client.eye)
|
||||
if(times_fired % 5) // lazy tick
|
||||
while(length(currentrun))
|
||||
var/client/processing_client = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if (QDELETED(processing_client) || !processing_client.eye)
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
processing_client.parallax_holder?.Update()
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
|
||||
var/atom/movable/movable_eye = processing_client.eye
|
||||
if(!istype(movable_eye))
|
||||
continue
|
||||
|
||||
for (movable_eye; isloc(movable_eye.loc) && !isturf(movable_eye.loc); movable_eye = movable_eye.loc);
|
||||
|
||||
if(movable_eye == processing_client.movingmob)
|
||||
else // full tick
|
||||
while(length(currentrun))
|
||||
var/client/processing_client = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if (QDELETED(processing_client) || !processing_client.eye)
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
processing_client.parallax_holder?.Update(TRUE)
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
if(!isnull(processing_client.movingmob))
|
||||
LAZYREMOVE(processing_client.movingmob.client_mobs_in_contents, processing_client.mob)
|
||||
LAZYADD(movable_eye.client_mobs_in_contents, processing_client.mob)
|
||||
processing_client.movingmob = movable_eye
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
currentrun = null
|
||||
|
||||
/**
|
||||
* Gets parallax type for zlevel.
|
||||
*/
|
||||
/datum/controller/subsystem/parallax/proc/get_parallax_type(z)
|
||||
return /datum/parallax/space
|
||||
|
||||
/**
|
||||
* Gets parallax for zlevel.
|
||||
*/
|
||||
/datum/controller/subsystem/parallax/proc/get_parallax_datum(z)
|
||||
var/datum_type = get_parallax_type(z)
|
||||
return new datum_type
|
||||
|
||||
/**
|
||||
* Gets parallax added vis contents for zlevel
|
||||
*/
|
||||
/datum/controller/subsystem/parallax/proc/get_parallax_vis_contents(z)
|
||||
return list()
|
||||
|
||||
/**
|
||||
* Gets parallax motion for a zlevel
|
||||
*
|
||||
* Returns null or list(speed, dir deg clockwise from north, windup, turnrate)
|
||||
* THE RETURNED LIST MUST BE A 4-TUPLE, OR PARALLAX WILL CRASH.
|
||||
* DO NOT SCREW WITH THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
|
||||
*
|
||||
* This will override area motion
|
||||
*/
|
||||
/datum/controller/subsystem/parallax/proc/get_parallax_motion(z)
|
||||
return null
|
||||
|
||||
/**
|
||||
* updates all parallax for clients on a z
|
||||
*/
|
||||
/datum/controller/subsystem/parallax/proc/update_clients_on_z(z)
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(C.mob.z == z)
|
||||
C.parallax_holder?.Update()
|
||||
|
||||
/**
|
||||
* resets all parallax for clients on a z
|
||||
*/
|
||||
/datum/controller/subsystem/parallax/proc/reset_clients_on_z(z)
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(C.mob.z == z)
|
||||
C.parallax_holder?.Reset()
|
||||
|
||||
/**
|
||||
* updates motion of all clients on z
|
||||
*/
|
||||
/datum/controller/subsystem/parallax/proc/update_z_motion(z)
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(C.mob.z == z)
|
||||
C.parallax_holder?.UpdateMotion()
|
||||
|
||||
@@ -17,7 +17,6 @@ SUBSYSTEM_DEF(processing)
|
||||
/datum/controller/subsystem/processing/fire(resumed = FALSE)
|
||||
if (!resumed)
|
||||
currentrun = processing.Copy()
|
||||
var/delta_time = (flags & SS_TICKER)? (wait * world.tick_lag * 0.1) : (wait * 0.1)
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/current_run = currentrun
|
||||
|
||||
@@ -26,7 +25,7 @@ SUBSYSTEM_DEF(processing)
|
||||
current_run.len--
|
||||
if(QDELETED(thing))
|
||||
processing -= thing
|
||||
else if(thing.process(delta_time) == PROCESS_KILL)
|
||||
else if(thing.process(wait * 0.1) == PROCESS_KILL)
|
||||
// fully stop so that a future START_PROCESSING will work
|
||||
STOP_PROCESSING(src, thing)
|
||||
if (MC_TICK_CHECK)
|
||||
@@ -47,5 +46,5 @@ SUBSYSTEM_DEF(processing)
|
||||
* If you override this do not call parent, as it will return PROCESS_KILL. This is done to prevent objects that dont override process() from staying in the processing list
|
||||
*/
|
||||
/datum/proc/process(delta_time)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
set waitfor = FALSE
|
||||
return PROCESS_KILL
|
||||
|
||||
@@ -48,6 +48,13 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
|
||||
cli.prefs.save_character()
|
||||
if (!silent && LAZYLEN(cut))
|
||||
to_chat(to_chat_target || user, "<span class='boldwarning'>Some quirks have been cut from your character because of these quirks conflicting with your job assignment: [english_list(cut)].</span>")
|
||||
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(istype(H) && H.dna?.species)
|
||||
var/datum/species/S = H.dna.species
|
||||
if(S.remove_blacklisted_quirks(H))
|
||||
to_chat(to_chat_target || user, "<span class='boldwarning'>Some quirks have been cut from your character due to them conflicting with your species: [english_list(S.removed_quirks)]</span>")
|
||||
|
||||
|
||||
/datum/controller/subsystem/processing/quirks/proc/quirk_path_by_name(name)
|
||||
return quirks[name]
|
||||
|
||||
@@ -513,7 +513,9 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(!midpoint)
|
||||
return FALSE
|
||||
var/area/shuttle/transit/A = new()
|
||||
A.parallax_movedir = travel_dir
|
||||
A.parallax_moving = TRUE
|
||||
A.parallax_move_angle = dir2angle(travel_dir)
|
||||
A.parallax_move_speed = M.parallax_speed
|
||||
A.contents = proposal.reserved_turfs
|
||||
var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint)
|
||||
new_transit_dock.reserved_area = proposal
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
PROCESSING_SUBSYSTEM_DEF(sound_loops)
|
||||
name = "Sound Loops"
|
||||
priority = FIRE_PRIORITY_SOUND_LOOPS
|
||||
@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(sounds)
|
||||
name = "Sounds"
|
||||
flags = SS_NO_FIRE
|
||||
init_order = INIT_ORDER_SOUNDS
|
||||
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
|
||||
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
|
||||
/// Amount of channels to reserve for random usage rather than reservations being allowed to reserve all channels. Also a nice safeguard for when someone screws up.
|
||||
var/static/random_channels_min = 50
|
||||
|
||||
@@ -42,7 +42,7 @@ SUBSYSTEM_DEF(sounds)
|
||||
var/text_channel = num2text(channel)
|
||||
var/using = using_channels[text_channel]
|
||||
using_channels -= text_channel
|
||||
if(using != TRUE) // datum channel
|
||||
if(using != TRUE) // datum channel
|
||||
using_channels_by_datum[using] -= channel
|
||||
if(!length(using_channels_by_datum[using]))
|
||||
using_channels_by_datum -= using
|
||||
@@ -65,7 +65,7 @@ SUBSYSTEM_DEF(sounds)
|
||||
/// NO AUTOMATIC CLEANUP - If you use this, you better manually free it later! Returns an integer for channel.
|
||||
/datum/controller/subsystem/sounds/proc/reserve_sound_channel_datumless()
|
||||
. = reserve_channel()
|
||||
if(!.) //oh no..
|
||||
if(!.) //oh no..
|
||||
return FALSE
|
||||
var/text_channel = num2text(.)
|
||||
using_channels[text_channel] = DATUMLESS
|
||||
@@ -74,7 +74,7 @@ SUBSYSTEM_DEF(sounds)
|
||||
|
||||
/// Reserves a channel for a datum. Automatic cleanup only when the datum is deleted. Returns an integer for channel.
|
||||
/datum/controller/subsystem/sounds/proc/reserve_sound_channel(datum/D)
|
||||
if(!D) //i don't like typechecks but someone will fuck it up
|
||||
if(!D) //i don't like typechecks but someone will fuck it up
|
||||
CRASH("Attempted to reserve sound channel without datum using the managed proc.")
|
||||
.= reserve_channel()
|
||||
if(!.)
|
||||
@@ -89,7 +89,7 @@ SUBSYSTEM_DEF(sounds)
|
||||
*/
|
||||
/datum/controller/subsystem/sounds/proc/reserve_channel()
|
||||
PRIVATE_PROC(TRUE)
|
||||
if(channel_reserve_high <= random_channels_min) // out of channels
|
||||
if(channel_reserve_high <= random_channels_min) // out of channels
|
||||
return
|
||||
var/channel = channel_list[channel_reserve_high]
|
||||
reserved_channels[num2text(channel)] = channel_reserve_high--
|
||||
@@ -112,7 +112,7 @@ SUBSYSTEM_DEF(sounds)
|
||||
// now, an existing reserved channel will likely (exception: unreserving last reserved channel) be at index
|
||||
// get it, and update position.
|
||||
var/text_reserved = num2text(channel_list[index])
|
||||
if(!reserved_channels[text_reserved]) //if it isn't already reserved make sure we don't accidently mistakenly put it on reserved list!
|
||||
if(!reserved_channels[text_reserved]) //if it isn't already reserved make sure we don't accidently mistakenly put it on reserved list!
|
||||
return
|
||||
reserved_channels[text_reserved] = index
|
||||
|
||||
|
||||
@@ -603,8 +603,10 @@ SUBSYSTEM_DEF(ticker)
|
||||
news_message = "The burst of energy released near [station_name()] has been confirmed as merely a test of a new weapon. However, due to an unexpected mechanical error, their communications system has been knocked offline."
|
||||
if(SHUTTLE_HIJACK)
|
||||
news_message = "During routine evacuation procedures, the emergency shuttle of [station_name()] had its navigation protocols corrupted and went off course, but was recovered shortly after."
|
||||
if(GANG_VICTORY)
|
||||
news_message = "Company officials reaffirmed that sudden deployments of special forces are not in any way connected to rumors of [station_name()] being covered in graffiti."
|
||||
if(GANG_OPERATING)
|
||||
news_message = "The company would like to state that any rumors of criminal organizing on board stations such as [station_name()] are falsehoods, and not to be emulated."
|
||||
if(GANG_DESTROYED)
|
||||
news_message = "The crew of [station_name()] would like to thank the Spinward Stellar Coalition Police Department for quickly resolving a minor terror threat to the station."
|
||||
|
||||
if(SSblackbox.first_death)
|
||||
var/list/ded = SSblackbox.first_death
|
||||
|
||||
@@ -224,6 +224,7 @@
|
||||
else
|
||||
to_chat(owner, "<span class='userdanger'>You feel your heart lurching in your chest...</span>")
|
||||
owner.adjustOxyLoss(8)
|
||||
else
|
||||
|
||||
/datum/brain_trauma/severe/discoordination
|
||||
name = "Discoordination"
|
||||
|
||||
+62
-35
@@ -4,7 +4,7 @@
|
||||
var/window_id // window_id is used as the window name for browse and onclose
|
||||
var/width = 0
|
||||
var/height = 0
|
||||
var/atom/ref = null
|
||||
var/datum/weakref/ref = null
|
||||
var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id
|
||||
var/stylesheets[0]
|
||||
var/scripts[0]
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
|
||||
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null)
|
||||
|
||||
user = nuser
|
||||
RegisterSignal(user, COMSIG_PARENT_QDELETING, .proc/user_deleted)
|
||||
window_id = nwindow_id
|
||||
if (ntitle)
|
||||
title = format_text(ntitle)
|
||||
@@ -26,7 +26,11 @@
|
||||
if (nheight)
|
||||
height = nheight
|
||||
if (nref)
|
||||
ref = nref
|
||||
ref = WEAKREF(nref)
|
||||
|
||||
/datum/browser/proc/user_deleted(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
user = null
|
||||
|
||||
/datum/browser/proc/add_head_content(nhead_content)
|
||||
head_content = nhead_content
|
||||
@@ -35,7 +39,7 @@
|
||||
window_options = nwindow_options
|
||||
|
||||
/datum/browser/proc/add_stylesheet(name, file)
|
||||
if(istype(name, /datum/asset/spritesheet))
|
||||
if (istype(name, /datum/asset/spritesheet))
|
||||
var/datum/asset/spritesheet/sheet = name
|
||||
stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]"
|
||||
else
|
||||
@@ -94,27 +98,32 @@
|
||||
"}
|
||||
|
||||
/datum/browser/proc/open(use_onclose = TRUE)
|
||||
if(isnull(window_id)) //null check because this can potentially nuke goonchat
|
||||
if(isnull(window_id)) //null check because this can potentially nuke goonchat
|
||||
WARNING("Browser [title] tried to open with a null ID")
|
||||
to_chat(user, "<span class='userdanger'>The [title] browser you tried to open failed a sanity check! Please report this on github!</span>")
|
||||
to_chat(user, span_userdanger("The [title] browser you tried to open failed a sanity check! Please report this on github!"))
|
||||
return
|
||||
var/window_size = ""
|
||||
if(width && height)
|
||||
if (width && height)
|
||||
window_size = "size=[width]x[height];"
|
||||
common_asset.send(user)
|
||||
if(stylesheets.len)
|
||||
if (stylesheets.len)
|
||||
SSassets.transport.send_assets(user, stylesheets)
|
||||
if(scripts.len)
|
||||
if (scripts.len)
|
||||
SSassets.transport.send_assets(user, scripts)
|
||||
user << browse(get_content(), "window=[window_id];[window_size][window_options]")
|
||||
if(use_onclose)
|
||||
if (use_onclose)
|
||||
setup_onclose()
|
||||
|
||||
/datum/browser/proc/setup_onclose()
|
||||
set waitfor = 0 //winexists sleeps, so we don't need to.
|
||||
for (var/i in 1 to 10)
|
||||
if (user && winexists(user, window_id))
|
||||
onclose(user, window_id, ref)
|
||||
if (user?.client && winexists(user, window_id))
|
||||
var/atom/send_ref
|
||||
if(ref)
|
||||
send_ref = ref.resolve()
|
||||
if(!send_ref)
|
||||
ref = null
|
||||
onclose(user, window_id, send_ref)
|
||||
break
|
||||
|
||||
/datum/browser/proc/close()
|
||||
@@ -153,11 +162,35 @@
|
||||
opentime = 0
|
||||
close()
|
||||
|
||||
//designed as a drop in replacement for alert(); functions the same. (outside of needing User specified)
|
||||
/proc/tgalert(mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000)
|
||||
/**
|
||||
* **DEPRECATED: USE tgui_alert(...) INSTEAD**
|
||||
*
|
||||
* Designed as a drop in replacement for alert(); functions the same. (outside of needing User specified)
|
||||
* Arguments:
|
||||
* * User - The user to show the alert to.
|
||||
* * Message - The textual body of the alert.
|
||||
* * Title - The title of the alert's window.
|
||||
* * Button1 - The first button option.
|
||||
* * Button2 - The second button option.
|
||||
* * Button3 - The third button option.
|
||||
* * StealFocus - Boolean operator controlling if the alert will steal the user's window focus.
|
||||
* * Timeout - The timeout of the window, after which no responses will be valid.
|
||||
*/
|
||||
/proc/tgalert(mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = TRUE, Timeout = 6000)
|
||||
if (!User)
|
||||
User = usr
|
||||
switch(askuser(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout))
|
||||
if (!istype(User))
|
||||
if (istype(User, /client))
|
||||
var/client/client = User
|
||||
User = client.mob
|
||||
else
|
||||
return
|
||||
|
||||
// Get user's response using a modal
|
||||
var/datum/browser/modal/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout)
|
||||
A.open()
|
||||
A.wait()
|
||||
switch(A.selectedbutton)
|
||||
if (1)
|
||||
return Button1
|
||||
if (2)
|
||||
@@ -197,8 +230,8 @@
|
||||
.=..()
|
||||
opentime = 0
|
||||
|
||||
/datum/browser/modal/open(use_onclose = 1)
|
||||
set waitfor = 0
|
||||
/datum/browser/modal/open(use_onclose)
|
||||
set waitfor = FALSE
|
||||
opentime = world.time
|
||||
|
||||
if (stealfocus)
|
||||
@@ -277,7 +310,7 @@
|
||||
opentime = 0
|
||||
close()
|
||||
|
||||
/proc/presentpicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor)
|
||||
/proc/presentpicker(mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor)
|
||||
if (!istype(User))
|
||||
if (istype(User, /client/))
|
||||
var/client/C = User
|
||||
@@ -290,7 +323,7 @@
|
||||
if (A.selectedbutton)
|
||||
return list("button" = A.selectedbutton, "values" = A.valueslist)
|
||||
|
||||
/proc/input_bitfield(var/mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null)
|
||||
/proc/input_bitfield(mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null)
|
||||
if (!User || !(bitfield in GLOB.bitfields))
|
||||
return
|
||||
var/list/pickerlist = list()
|
||||
@@ -401,7 +434,7 @@
|
||||
opentime = 0
|
||||
close()
|
||||
|
||||
/proc/presentpreflikepicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/settings, width, height, slidecolor)
|
||||
/proc/presentpreflikepicker(mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/settings, width, height, slidecolor)
|
||||
if (!istype(User))
|
||||
if (istype(User, /client/))
|
||||
var/client/C = User
|
||||
@@ -414,12 +447,6 @@
|
||||
if (A.selectedbutton)
|
||||
return list("button" = A.selectedbutton, "settings" = A.settings)
|
||||
|
||||
// This will allow you to show an icon in the browse window
|
||||
// This is added to mob so that it can be used without a reference to the browser object
|
||||
// There is probably a better place for this...
|
||||
/mob/proc/browse_rsc_icon(icon, icon_state, dir = -1)
|
||||
|
||||
|
||||
// Registers the on-close verb for a browse window (client/verb/.windowclose)
|
||||
// this will be called when the close-button of a window is pressed.
|
||||
//
|
||||
@@ -427,8 +454,8 @@
|
||||
// e.g. canisters, timers, etc.
|
||||
//
|
||||
// windowid should be the specified window name
|
||||
// e.g. code is : user << browse(text, "window=fred")
|
||||
// then use : onclose(user, "fred")
|
||||
// e.g. code is : user << browse(text, "window=fred")
|
||||
// then use : onclose(user, "fred")
|
||||
//
|
||||
// Optionally, specify the "ref" parameter as the controlled atom (usually src)
|
||||
// to pass a "close=1" parameter to the atom's Topic() proc for special handling.
|
||||
@@ -451,18 +478,18 @@
|
||||
// otherwise, just reset the client mob's machine var.
|
||||
//
|
||||
/client/verb/windowclose(atomref as text)
|
||||
set hidden = TRUE // hide this verb from the user's panel
|
||||
set name = ".windowclose" // no autocomplete on cmd line
|
||||
set hidden = TRUE // hide this verb from the user's panel
|
||||
set name = ".windowclose" // no autocomplete on cmd line
|
||||
|
||||
if(atomref!="null") // if passed a real atomref
|
||||
var/hsrc = locate(atomref) // find the reffed atom
|
||||
if(atomref!="null") // if passed a real atomref
|
||||
var/hsrc = locate(atomref) // find the reffed atom
|
||||
var/href = "close=1"
|
||||
if(hsrc)
|
||||
usr = src.mob
|
||||
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
|
||||
return // Topic() proc via client.Topic()
|
||||
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
|
||||
return // Topic() proc via client.Topic()
|
||||
|
||||
// no atomref specified (or not found)
|
||||
// so just reset the user mob's machine var
|
||||
if(src && src.mob)
|
||||
if(src?.mob)
|
||||
src.mob.unset_machine()
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/datum/changelog
|
||||
var/static/list/changelog_items = list()
|
||||
|
||||
/datum/changelog/ui_state()
|
||||
return GLOB.always_state
|
||||
|
||||
/datum/changelog/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if (!ui)
|
||||
ui = new(user, src, "Changelog")
|
||||
ui.open()
|
||||
|
||||
/datum/changelog/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(action == "get_month")
|
||||
var/datum/asset/changelog_item/changelog_item = changelog_items[params["date"]]
|
||||
if (!changelog_item)
|
||||
changelog_item = new /datum/asset/changelog_item(params["date"])
|
||||
changelog_items[params["date"]] = changelog_item
|
||||
return ui.send_asset(changelog_item)
|
||||
|
||||
/datum/changelog/ui_static_data()
|
||||
var/list/data = list( "dates" = list() )
|
||||
var/regex/ymlRegex = regex(@"\.yml", "g")
|
||||
|
||||
for(var/archive_file in flist("[global.config.directory]/../html/changelogs/archive/"))
|
||||
var/archive_date = ymlRegex.Replace(archive_file, "")
|
||||
data["dates"] = list(archive_date) + data["dates"]
|
||||
|
||||
return data
|
||||
@@ -18,8 +18,6 @@
|
||||
#define CHAT_LAYER_Z_STEP 0.0001
|
||||
/// The number of z-layer 'slices' usable by the chat message layering
|
||||
#define CHAT_LAYER_MAX_Z (CHAT_LAYER_MAX - CHAT_LAYER) / CHAT_LAYER_Z_STEP
|
||||
/// Macro from Lummox used to get height from a MeasureText proc
|
||||
#define WXH_TO_HEIGHT(x) text2num(copytext(x, findtextEx(x, "x") + 1))
|
||||
|
||||
/**
|
||||
* # Chat Message Overlay
|
||||
@@ -125,7 +123,7 @@
|
||||
|
||||
// Append radio icon if from a virtual speaker
|
||||
if (extra_classes.Find("virtual-speaker"))
|
||||
var/image/r_icon = image('icons/UI_Icons/chat/chat_icons.dmi', icon_state = "radio")
|
||||
var/image/r_icon = image('icons/ui_icons/chat/chat_icons.dmi', icon_state = "radio")
|
||||
text = "\icon[r_icon] " + text
|
||||
|
||||
// We dim italicized text to make it more distinguishable from regular text
|
||||
@@ -165,7 +163,7 @@
|
||||
message.maptext_width = CHAT_MESSAGE_WIDTH
|
||||
message.maptext_height = mheight
|
||||
message.maptext_x = (CHAT_MESSAGE_WIDTH - owner.bound_width) * -0.5
|
||||
message.maptext = complete_text
|
||||
message.maptext = MAPTEXT(complete_text)
|
||||
|
||||
// View the message
|
||||
LAZYADDASSOC(owned_by.seen_messages, message_loc, src)
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
if(!C)
|
||||
return
|
||||
watching += C
|
||||
M.overlay_fullscreen("cinematic",/atom/movable/screen/fullscreen/cinematic_backdrop)
|
||||
M.overlay_fullscreen("cinematic",/atom/movable/screen/fullscreen/tiled/cinematic_backdrop)
|
||||
C.screen += screen
|
||||
|
||||
//Sound helper
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
///Allows you to set a theme for a set of areas without tying them to looping sounds explicitly
|
||||
/datum/component/area_sound_manager
|
||||
///area -> looping sound type
|
||||
var/list/area_to_looping_type = list()
|
||||
///Current sound loop
|
||||
var/datum/looping_sound/our_loop
|
||||
///A list of "acceptable" z levels to be on. If you leave this, we're gonna delete ourselves
|
||||
var/list/accepted_zs
|
||||
///The timer id of our current start delay, if it exists
|
||||
var/timerid
|
||||
|
||||
/datum/component/area_sound_manager/Initialize(area_loop_pairs, change_on, remove_on, acceptable_zs)
|
||||
if(!ismovable(parent))
|
||||
return
|
||||
area_to_looping_type = area_loop_pairs
|
||||
accepted_zs = acceptable_zs
|
||||
change_the_track()
|
||||
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/react_to_move)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_Z_CHANGED, .proc/react_to_z_move)
|
||||
RegisterSignal(parent, change_on, .proc/handle_change)
|
||||
RegisterSignal(parent, remove_on, .proc/handle_removal)
|
||||
|
||||
/datum/component/area_sound_manager/Destroy(force, silent)
|
||||
QDEL_NULL(our_loop)
|
||||
. = ..()
|
||||
|
||||
/datum/component/area_sound_manager/proc/react_to_move(datum/source, atom/oldloc, dir, forced)
|
||||
SIGNAL_HANDLER
|
||||
var/list/loop_lookup = area_to_looping_type
|
||||
if(loop_lookup[get_area(oldloc)] == loop_lookup[get_area(parent)])
|
||||
return
|
||||
change_the_track(TRUE)
|
||||
|
||||
/datum/component/area_sound_manager/proc/react_to_z_move(datum/source, old_z, new_z)
|
||||
SIGNAL_HANDLER
|
||||
if(!length(accepted_zs) || (new_z in accepted_zs))
|
||||
return
|
||||
qdel(src)
|
||||
|
||||
/datum/component/area_sound_manager/proc/handle_removal(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
qdel(src)
|
||||
|
||||
/datum/component/area_sound_manager/proc/handle_change(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
change_the_track()
|
||||
|
||||
/datum/component/area_sound_manager/proc/change_the_track(skip_start = FALSE)
|
||||
var/time_remaining = 0
|
||||
|
||||
if(our_loop)
|
||||
var/our_id = our_loop.timerid || timerid
|
||||
if(our_id)
|
||||
time_remaining = timeleft(our_id, SSsound_loops) || 0
|
||||
//Time left will sometimes return negative values, just ignore them and start a new sound loop now
|
||||
time_remaining = max(time_remaining, 0)
|
||||
QDEL_NULL(our_loop)
|
||||
|
||||
var/area/our_area = get_area(parent)
|
||||
var/new_loop_type = area_to_looping_type[our_area]
|
||||
if(!new_loop_type)
|
||||
return
|
||||
|
||||
our_loop = new new_loop_type(parent, FALSE, TRUE, skip_start)
|
||||
|
||||
//If we're still playing, wait a bit before changing the sound so we don't double up
|
||||
if(time_remaining)
|
||||
timerid = addtimer(CALLBACK(src, .proc/start_looping_sound), time_remaining, TIMER_UNIQUE | TIMER_CLIENT_TIME | TIMER_STOPPABLE | TIMER_NO_HASH_WAIT | TIMER_DELETE_ME, SSsound_loops)
|
||||
return
|
||||
timerid = null
|
||||
our_loop.start()
|
||||
|
||||
/datum/component/area_sound_manager/proc/start_looping_sound()
|
||||
timerid = null
|
||||
if(our_loop)
|
||||
our_loop.start()
|
||||
@@ -66,7 +66,7 @@
|
||||
/datum/component/storage/concrete/_insert_physical_item(obj/item/I, override = FALSE)
|
||||
. = TRUE
|
||||
var/atom/real_location = real_location()
|
||||
if(I.loc != real_location && real_location)
|
||||
if(real_location && I.loc != real_location)
|
||||
I.forceMove(real_location)
|
||||
refresh_mob_views()
|
||||
|
||||
@@ -95,16 +95,19 @@
|
||||
return FALSE
|
||||
|
||||
/datum/component/storage/concrete/proc/on_contents_del(datum/source, atom/A)
|
||||
SIGNAL_HANDLER
|
||||
var/atom/real_location = parent
|
||||
if(A in real_location)
|
||||
usr = null
|
||||
remove_from_storage(A, null)
|
||||
|
||||
/datum/component/storage/concrete/proc/on_deconstruct(datum/source, disassembled)
|
||||
SIGNAL_HANDLER
|
||||
if(drop_all_on_deconstruct)
|
||||
do_quick_empty()
|
||||
|
||||
/datum/component/storage/concrete/proc/on_break(datum/source, damage_flag)
|
||||
SIGNAL_HANDLER
|
||||
if(drop_all_on_break)
|
||||
do_quick_empty()
|
||||
if(unlock_on_break)
|
||||
@@ -131,14 +134,16 @@
|
||||
var/list/seeing_mobs = can_see_contents()
|
||||
for(var/mob/M in seeing_mobs)
|
||||
M.client.screen -= AM
|
||||
if(ismob(parent.loc) && isitem(AM))
|
||||
var/obj/item/I = AM
|
||||
var/mob/M = parent.loc
|
||||
I.dropped(M)
|
||||
I.item_flags &= ~IN_STORAGE
|
||||
I.remove_outline()
|
||||
if(isitem(AM))
|
||||
var/obj/item/removed_item = AM
|
||||
removed_item.item_flags &= ~IN_STORAGE
|
||||
if(ismob(parent.loc))
|
||||
var/mob/carrying_mob = parent.loc
|
||||
removed_item.dropped(carrying_mob, TRUE)
|
||||
if(new_location)
|
||||
AM.forceMove(new_location) // exited comsig will handle removal reset.
|
||||
//Reset the items values
|
||||
_removal_reset(AM)
|
||||
AM.forceMove(new_location)
|
||||
//We don't want to call this if the item is being destroyed
|
||||
AM.on_exit_storage(src)
|
||||
else
|
||||
@@ -147,7 +152,7 @@
|
||||
refresh_mob_views()
|
||||
if(isobj(parent))
|
||||
var/obj/O = parent
|
||||
O.update_icon()
|
||||
O.update_appearance()
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/concrete/proc/slave_can_insert_object(datum/component/storage/slave, obj/item/I, stop_messages = FALSE, mob/M)
|
||||
@@ -158,7 +163,7 @@
|
||||
if(. && !prevent_warning)
|
||||
slave.mob_item_insertion_feedback(usr, M, I)
|
||||
|
||||
/datum/component/storage/concrete/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) //Remote is null or the slave datum
|
||||
/datum/component/storage/concrete/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) //Remote is null or the slave datum
|
||||
var/datum/component/storage/concrete/master = master()
|
||||
var/atom/parent = src.parent
|
||||
var/moved = FALSE
|
||||
@@ -168,7 +173,7 @@
|
||||
if(!M.temporarilyRemoveItemFromInventory(I))
|
||||
return FALSE
|
||||
else
|
||||
moved = TRUE //At this point if the proc fails we need to manually move the object back to the turf/mob/whatever.
|
||||
moved = TRUE //At this point if the proc fails we need to manually move the object back to the turf/mob/whatever.
|
||||
if(I.pulledby)
|
||||
I.pulledby.stop_pulling()
|
||||
if(silent)
|
||||
@@ -203,7 +208,7 @@
|
||||
/datum/component/storage/concrete/update_icon()
|
||||
if(isobj(parent))
|
||||
var/obj/O = parent
|
||||
O.update_icon()
|
||||
O.update_appearance()
|
||||
for(var/i in slaves)
|
||||
var/datum/component/storage/slave = i
|
||||
slave.update_icon()
|
||||
|
||||
@@ -418,38 +418,38 @@
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/proc/mousedrop_onto(datum/source, atom/over_object, mob/M)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
set waitfor = FALSE
|
||||
. = COMPONENT_NO_MOUSEDROP
|
||||
if(!ismob(M))
|
||||
return
|
||||
if(!over_object)
|
||||
return
|
||||
if(ismecha(M.loc)) // stops inventory actions in a mech
|
||||
return
|
||||
if(M.incapacitated() || !M.canUseStorage())
|
||||
return
|
||||
var/atom/A = parent
|
||||
if(ismob(M)) //all the check for item manipulation are in other places, you can safely open any storages as anything and its not buggy, i checked
|
||||
A.add_fingerprint(M)
|
||||
if(istype(A, /obj/item))
|
||||
var/obj/item/I = A
|
||||
I.remove_outline() //Removes the outline when we drag
|
||||
if(!over_object)
|
||||
return FALSE
|
||||
if(ismecha(M.loc)) // stops inventory actions in a mech
|
||||
return FALSE
|
||||
// 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)
|
||||
return
|
||||
if(isrevenant(M))
|
||||
RevenantThrow(over_object, M, source)
|
||||
return
|
||||
if(!M.incapacitated())
|
||||
if(!istype(over_object, /atom/movable/screen))
|
||||
dump_content_at(over_object, M)
|
||||
return
|
||||
if(A.loc != M)
|
||||
return
|
||||
playsound(A, "rustle", 50, 1, -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)
|
||||
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(!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
|
||||
|
||||
@@ -370,7 +370,7 @@
|
||||
user.emote("scream")
|
||||
user.gain_trauma(/datum/brain_trauma/severe/paralysis/spinesnapped) // oopsie indeed!
|
||||
shake_camera(user, 7, 7)
|
||||
user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
|
||||
user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
|
||||
user.clear_fullscreen("flash", 4.5)
|
||||
|
||||
if(94 to 98)
|
||||
@@ -381,7 +381,7 @@
|
||||
user.gain_trauma_type(BRAIN_TRAUMA_MILD)
|
||||
user.playsound_local(get_turf(user), 'sound/weapons/flashbang.ogg', 100, TRUE, 8, 0.9)
|
||||
shake_camera(user, 6, 6)
|
||||
user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
|
||||
user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
|
||||
user.clear_fullscreen("flash", 3.5)
|
||||
|
||||
if(84 to 93)
|
||||
@@ -394,7 +394,7 @@
|
||||
user.playsound_local(get_turf(user), 'sound/weapons/flashbang.ogg', 100, TRUE, 8, 0.9)
|
||||
user.DefaultCombatKnockdown(40)
|
||||
shake_camera(user, 5, 5)
|
||||
user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
|
||||
user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
|
||||
user.clear_fullscreen("flash", 2.5)
|
||||
|
||||
if(64 to 83)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
GLOBAL_LIST_EMPTY(uplinks)
|
||||
#define PEN_ROTATIONS 2
|
||||
|
||||
/**
|
||||
* Uplinks
|
||||
@@ -17,7 +18,7 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
var/telecrystals
|
||||
var/selected_cat
|
||||
var/owner = null
|
||||
var/datum/game_mode/gamemode
|
||||
var/uplink_flag
|
||||
var/datum/uplink_purchase_log/purchase_log
|
||||
var/list/uplink_items
|
||||
var/hidden_crystals = 0
|
||||
@@ -26,11 +27,11 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
var/failsafe_code
|
||||
var/compact_mode = FALSE
|
||||
var/debug = FALSE
|
||||
var/saved_player_population = 0
|
||||
var/list/filters = list()
|
||||
///Instructions on how to access the uplink based on location
|
||||
var/unlock_text
|
||||
var/list/previous_attempts
|
||||
|
||||
|
||||
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/traitor_class/traitor_class)
|
||||
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, uplink_flag = UPLINK_TRAITORS, starting_tc = TELECRYSTALS_DEFAULT)
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
@@ -44,16 +45,13 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
RegisterSignal(parent, COMSIG_IMPLANT_EXISTING_UPLINK, .proc/new_implant)
|
||||
else if(istype(parent, /obj/item/pda))
|
||||
RegisterSignal(parent, COMSIG_PDA_CHANGE_RINGTONE, .proc/new_ringtone)
|
||||
// RegisterSignal(parent, COMSIG_PDA_CHECK_DETONATE, .proc/check_detonate)
|
||||
else if(istype(parent, /obj/item/radio))
|
||||
RegisterSignal(parent, COMSIG_RADIO_NEW_FREQUENCY, .proc/new_frequency)
|
||||
else if(istype(parent, /obj/item/pen))
|
||||
RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation)
|
||||
|
||||
GLOB.uplinks += src
|
||||
if(istype(traitor_class))
|
||||
filters = traitor_class.uplink_filters
|
||||
starting_tc = traitor_class.TC
|
||||
uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted, filters)
|
||||
GLOB.uplinks |= src
|
||||
|
||||
if(_owner)
|
||||
owner = _owner
|
||||
@@ -64,44 +62,58 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
purchase_log = new(owner, src)
|
||||
lockable = _lockable
|
||||
active = _enabled
|
||||
gamemode = _gamemode
|
||||
src.uplink_flag = uplink_flag
|
||||
update_items()
|
||||
telecrystals = starting_tc
|
||||
if(!lockable)
|
||||
active = TRUE
|
||||
locked = FALSE
|
||||
saved_player_population = GLOB.joined_player_list.len
|
||||
|
||||
previous_attempts = list()
|
||||
|
||||
/datum/component/uplink/InheritComponent(datum/component/uplink/U)
|
||||
lockable |= U.lockable
|
||||
active |= U.active
|
||||
if(!gamemode)
|
||||
gamemode = U.gamemode
|
||||
uplink_flag |= U.uplink_flag
|
||||
telecrystals += U.telecrystals
|
||||
if(purchase_log && U.purchase_log)
|
||||
purchase_log.MergeWithAndDel(U.purchase_log)
|
||||
|
||||
/datum/component/uplink/Destroy()
|
||||
GLOB.uplinks -= src
|
||||
gamemode = null
|
||||
purchase_log = null
|
||||
return ..()
|
||||
|
||||
/datum/component/uplink/proc/update_items()
|
||||
var/updated_items
|
||||
updated_items = get_uplink_items(uplink_flag, TRUE, allow_restricted)
|
||||
update_sales(updated_items)
|
||||
uplink_items = updated_items
|
||||
|
||||
/datum/component/uplink/proc/update_sales(updated_items)
|
||||
var/discount_categories = list("Discounted Gear", "Discounted Team Gear", "Limited Stock Team Gear")
|
||||
if (uplink_items == null)
|
||||
return
|
||||
for (var/category in discount_categories) // Makes sure discounted items aren't renewed or replaced
|
||||
if (uplink_items[category] != null && updated_items[category] != null)
|
||||
updated_items[category] = uplink_items[category]
|
||||
|
||||
/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/telecrystal/TC, silent = FALSE)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='notice'>You slot [TC] into [parent] and charge its internal uplink.</span>")
|
||||
to_chat(user, span_notice("You slot [TC] into [parent] and charge its internal uplink."))
|
||||
var/amt = TC.amount
|
||||
telecrystals += amt
|
||||
TC.use(amt)
|
||||
|
||||
/datum/component/uplink/proc/set_gamemode(_gamemode)
|
||||
gamemode = _gamemode
|
||||
uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted)
|
||||
// log_uplink("[key_name(user)] loaded [amt] telecrystals into [parent]'s uplink")
|
||||
|
||||
/datum/component/uplink/proc/OnAttackBy(datum/source, obj/item/I, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!active)
|
||||
return //no hitting everyone/everything just to try to slot tcs in!
|
||||
return //no hitting everyone/everything just to try to slot tcs in!
|
||||
if(istype(I, /obj/item/stack/telecrystal))
|
||||
LoadTC(user, I)
|
||||
// CIT SPECIFIC: STEALING from unlocked uplink.
|
||||
if(active)
|
||||
if(I.GetComponent(/datum/component/uplink))
|
||||
var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
|
||||
@@ -118,31 +130,26 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
var/cost = UI.refund_amount || UI.cost
|
||||
if(I.type == path && UI.refundable && I.check_uplink_validity())
|
||||
telecrystals += cost
|
||||
purchase_log.total_spent -= cost
|
||||
to_chat(user, "<span class='notice'>[I] refunded.</span>")
|
||||
// log_uplink("[key_name(user)] refunded [UI] for [cost] telecrystals using [parent]'s uplink")
|
||||
if(purchase_log)
|
||||
purchase_log.total_spent -= cost
|
||||
to_chat(user, span_notice("[I] refunded."))
|
||||
qdel(I)
|
||||
return
|
||||
|
||||
/datum/component/uplink/proc/interact(datum/source, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(locked)
|
||||
return
|
||||
active = TRUE
|
||||
update_items()
|
||||
if(user)
|
||||
//update the saved population
|
||||
var/previous_player_population = saved_player_population
|
||||
saved_player_population = GLOB.joined_player_list.len
|
||||
//if population has changed, update uplink items
|
||||
if(saved_player_population != previous_player_population)
|
||||
//make sure discounts are not rerolled
|
||||
var/old_discounts = uplink_items["Discounted Gear"]
|
||||
uplink_items = get_uplink_items(gamemode, FALSE, allow_restricted, filters)
|
||||
if(old_discounts)
|
||||
uplink_items["Discounted Gear"] = old_discounts
|
||||
ui_interact(user)
|
||||
|
||||
INVOKE_ASYNC(src, .proc/ui_interact, user)
|
||||
// an unlocked uplink blocks also opening the PDA or headset menu
|
||||
return COMPONENT_NO_INTERACT
|
||||
|
||||
|
||||
/datum/component/uplink/ui_state(mob/user)
|
||||
if(istype(parent, /obj/item/implant/uplink))
|
||||
return GLOB.not_incapacitated_state
|
||||
@@ -178,15 +185,10 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
var/datum/uplink_item/I = uplink_items[category][item]
|
||||
if(I.limited_stock == 0)
|
||||
continue
|
||||
if(I.restricted_roles.len)
|
||||
var/is_inaccessible = TRUE
|
||||
for(var/R in I.restricted_roles)
|
||||
if(R == user.mind.assigned_role || debug)
|
||||
is_inaccessible = FALSE
|
||||
if(is_inaccessible)
|
||||
if(length(I.restricted_roles))
|
||||
if(!debug && !(user.mind.assigned_role in I.restricted_roles))
|
||||
continue
|
||||
/*
|
||||
if(I.restricted_species) //catpeople specfic gloves.
|
||||
if(I.restricted_species)
|
||||
if(ishuman(user))
|
||||
var/is_inaccessible = TRUE
|
||||
var/mob/living/carbon/human/H = user
|
||||
@@ -196,7 +198,6 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
break
|
||||
if(is_inaccessible)
|
||||
continue
|
||||
*/
|
||||
cat["items"] += list(list(
|
||||
"name" = I.name,
|
||||
"cost" = I.cost,
|
||||
@@ -255,25 +256,41 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
// Implant signal responses
|
||||
|
||||
/datum/component/uplink/proc/implant_activation()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/item/implant/implant = parent
|
||||
locked = FALSE
|
||||
interact(null, implant.imp_in)
|
||||
|
||||
/datum/component/uplink/proc/implanting(datum/source, list/arguments)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/mob/user = arguments[2]
|
||||
owner = "[user.key]"
|
||||
owner = user?.key
|
||||
if(owner && !purchase_log)
|
||||
LAZYINITLIST(GLOB.uplink_purchase_logs_by_key)
|
||||
if(GLOB.uplink_purchase_logs_by_key[owner])
|
||||
purchase_log = GLOB.uplink_purchase_logs_by_key[owner]
|
||||
else
|
||||
purchase_log = new(owner, src)
|
||||
|
||||
/datum/component/uplink/proc/old_implant(datum/source, list/arguments, obj/item/implant/new_implant)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
// It kinda has to be weird like this until implants are components
|
||||
return SEND_SIGNAL(new_implant, COMSIG_IMPLANT_EXISTING_UPLINK, src)
|
||||
|
||||
/datum/component/uplink/proc/new_implant(datum/source, datum/component/uplink/uplink)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
uplink.telecrystals += telecrystals
|
||||
return COMPONENT_DELETE_NEW_IMPLANT
|
||||
|
||||
// PDA signal responses
|
||||
|
||||
/datum/component/uplink/proc/new_ringtone(datum/source, mob/living/user, new_ring_text)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/item/pda/master = parent
|
||||
if(trim(lowertext(new_ring_text)) != trim(lowertext(unlock_code)))
|
||||
if(trim(lowertext(new_ring_text)) == trim(lowertext(failsafe_code)))
|
||||
@@ -282,14 +299,21 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
return
|
||||
locked = FALSE
|
||||
interact(null, user)
|
||||
to_chat(user, "<span class='hear'>The PDA softly beeps.</span>")
|
||||
to_chat(user, span_hear("The PDA softly beeps."))
|
||||
user << browse(null, "window=pda")
|
||||
master.mode = 0
|
||||
return COMPONENT_STOP_RINGTONE_CHANGE
|
||||
|
||||
/datum/component/uplink/proc/check_detonate()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
// return COMPONENT_PDA_NO_DETONATE
|
||||
|
||||
// Radio signal responses
|
||||
|
||||
/datum/component/uplink/proc/new_frequency(datum/source, list/arguments)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/item/radio/master = parent
|
||||
var/frequency = arguments[1]
|
||||
if(frequency != unlock_code)
|
||||
@@ -303,15 +327,22 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
// Pen signal responses
|
||||
|
||||
/datum/component/uplink/proc/pen_rotation(datum/source, degrees, mob/living/carbon/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/item/pen/master = parent
|
||||
if(degrees != unlock_code)
|
||||
if(degrees == failsafe_code) //Getting failsafes on pens is risky business
|
||||
failsafe()
|
||||
return
|
||||
locked = FALSE
|
||||
master.degrees = 0
|
||||
interact(null, user)
|
||||
to_chat(user, "<span class='warning'>Your pen makes a clicking noise, before quickly rotating back to 0 degrees!</span>")
|
||||
previous_attempts += degrees
|
||||
if(length(previous_attempts) > PEN_ROTATIONS)
|
||||
popleft(previous_attempts)
|
||||
|
||||
if(compare_list(previous_attempts, unlock_code))
|
||||
locked = FALSE
|
||||
previous_attempts.Cut()
|
||||
master.degrees = 0
|
||||
interact(null, user)
|
||||
to_chat(user, span_warning("Your pen makes a clicking noise, before quickly rotating back to 0 degrees!"))
|
||||
|
||||
else if(compare_list(previous_attempts, failsafe_code))
|
||||
failsafe(user)
|
||||
|
||||
/datum/component/uplink/proc/setup_unlock_code()
|
||||
unlock_code = generate_code()
|
||||
@@ -321,15 +352,18 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
else if(istype(parent,/obj/item/radio))
|
||||
unlock_note = "<B>Radio Frequency:</B> [format_frequency(unlock_code)] ([P.name])."
|
||||
else if(istype(parent,/obj/item/pen))
|
||||
unlock_note = "<B>Uplink Degrees:</B> [unlock_code] ([P.name])."
|
||||
unlock_note = "<B>Uplink Degrees:</B> [english_list(unlock_code)] ([P.name])."
|
||||
|
||||
/datum/component/uplink/proc/generate_code()
|
||||
if(istype(parent,/obj/item/pda))
|
||||
return "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
|
||||
else if(istype(parent,/obj/item/radio))
|
||||
return sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
|
||||
return return_unused_frequency()
|
||||
else if(istype(parent,/obj/item/pen))
|
||||
return rand(1, 360)
|
||||
var/list/L = list()
|
||||
for(var/i in 1 to PEN_ROTATIONS)
|
||||
L += rand(1, 360)
|
||||
return L
|
||||
|
||||
/datum/component/uplink/proc/failsafe(mob/living/carbon/user)
|
||||
if(!parent)
|
||||
@@ -339,5 +373,5 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
return
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has triggered an uplink failsafe explosion at [AREACOORD(T)] The owner of the uplink was [ADMIN_LOOKUPFLW(owner)].")
|
||||
log_game("[key_name(user)] triggered an uplink failsafe explosion. The owner of the uplink was [key_name(owner)].")
|
||||
explosion(T,1,2,3)
|
||||
explosion(parent, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 3)
|
||||
qdel(parent) //Alternatively could brick the uplink.
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
active_timers = null
|
||||
for(var/thing in timers)
|
||||
var/datum/timedevent/timer = thing
|
||||
if (timer.spent)
|
||||
if (timer.spent && !(timer.flags & TIMER_DELETE_ME))
|
||||
continue
|
||||
qdel(timer)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
return
|
||||
|
||||
switch(stage)
|
||||
if(2 || 3) //Pretend to be a cold and give time to spread.
|
||||
if(2, 3) //Pretend to be a cold and give time to spread.
|
||||
if(prob(8))
|
||||
affected_mob.emote("sneeze")
|
||||
if(prob(8))
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
L.visible_message("<span class='warning'>[held_mob] escapes from [L]!</span>", "<span class='warning'>[held_mob] escapes your grip!</span>")
|
||||
release()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
/obj/item/clothing/head/mob_holder/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
|
||||
if(M == held_mob || !ishuman(M)) //monkeys holding monkeys holding monkeys...
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -0,0 +1,517 @@
|
||||
/// An element for atoms that, when dragged and dropped onto a mob, opens a strip panel.
|
||||
/datum/element/strippable
|
||||
element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH
|
||||
id_arg_index = 2
|
||||
|
||||
/// An assoc list of keys to /datum/strippable_item
|
||||
var/list/items
|
||||
|
||||
/// A proc path that returns TRUE/FALSE if we should show the strip panel for this entity.
|
||||
/// If it does not exist, the strip menu will always show.
|
||||
/// Will be called with (mob/user).
|
||||
var/should_strip_proc_path
|
||||
|
||||
/// An existing strip menus
|
||||
var/list/strip_menus
|
||||
|
||||
/datum/element/strippable/Attach(datum/target, list/items, should_strip_proc_path)
|
||||
. = ..()
|
||||
if (!isatom(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
RegisterSignal(target, COMSIG_MOUSEDROP_ONTO, .proc/mouse_drop_onto)
|
||||
|
||||
src.items = items
|
||||
src.should_strip_proc_path = should_strip_proc_path
|
||||
|
||||
/datum/element/strippable/Detach(datum/source)
|
||||
. = ..()
|
||||
|
||||
UnregisterSignal(source, COMSIG_MOUSEDROP_ONTO)
|
||||
|
||||
if (!isnull(strip_menus))
|
||||
qdel(strip_menus[source])
|
||||
strip_menus -= source
|
||||
|
||||
/datum/element/strippable/proc/mouse_drop_onto(datum/source, atom/over, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (user == source)
|
||||
return
|
||||
|
||||
if (over != user)
|
||||
return
|
||||
|
||||
// Cyborgs buckle people by dragging them onto them, unless in combat mode.
|
||||
if (iscyborg(user))
|
||||
var/mob/living/silicon/robot/cyborg_user = user
|
||||
if (cyborg_user.a_intent == INTENT_HARM)
|
||||
return
|
||||
|
||||
if (!isnull(should_strip_proc_path) && !call(source, should_strip_proc_path)(user))
|
||||
return
|
||||
|
||||
var/datum/strip_menu/strip_menu
|
||||
|
||||
if (isnull(strip_menu))
|
||||
strip_menu = new(source, src)
|
||||
LAZYSET(strip_menus, source, strip_menu)
|
||||
|
||||
INVOKE_ASYNC(strip_menu, /datum/.proc/ui_interact, user)
|
||||
|
||||
/// A representation of an item that can be stripped down
|
||||
/datum/strippable_item
|
||||
/// The STRIPPABLE_ITEM_* key
|
||||
var/key
|
||||
|
||||
/// Should we warn about dangerous clothing?
|
||||
var/warn_dangerous_clothing = TRUE
|
||||
|
||||
/// Gets the item from the given source.
|
||||
/datum/strippable_item/proc/get_item(atom/source)
|
||||
|
||||
/// Tries to equip the item onto the given source.
|
||||
/// Returns TRUE/FALSE depending on if it is allowed.
|
||||
/// This should be used for checking if an item CAN be equipped.
|
||||
/// It should not perform the equipping itself.
|
||||
/datum/strippable_item/proc/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
if (HAS_TRAIT(equipping, TRAIT_NODROP))
|
||||
to_chat(user, span_warning("You can't put [equipping] on [source], it's stuck to your hand!"))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Start the equipping process. This is the proc you should yield in.
|
||||
/// Returns TRUE/FALSE depending on if it is allowed.
|
||||
/datum/strippable_item/proc/start_equip(atom/source, obj/item/equipping, mob/user)
|
||||
if (warn_dangerous_clothing && isclothing(source))
|
||||
source.visible_message(
|
||||
span_notice("[user] tries to put [equipping] on [source]."),
|
||||
span_notice("[user] tries to put [equipping] on you."),
|
||||
ignored_mobs = user,
|
||||
)
|
||||
|
||||
if(ishuman(source))
|
||||
var/mob/living/carbon/human/victim_human = source
|
||||
if(victim_human.key && !victim_human.client) // AKA braindead
|
||||
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
|
||||
var/list/new_entry = list(list(user.name, "tried equipping you with [equipping]", world.time))
|
||||
LAZYADD(victim_human.afk_thefts, new_entry)
|
||||
|
||||
to_chat(user, span_notice("You try to put [equipping] on [source]..."))
|
||||
|
||||
var/log = "[key_name(source)] is having [equipping] put on them by [key_name(user)]"
|
||||
user.log_message(log, LOG_ATTACK, color="red")
|
||||
source.log_message(log, LOG_VICTIM, color="red", log_globally=FALSE)
|
||||
|
||||
return TRUE
|
||||
|
||||
/// The proc that places the item on the source. This should not yield.
|
||||
/datum/strippable_item/proc/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
return TRUE
|
||||
|
||||
/// Tries to unequip the item from the given source.
|
||||
/// Returns TRUE/FALSE depending on if it is allowed.
|
||||
/// This should be used for checking if it CAN be unequipped.
|
||||
/// It should not perform the unequipping itself.
|
||||
/datum/strippable_item/proc/try_unequip(atom/source, mob/user)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
var/obj/item/item = get_item(source)
|
||||
if (isnull(item))
|
||||
return FALSE
|
||||
|
||||
if (ismob(source))
|
||||
var/mob/mob_source = source
|
||||
if (!item.canStrip(user, mob_source))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Start the unequipping process. This is the proc you should yield in.
|
||||
/// Returns TRUE/FALSE depending on if it is allowed.
|
||||
/datum/strippable_item/proc/start_unequip(atom/source, mob/user)
|
||||
var/obj/item/item = get_item(source)
|
||||
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,
|
||||
)
|
||||
|
||||
to_chat(user, span_danger("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)
|
||||
|
||||
if(ishuman(source))
|
||||
var/mob/living/carbon/human/victim_human = source
|
||||
if(victim_human.key && !victim_human.client) // AKA braindead
|
||||
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
|
||||
var/list/new_entry = list(list(user.name, "tried unequipping your [item.name]", world.time))
|
||||
LAZYADD(victim_human.afk_thefts, new_entry)
|
||||
|
||||
return TRUE
|
||||
|
||||
/// The proc that unequips the item from the source. This should not yield.
|
||||
/datum/strippable_item/proc/finish_unequip(atom/source, mob/user)
|
||||
|
||||
/// Returns a STRIPPABLE_OBSCURING_* define to report on whether or not this is obscured.
|
||||
/datum/strippable_item/proc/get_obscuring(atom/source)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
return STRIPPABLE_OBSCURING_NONE
|
||||
|
||||
/// Returns the ID of this item's strippable action.
|
||||
/// Return `null` if there is no alternate action.
|
||||
/// Any return value of this must be in StripMenu.
|
||||
/datum/strippable_item/proc/get_alternate_action(atom/source, mob/user)
|
||||
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
|
||||
return FALSE
|
||||
return null
|
||||
|
||||
/// Performs an alternative action on this strippable_item.
|
||||
/// `has_alternate_action` needs to be TRUE.
|
||||
/datum/strippable_item/proc/alternate_action(atom/source, mob/user)
|
||||
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
|
||||
return null
|
||||
return TRUE
|
||||
|
||||
/// Returns whether or not this item should show.
|
||||
/datum/strippable_item/proc/should_show(atom/source, mob/user)
|
||||
return TRUE
|
||||
|
||||
/// A preset for equipping items onto mob slots
|
||||
/datum/strippable_item/mob_item_slot
|
||||
/// The ITEM_SLOT_* to equip to.
|
||||
var/item_slot
|
||||
|
||||
/datum/strippable_item/mob_item_slot/get_item(atom/source)
|
||||
if (!ismob(source))
|
||||
return null
|
||||
|
||||
var/mob/mob_source = source
|
||||
return mob_source.get_item_by_slot(item_slot)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
if (!equipping.mob_can_equip(
|
||||
source,
|
||||
user,
|
||||
item_slot,
|
||||
disable_warning = TRUE,
|
||||
bypass_equip_delay_self = TRUE,
|
||||
))
|
||||
to_chat(user, span_warning("\The [equipping] doesn't fit in that place!"))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/mob_item_slot/start_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
if (!do_mob(user, source, get_equip_delay(equipping)))
|
||||
return FALSE
|
||||
|
||||
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
|
||||
return FALSE
|
||||
|
||||
if (!equipping.mob_can_equip(
|
||||
source,
|
||||
user,
|
||||
item_slot,
|
||||
disable_warning = TRUE,
|
||||
bypass_equip_delay_self = TRUE,
|
||||
))
|
||||
return FALSE
|
||||
|
||||
if (!user.temporarilyRemoveItemFromInventory(equipping))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/mob_item_slot/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
var/mob/mob_source = source
|
||||
mob_source.equip_to_slot(equipping, item_slot)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/get_obscuring(atom/source)
|
||||
if (iscarbon(source))
|
||||
var/mob/living/carbon/carbon_source = source
|
||||
return (item_slot in carbon_source.check_obscured_slots()) \
|
||||
? STRIPPABLE_OBSCURING_COMPLETELY \
|
||||
: STRIPPABLE_OBSCURING_NONE
|
||||
|
||||
return FALSE
|
||||
|
||||
/datum/strippable_item/mob_item_slot/start_unequip(atom/source, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
return start_unequip_mob(get_item(source), source, user)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/finish_unequip(atom/source, mob/user)
|
||||
var/obj/item/item = get_item(source)
|
||||
if (isnull(item))
|
||||
return FALSE
|
||||
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
return finish_unequip_mob(item, source, user)
|
||||
|
||||
/// Returns the delay of equipping this item to a mob
|
||||
/datum/strippable_item/mob_item_slot/proc/get_equip_delay(obj/item/equipping)
|
||||
return equipping.equip_delay_other
|
||||
|
||||
/// 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))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// A utility function for `/datum/strippable_item`s to finish unequipping an item from a mob.
|
||||
/proc/finish_unequip_mob(obj/item/item, mob/source, mob/user)
|
||||
if (!item.doStrip(user, source))
|
||||
return FALSE
|
||||
|
||||
user.log_message("[key_name(source)] has been stripped of [item] by [key_name(user)]", LOG_ATTACK, color="red")
|
||||
source.log_message("[key_name(source)] has been stripped of [item] by [key_name(user)]", LOG_VICTIM, color="red", log_globally=FALSE)
|
||||
|
||||
// Updates speed in case stripped speed affecting item
|
||||
source.update_equipment_speed_mods()
|
||||
|
||||
/// A representation of the stripping UI
|
||||
/datum/strip_menu
|
||||
/// The owner who has the element /datum/element/strippable
|
||||
var/atom/movable/owner
|
||||
|
||||
/// The strippable element itself
|
||||
var/datum/element/strippable/strippable
|
||||
|
||||
/// A lazy list of user mobs to a list of strip menu keys that they're interacting with
|
||||
var/list/interactions
|
||||
|
||||
/datum/strip_menu/New(atom/movable/owner, datum/element/strippable/strippable)
|
||||
. = ..()
|
||||
src.owner = owner
|
||||
src.strippable = strippable
|
||||
|
||||
/datum/strip_menu/Destroy()
|
||||
owner = null
|
||||
strippable = null
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/strip_menu/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if (!ui)
|
||||
ui = new(user, src, "StripMenu")
|
||||
ui.open()
|
||||
|
||||
/datum/strip_menu/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/simple/inventory),
|
||||
)
|
||||
|
||||
/datum/strip_menu/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
var/list/items = list()
|
||||
|
||||
for (var/strippable_key in strippable.items)
|
||||
var/datum/strippable_item/item_data = strippable.items[strippable_key]
|
||||
|
||||
if (!item_data.should_show(owner, user))
|
||||
continue
|
||||
|
||||
var/list/result
|
||||
|
||||
if(strippable_key in LAZYACCESS(interactions, user))
|
||||
LAZYSET(result, "interacting", TRUE)
|
||||
|
||||
var/obscuring = item_data.get_obscuring(owner)
|
||||
if (obscuring != STRIPPABLE_OBSCURING_NONE)
|
||||
LAZYSET(result, "obscured", obscuring)
|
||||
items[strippable_key] = result
|
||||
continue
|
||||
|
||||
var/obj/item/item = item_data.get_item(owner)
|
||||
if (isnull(item))
|
||||
items[strippable_key] = result
|
||||
continue
|
||||
|
||||
LAZYINITLIST(result)
|
||||
|
||||
result["icon"] = icon2base64(icon(item.icon, item.icon_state, SOUTH, 1))
|
||||
result["name"] = item.name
|
||||
result["alternate"] = item_data.get_alternate_action(owner, user)
|
||||
|
||||
items[strippable_key] = result
|
||||
|
||||
data["items"] = items
|
||||
|
||||
// While most `\the`s are implicit, this one is not.
|
||||
// In this case, `\The` would otherwise be used.
|
||||
// This doesn't match with what it's used for, which is to say "Stripping the alien drone",
|
||||
// as opposed to "Stripping The alien drone".
|
||||
// Human names will still show without "the", as they are proper nouns.
|
||||
data["name"] = "\the [owner]"
|
||||
|
||||
/// Customize the strip menu
|
||||
data["long_strip_menu"] = user.client.prefs.long_strip_menu
|
||||
|
||||
return data
|
||||
|
||||
/datum/strip_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if (.)
|
||||
return
|
||||
|
||||
. = TRUE
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
switch (action)
|
||||
if ("use")
|
||||
var/key = params["key"]
|
||||
var/datum/strippable_item/strippable_item = strippable.items[key]
|
||||
|
||||
if (isnull(strippable_item))
|
||||
return
|
||||
|
||||
if (!strippable_item.should_show(owner, user))
|
||||
return
|
||||
|
||||
if (strippable_item.get_obscuring(owner) == STRIPPABLE_OBSCURING_COMPLETELY)
|
||||
return
|
||||
|
||||
var/item = strippable_item.get_item(owner)
|
||||
if (isnull(item))
|
||||
var/obj/item/held_item = user.get_active_held_item()
|
||||
if (isnull(held_item))
|
||||
return
|
||||
|
||||
if (strippable_item.try_equip(owner, held_item, user))
|
||||
LAZYORASSOCLIST(interactions, user, key)
|
||||
|
||||
// Yielding call
|
||||
var/should_finish = strippable_item.start_equip(owner, held_item, user)
|
||||
|
||||
LAZYREMOVEASSOC(interactions, user, key)
|
||||
|
||||
if (!should_finish)
|
||||
return
|
||||
|
||||
if (QDELETED(src) || QDELETED(owner))
|
||||
return
|
||||
|
||||
// They equipped an item in the meantime
|
||||
if (!isnull(strippable_item.get_item(owner)))
|
||||
return
|
||||
|
||||
if (!user.Adjacent(owner))
|
||||
return
|
||||
|
||||
strippable_item.finish_equip(owner, held_item, user)
|
||||
else if (strippable_item.try_unequip(owner, user))
|
||||
LAZYORASSOCLIST(interactions, user, key)
|
||||
|
||||
var/should_unequip = strippable_item.start_unequip(owner, user)
|
||||
|
||||
LAZYREMOVEASSOC(interactions, user, key)
|
||||
|
||||
// Yielding call
|
||||
if (!should_unequip)
|
||||
return
|
||||
|
||||
if (QDELETED(src) || QDELETED(owner))
|
||||
return
|
||||
|
||||
// They changed the item in the meantime
|
||||
if (strippable_item.get_item(owner) != item)
|
||||
return
|
||||
|
||||
if (!user.Adjacent(owner))
|
||||
return
|
||||
|
||||
strippable_item.finish_unequip(owner, user)
|
||||
if ("alt")
|
||||
var/key = params["key"]
|
||||
var/datum/strippable_item/strippable_item = strippable.items[key]
|
||||
|
||||
if (isnull(strippable_item))
|
||||
return
|
||||
|
||||
if (!strippable_item.should_show(owner, user))
|
||||
return
|
||||
|
||||
if (strippable_item.get_obscuring(owner) == STRIPPABLE_OBSCURING_COMPLETELY)
|
||||
return
|
||||
|
||||
var/item = strippable_item.get_item(owner)
|
||||
if (isnull(item))
|
||||
return
|
||||
|
||||
if (isnull(strippable_item.get_alternate_action(owner, user)))
|
||||
return
|
||||
|
||||
LAZYORASSOCLIST(interactions, user, key)
|
||||
|
||||
// Potentially yielding
|
||||
strippable_item.alternate_action(owner, user)
|
||||
|
||||
LAZYREMOVEASSOC(interactions, user, key)
|
||||
|
||||
/datum/strip_menu/ui_host(mob/user)
|
||||
return owner
|
||||
|
||||
/datum/strip_menu/ui_state(mob/user)
|
||||
return GLOB.always_state
|
||||
|
||||
/datum/strip_menu/ui_status(mob/user, datum/ui_state/state)
|
||||
. = ..()
|
||||
|
||||
if(isliving(user))
|
||||
var/mob/living/living_user = user
|
||||
|
||||
if (
|
||||
living_user.stat == CONSCIOUS \
|
||||
&& living_user.Adjacent(owner)
|
||||
)
|
||||
return UI_INTERACTIVE
|
||||
if(IsAdminGhost(user))
|
||||
return UI_INTERACTIVE
|
||||
if(user.Adjacent(owner))
|
||||
return UI_UPDATE
|
||||
else
|
||||
return UI_DISABLED
|
||||
|
||||
/// Creates an assoc list of keys to /datum/strippable_item
|
||||
/proc/create_strippable_list(types)
|
||||
var/list/strippable_items = list()
|
||||
|
||||
for (var/strippable_type in types)
|
||||
var/datum/strippable_item/strippable_item = new strippable_type
|
||||
strippable_items[strippable_item.key] = strippable_item
|
||||
|
||||
return strippable_items
|
||||
@@ -0,0 +1,44 @@
|
||||
///This element just handles creating and destroying an area sound manager that's hooked into weather stuff
|
||||
/datum/element/weather_listener
|
||||
element_flags = ELEMENT_BESPOKE
|
||||
id_arg_index = 2
|
||||
var/weather_type
|
||||
//What events to change the track on
|
||||
var/list/sound_change_signals
|
||||
//The weather type we're working with
|
||||
var/weather_trait
|
||||
//The playlist of sounds to draw from. Pass by ref
|
||||
var/list/playlist
|
||||
|
||||
|
||||
/datum/element/weather_listener/Attach(datum/target, w_type, trait, weather_playlist)
|
||||
. = ..()
|
||||
if(!weather_type)
|
||||
weather_type = w_type
|
||||
sound_change_signals = list(
|
||||
COMSIG_WEATHER_TELEGRAPH(weather_type),
|
||||
COMSIG_WEATHER_START(weather_type),
|
||||
COMSIG_WEATHER_WINDDOWN(weather_type),
|
||||
COMSIG_WEATHER_END(weather_type)
|
||||
)
|
||||
weather_trait = trait
|
||||
playlist = weather_playlist
|
||||
|
||||
RegisterSignal(target, COMSIG_MOVABLE_Z_CHANGED, .proc/handle_z_level_change, override = TRUE)
|
||||
RegisterSignal(target, COMSIG_MOB_CLIENT_LOGOUT, .proc/handle_logout, override = TRUE)
|
||||
|
||||
/datum/element/weather_listener/Detach(datum/source)
|
||||
. = ..()
|
||||
UnregisterSignal(source, COMSIG_MOVABLE_Z_CHANGED, COMSIG_MOB_CLIENT_LOGOUT)
|
||||
|
||||
/datum/element/weather_listener/proc/handle_z_level_change(datum/source, old_z, new_z)
|
||||
SIGNAL_HANDLER
|
||||
var/list/fitting_z_levels = SSmapping.levels_by_trait(weather_trait)
|
||||
if(!(new_z in fitting_z_levels))
|
||||
return
|
||||
var/datum/component/our_comp = source.AddComponent(/datum/component/area_sound_manager, playlist, list(), COMSIG_MOB_CLIENT_LOGOUT, fitting_z_levels)
|
||||
our_comp.RegisterSignal(SSdcs, sound_change_signals, /datum/component/area_sound_manager/proc/handle_change)
|
||||
|
||||
/datum/element/weather_listener/proc/handle_logout(datum/source, client/this_is_a_null_ref)
|
||||
SIGNAL_HANDLER
|
||||
source.RemoveElement(/datum/element/weather_listener, weather_type, weather_trait, playlist)
|
||||
@@ -1,21 +1,21 @@
|
||||
/*
|
||||
output_atoms (list of atoms) The destination(s) for the sounds
|
||||
output_atoms (list of atoms) The destination(s) for the sounds
|
||||
|
||||
mid_sounds (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end.
|
||||
mid_length (num) The length to wait between playing mid_sounds
|
||||
mid_sounds (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end.
|
||||
mid_length (num) The length to wait between playing mid_sounds
|
||||
|
||||
start_sound (soundfile) Played before starting the mid_sounds loop
|
||||
start_length (num) How long to wait before starting the main loop after playing start_sound
|
||||
start_sound (soundfile) Played before starting the mid_sounds loop
|
||||
start_length (num) How long to wait before starting the main loop after playing start_sound
|
||||
|
||||
end_sound (soundfile) The sound played after the main loop has concluded
|
||||
end_sound (soundfile) The sound played after the main loop has concluded
|
||||
|
||||
chance (num) Chance per loop to play a mid_sound
|
||||
volume (num) Sound output volume
|
||||
max_loops (num) The max amount of loops to run for.
|
||||
direct (bool) If true plays directly to provided atoms instead of from them
|
||||
chance (num) Chance per loop to play a mid_sound
|
||||
volume (num) Sound output volume
|
||||
max_loops (num) The max amount of loops to run for.
|
||||
direct (bool) If true plays directly to provided atoms instead of from them
|
||||
*/
|
||||
/datum/looping_sound
|
||||
var/list/atom/output_atoms
|
||||
var/atom/parent
|
||||
var/mid_sounds
|
||||
var/mid_length
|
||||
///Override for volume of start sound
|
||||
@@ -34,38 +34,46 @@
|
||||
var/falloff_exponent
|
||||
var/timerid
|
||||
var/falloff_distance
|
||||
var/skip_starting_sounds = FALSE
|
||||
var/loop_started = FALSE
|
||||
|
||||
/datum/looping_sound/New(list/_output_atoms=list(), start_immediately=FALSE, _direct=FALSE)
|
||||
/datum/looping_sound/New(_parent, start_immediately=FALSE, _direct=FALSE, _skip_starting_sounds = FALSE)
|
||||
if(!mid_sounds)
|
||||
WARNING("A looping sound datum was created without sounds to play.")
|
||||
return
|
||||
|
||||
output_atoms = _output_atoms
|
||||
set_parent(_parent)
|
||||
direct = _direct
|
||||
skip_starting_sounds = _skip_starting_sounds
|
||||
|
||||
if(start_immediately)
|
||||
start()
|
||||
|
||||
/datum/looping_sound/Destroy()
|
||||
stop()
|
||||
output_atoms = null
|
||||
stop(TRUE)
|
||||
return ..()
|
||||
|
||||
/datum/looping_sound/proc/start(atom/add_thing)
|
||||
if(add_thing)
|
||||
output_atoms |= add_thing
|
||||
/datum/looping_sound/proc/start(on_behalf_of)
|
||||
if(on_behalf_of)
|
||||
set_parent(on_behalf_of)
|
||||
if(timerid)
|
||||
return
|
||||
on_start()
|
||||
|
||||
/datum/looping_sound/proc/stop(atom/remove_thing)
|
||||
if(remove_thing)
|
||||
output_atoms -= remove_thing
|
||||
/datum/looping_sound/proc/stop(null_parent)
|
||||
if(null_parent)
|
||||
set_parent(null)
|
||||
if(!timerid)
|
||||
return
|
||||
on_stop()
|
||||
deltimer(timerid)
|
||||
deltimer(timerid, SSsound_loops)
|
||||
timerid = null
|
||||
loop_started = FALSE
|
||||
|
||||
/datum/looping_sound/proc/start_sound_loop()
|
||||
loop_started = TRUE
|
||||
sound_loop()
|
||||
timerid = addtimer(CALLBACK(src, .proc/sound_loop, world.time), mid_length, TIMER_CLIENT_TIME | TIMER_STOPPABLE | TIMER_LOOP | TIMER_DELETE_ME, SSsound_loops)
|
||||
|
||||
/datum/looping_sound/proc/sound_loop(starttime)
|
||||
if(max_loops && world.time >= starttime + mid_length * max_loops)
|
||||
@@ -73,21 +81,15 @@
|
||||
return
|
||||
if(!chance || prob(chance))
|
||||
play(get_sound(starttime))
|
||||
if(!timerid)
|
||||
timerid = addtimer(CALLBACK(src, .proc/sound_loop, world.time), mid_length, TIMER_CLIENT_TIME | TIMER_STOPPABLE | TIMER_LOOP)
|
||||
|
||||
/datum/looping_sound/proc/play(soundfile, volume_override)
|
||||
var/list/atoms_cache = output_atoms
|
||||
var/sound/S = sound(soundfile)
|
||||
if(direct)
|
||||
S.channel = SSsounds.random_available_channel()
|
||||
S.volume = volume_override || volume //Use volume as fallback if theres no override
|
||||
for(var/i in 1 to atoms_cache.len)
|
||||
var/atom/thing = atoms_cache[i]
|
||||
if(direct)
|
||||
SEND_SOUND(thing, S)
|
||||
else
|
||||
playsound(thing, S, volume, vary, extra_range, falloff_exponent = falloff_exponent, falloff_distance = falloff_distance)
|
||||
SEND_SOUND(parent, S)
|
||||
else
|
||||
playsound(parent, S, volume, vary, extra_range, falloff_exponent = falloff_exponent, falloff_distance = falloff_distance)
|
||||
|
||||
/datum/looping_sound/proc/get_sound(starttime, _mid_sounds)
|
||||
. = _mid_sounds || mid_sounds
|
||||
@@ -96,11 +98,22 @@
|
||||
|
||||
/datum/looping_sound/proc/on_start()
|
||||
var/start_wait = 0
|
||||
if(start_sound)
|
||||
if(start_sound && !skip_starting_sounds)
|
||||
play(start_sound, start_volume)
|
||||
start_wait = start_length
|
||||
addtimer(CALLBACK(src, .proc/sound_loop), start_wait, TIMER_CLIENT_TIME)
|
||||
timerid = addtimer(CALLBACK(src, .proc/start_sound_loop), start_wait, TIMER_CLIENT_TIME | TIMER_DELETE_ME | TIMER_STOPPABLE, SSsound_loops)
|
||||
|
||||
/datum/looping_sound/proc/on_stop()
|
||||
if(end_sound)
|
||||
if(end_sound && loop_started)
|
||||
play(end_sound, end_volume)
|
||||
|
||||
/datum/looping_sound/proc/set_parent(new_parent)
|
||||
if(parent)
|
||||
UnregisterSignal(parent, COMSIG_PARENT_QDELETING)
|
||||
parent = new_parent
|
||||
if(parent)
|
||||
RegisterSignal(parent, COMSIG_PARENT_QDELETING, .proc/handle_parent_del)
|
||||
|
||||
/datum/looping_sound/proc/handle_parent_del(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
set_parent(null)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user