diff --git a/code/__DEFINES/_bitfields.dm b/code/__DEFINES/_bitfields.dm new file mode 100644 index 000000000000..19a962fbffe5 --- /dev/null +++ b/code/__DEFINES/_bitfields.dm @@ -0,0 +1,4 @@ +#define DEFINE_BITFIELD(_variable, _flags) /datum/bitfield/##_variable { \ + flags = ##_flags; \ + variable = #_variable; \ +} diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm index 88a29ec697a4..63a366ea1aea 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm @@ -19,6 +19,14 @@ #define COMSIG_ATOM_SET_LIGHT_COLOR "atom_set_light_color" ///Called right after the atom changes the value of light_color to a different one, from base of [/atom/proc/set_light_color]: (old_color) #define COMSIG_ATOM_UPDATE_LIGHT_COLOR "atom_update_light_color" +///Called right before the atom changes the value of light_angle to a different one, from base [atom/proc/set_light_angle]: (new_angle) +#define COMSIG_ATOM_SET_LIGHT_ANGLE "atom_set_light_angle" +///Called right after the atom changes the value of light_angle to a different one, from base of [/atom/proc/set_light_angle]: (old_angle) +#define COMSIG_ATOM_UPDATE_LIGHT_ANGLE "atom_update_light_angle" +///Called right before the atom changes the value of light_dir to a different one, from base [atom/proc/set_light_dir]: (new_dir) +#define COMSIG_ATOM_SET_LIGHT_DIR "atom_set_light_dir" +///Called right after the atom changes the value of light_dir to a different one, from base of [/atom/proc/set_light_dir]: (old_dir) +#define COMSIG_ATOM_UPDATE_LIGHT_DIR "atom_update_light_dir" ///Called right before the atom changes the value of light_on to a different one, from base [atom/proc/set_light_on]: (new_value) #define COMSIG_ATOM_SET_LIGHT_ON "atom_set_light_on" ///Called right after the atom changes the value of light_on to a different one, from base of [/atom/proc/set_light_on]: (old_value) diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm index 720e132aa190..2ef0297bd972 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm @@ -77,14 +77,6 @@ #define COMSIG_MOVABLE_SET_ANCHORED "movable_set_anchored" ///from base of atom/movable/setGrabState(): (newstate) #define COMSIG_MOVABLE_SET_GRAB_STATE "living_set_grab_state" -///Called when the movable tries to change its dynamic light color setting, from base atom/movable/lighting_overlay_set_color(): (color) -#define COMSIG_MOVABLE_LIGHT_OVERLAY_SET_RANGE "movable_light_overlay_set_color" -///Called when the movable tries to change its dynamic light power setting, from base atom/movable/lighting_overlay_set_power(): (power) -#define COMSIG_MOVABLE_LIGHT_OVERLAY_SET_POWER "movable_light_overlay_set_power" -///Called when the movable tries to change its dynamic light range setting, from base atom/movable/lighting_overlay_set_range(): (range) -#define COMSIG_MOVABLE_LIGHT_OVERLAY_SET_COLOR "movable_light_overlay_set_range" -///Called when the movable tries to toggle its dynamic light LIGHTING_ON status, from base atom/movable/lighting_overlay_toggle_on(): (new_state) -#define COMSIG_MOVABLE_LIGHT_OVERLAY_TOGGLE_ON "movable_light_overlay_toggle_on" ///called when the movable's glide size is updated: (new_glide_size) #define COMSIG_MOVABLE_UPDATE_GLIDE_SIZE "movable_glide_size" ///Called when a movable is hit by a plunger in layer mode, from /obj/item/plunger/attack_atom() diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index b01ac0fc1552..92c389063f8a 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -4,6 +4,10 @@ #define ALL (~0) //For convenience. #define NONE 0 +/* Directions */ +///All the cardinal direction bitflags. +#define ALL_CARDINALS (NORTH|SOUTH|EAST|WEST) + //for convenience #define ENABLE_BITFIELD(variable, flag) (variable |= (flag)) #define DISABLE_BITFIELD(variable, flag) (variable &= ~(flag)) @@ -99,18 +103,18 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 the atom/checkpass() proc uses them (tables will call movable atom checkpass(PASSTABLE) for example) */ //flags for pass_flags -#define PASSTABLE (1<<0) -#define PASSGLASS (1<<1) -#define PASSGRILLE (1<<2) -#define PASSBLOB (1<<3) -#define PASSMOB (1<<4) -#define PASSCLOSEDTURF (1<<5) -#define LETPASSTHROW (1<<6) -#define PASSMACHINES (1<<7) -#define PASSCOMPUTER (1<<8) -#define PASSSTRUCTURE (1<<9) -#define PASSDOORS (1<<10) -#define PASSMECH (1<<11) +#define PASSTABLE (1<<0) +#define PASSGLASS (1<<1) +#define PASSGRILLE (1<<2) +#define PASSBLOB (1<<3) +#define PASSMOB (1<<4) +#define PASSCLOSEDTURF (1<<5) +#define LETPASSTHROW (1<<6) +#define PASSMACHINES (1<<7) +#define PASSCOMPUTER (1<<8) +#define PASSSTRUCTURE (1<<9) +#define PASSDOOR (1<<10) +#define PASSMECH (1<<11) //Movement Types #define GROUND (1<<0) diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index 18f3e09c7a6c..57271b6bcdee 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -4,12 +4,17 @@ #define STATIC_LIGHT 1 ///Light made by masking the lighting darkness plane. #define MOVABLE_LIGHT 2 +/// Light made by masking the lighting darkness plane, and is directional. +#define MOVABLE_LIGHT_DIRECTIONAL 3 +///Light made by masking the lighting darkness plane, and is a directionally focused beam. +#define MOVABLE_LIGHT_BEAM 4 + +#define NONSENSICAL_VALUE -99999 ///Is a movable light source attached to another movable (its loc), meaning that the lighting component should go one level deeper. #define LIGHT_ATTACHED (1<<0) - -///This light doesn't affect turf's lumcount calculations. Set to 1<<15 to ignore conflicts -#define LIGHT_NO_LUMCOUNT (1<<15) +/// Freezes a light in its current state, blocking any attempts at modification +#define LIGHT_FROZEN (1<<1) //Bay lighting engine shit, not in /code/modules/lighting because BYOND is being shit about it /// frequency, in 1/10ths of a second, of the lighting process @@ -67,6 +72,7 @@ #define DYNAMIC_LIGHTING_FORCED 2 /// dynamic lighting enabled only if starlight is. #define DYNAMIC_LIGHTING_IFSTARLIGHT 3 + #define IS_DYNAMIC_LIGHTING(A) A.dynamic_lighting diff --git a/code/__DEFINES/magic.dm b/code/__DEFINES/magic.dm index 7eeae378337c..34ec4b6659b6 100644 --- a/code/__DEFINES/magic.dm +++ b/code/__DEFINES/magic.dm @@ -64,7 +64,7 @@ /// (effectively making the invocation flavor, instead of required). #define SPELL_CASTABLE_WITHOUT_INVOCATION (1 << 8) -/*DEFINE_BITFIELD(spell_requirements, list( +DEFINE_BITFIELD(spell_requirements, list( "SPELL_CASTABLE_AS_BRAIN" = SPELL_CASTABLE_AS_BRAIN, "SPELL_CASTABLE_WHILE_PHASED" = SPELL_CASTABLE_WHILE_PHASED, "SPELL_CASTABLE_WITHOUT_INVOCATION" = SPELL_CASTABLE_WITHOUT_INVOCATION, @@ -74,7 +74,7 @@ "SPELL_REQUIRES_NO_ANTIMAGIC" = SPELL_REQUIRES_NO_ANTIMAGIC, "SPELL_REQUIRES_STATION" = SPELL_REQUIRES_STATION, "SPELL_REQUIRES_WIZARD_GARB" = SPELL_REQUIRES_WIZARD_GARB, -))*/ +)) // Bitflags for teleport spells /// Whether the teleport spell skips over space turfs @@ -92,11 +92,11 @@ /// Holy magic resistance that blocks unholy magic (revenant, vampire, voice of god) #define MAGIC_RESISTANCE_HOLY (1<<2) -/*DEFINE_BITFIELD(antimagic_flags, list( +DEFINE_BITFIELD(antimagic_flags, list( "MAGIC_RESISTANCE" = MAGIC_RESISTANCE, "MAGIC_RESISTANCE_HOLY" = MAGIC_RESISTANCE_HOLY, "MAGIC_RESISTANCE_MIND" = MAGIC_RESISTANCE_MIND, -))*/ +)) /** * Checks if our mob is jaunting actively (within a phased mob object) diff --git a/code/__DEFINES/turfs.dm b/code/__DEFINES/turfs.dm index 25d4c40b9d38..549af806ee03 100644 --- a/code/__DEFINES/turfs.dm +++ b/code/__DEFINES/turfs.dm @@ -8,3 +8,5 @@ ///Returns all currently loaded turfs #define ALL_TURFS(...) block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz)) + +#define IS_OPAQUE_TURF(turf) (turf.directional_opacity == ALL_CARDINALS) diff --git a/code/__DEFINES/{yogs_defines}/flags.dm b/code/__DEFINES/{yogs_defines}/flags.dm deleted file mode 100644 index 1dd763fe00b1..000000000000 --- a/code/__DEFINES/{yogs_defines}/flags.dm +++ /dev/null @@ -1,2 +0,0 @@ -//pass_flags -#define PASSDOOR (1<<13) \ No newline at end of file diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index e33a3bdd893c..cc774bb2b446 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -322,7 +322,7 @@ Y1+=s while(Y1!=Y2) T=locate(X1,Y1,Z) - if(T.opacity) + if(IS_OPAQUE_TURF(T)) return 0 Y1+=s else @@ -338,7 +338,7 @@ else X1+=signX //Line exits tile horizontally T=locate(X1,Y1,Z) - if(T.opacity) + if(IS_OPAQUE_TURF(T)) return 0 return 1 #undef SIGNV diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 38aef9e817b7..74ec550f4a37 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -492,17 +492,13 @@ Turf and target are separate in case you want to teleport some distance from a t current = get_step_towards(current, target_turf) while(current != target_turf) if(steps > length) - return 0 - if(current.opacity) - return 0 - for(var/thing in current) - var/atom/A = thing - if(A.opacity) - return 0 + return FALSE + if(IS_OPAQUE_TURF(current)) + return FALSE current = get_step_towards(current, target_turf) steps++ - return 1 + return TRUE /proc/is_anchored_dense_turf(turf/T) //like the older version of the above, fails only if also anchored if(T.density) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index b77ed18af259..2123f6a32d20 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -1,204 +1,237 @@ -GLOBAL_LIST_INIT(bitfields, list( - "appearance_flags" = list( - "LONG_GLIDE" = LONG_GLIDE, - "RESET_COLOR" = RESET_COLOR, - "RESET_ALPHA" = RESET_ALPHA, - "RESET_TRANSFORM" = RESET_TRANSFORM, - "NO_CLIENT_COLOR" = NO_CLIENT_COLOR, - "KEEP_TOGETHER" = KEEP_TOGETHER, - "KEEP_APART" = KEEP_APART, - "PLANE_MASTER" = PLANE_MASTER, - "TILE_BOUND" = TILE_BOUND, - "PIXEL_SCALE" = PIXEL_SCALE - ), - "sight" = list( - "SEE_INFRA" = SEE_INFRA, - "SEE_SELF" = SEE_SELF, - "SEE_MOBS" = SEE_MOBS, - "SEE_OBJS" = SEE_OBJS, - "SEE_TURFS" = SEE_TURFS, - "SEE_PIXELS" = SEE_PIXELS, - "SEE_THRU" = SEE_THRU, - "SEE_BLACKNESS" = SEE_BLACKNESS, - "BLIND" = BLIND - ), - "obj_flags" = list( - "EMAGGED" = EMAGGED, - "IN_USE" = IN_USE, - "CAN_BE_HIT" = CAN_BE_HIT, - "BEING_SHOCKED" = BEING_SHOCKED, - "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION, - "ON_BLUEPRINTS" = ON_BLUEPRINTS, - "UNIQUE_RENAME" = UNIQUE_RENAME, - "USES_TGUI" = USES_TGUI, - "FROZEN" = FROZEN, - "UNIQUE_REDESC" = UNIQUE_REDESC, - "CMAGGED" = CMAGGED, - ), - "datum_flags" = list( - "DF_USE_TAG" = DF_USE_TAG, - "DF_VAR_EDITED" = DF_VAR_EDITED, - "DF_ISPROCESSING" = DF_ISPROCESSING, - ), - "item_flags" = list( - "BEING_REMOVED" = BEING_REMOVED, - "IN_INVENTORY" = IN_INVENTORY, - "FORCE_STRING_OVERRIDE" = FORCE_STRING_OVERRIDE, - "HAND_ITEM" = HAND_ITEM, - "NEEDS_PERMIT" = NEEDS_PERMIT, - "SLOWS_WHILE_IN_HAND" = SLOWS_WHILE_IN_HAND, - "NO_MAT_REDEMPTION" = NO_MAT_REDEMPTION, - "DROPDEL" = DROPDEL, - "NOBLUDGEON" = NOBLUDGEON, - "ABSTRACT" = ABSTRACT, - "IN_STORAGE" = IN_STORAGE, - "UNCATCHABLE" = UNCATCHABLE, - "MEDRESIST" = MEDRESIST, - ), - "admin_flags" = list( - "BUILDMODE" = R_BUILDMODE, - "ADMIN" = R_ADMIN, - "BAN" = R_BAN, - "FUN" = R_FUN, - "SERVER" = R_SERVER, - "DEBUG" = R_DEBUG, - "POSSESS" = R_POSSESS, - "PERMISSIONS" = R_PERMISSIONS, - "STEALTH" = R_STEALTH, - "POLL" = R_POLL, - "VAREDIT" = R_VAREDIT, - "SOUNDS" = R_SOUNDS, - "SPAWN" = R_SPAWN, - "AUTOLOGIN" = R_AUTOLOGIN, - "DEV" = R_DEV, - "PERSISTPERMS" = R_PERSIST_PERMS - ), - "interaction_flags_atom" = list( - "INTERACT_ATOM_REQUIRES_ANCHORED" = INTERACT_ATOM_REQUIRES_ANCHORED, - "INTERACT_ATOM_ATTACK_HAND" = INTERACT_ATOM_ATTACK_HAND, - "INTERACT_ATOM_UI_INTERACT" = INTERACT_ATOM_UI_INTERACT, - "INTERACT_ATOM_REQUIRES_DEXTERITY" = INTERACT_ATOM_REQUIRES_DEXTERITY, - "INTERACT_ATOM_IGNORE_INCAPACITATED" = INTERACT_ATOM_IGNORE_INCAPACITATED, - "INTERACT_ATOM_IGNORE_RESTRAINED" = INTERACT_ATOM_IGNORE_RESTRAINED, - "INTERACT_ATOM_CHECK_GRAB" = INTERACT_ATOM_CHECK_GRAB, - "INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND" = INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND, - "INTERACT_ATOM_NO_FINGERPRINT_INTERACT" = INTERACT_ATOM_NO_FINGERPRINT_INTERACT - ), - "interaction_flags_machine" = list( - "INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN, - "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE, - "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN, - "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON, - "INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON, - "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON, - "INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE - ), - "interaction_flags_item" = list( - "INTERACT_ITEM_ATTACK_HAND_PICKUP" = INTERACT_ITEM_ATTACK_HAND_PICKUP, - ), - "pass_flags" = list( - "PASSTABLE" = PASSTABLE, - "PASSGLASS" = PASSGLASS, - "PASSGRILLE" = PASSGRILLE, - "PASSBLOB" = PASSBLOB, - "PASSMOB" = PASSMOB, - "PASSCLOSEDTURF" = PASSCLOSEDTURF, - "LETPASSTHROW" = LETPASSTHROW, - "PASSDOOR" = PASSDOOR, //yogs - "PASSMACHINES" = PASSMACHINES, - "PASSCOMPUTER" = PASSCOMPUTER, - "PASSSTRUCTURE" = PASSSTRUCTURE - ), - "movement_type" = list( - "GROUND" = GROUND, - "FLYING" = FLYING, - "VENTCRAWLING" = VENTCRAWLING, - "FLOATING" = FLOATING, - "UNSTOPPABLE" = UNSTOPPABLE - ), - "resistance_flags" = list( - "LAVA_PROOF" = LAVA_PROOF, - "FIRE_PROOF" = FIRE_PROOF, - "FLAMMABLE" = FLAMMABLE, - "ON_FIRE" = ON_FIRE, - "UNACIDABLE" = UNACIDABLE, - "ACID_PROOF" = ACID_PROOF, - "INDESTRUCTIBLE" = INDESTRUCTIBLE, - "FREEZE_PROOF" = FREEZE_PROOF - ), - "flags_1" = list( - "NOJAUNT_1" = NOJAUNT_1, - "UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1, - "CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1, - "HEAR_1" = HEAR_1, - "CHECK_RICOCHET_1" = CHECK_RICOCHET_1, - "CONDUCT_1" = CONDUCT_1, - "NO_LAVA_GEN_1" = NO_LAVA_GEN_1, - "NODECONSTRUCT_1" = NODECONSTRUCT_1, - "ON_BORDER_1" = ON_BORDER_1, - "NO_RUINS_1" = NO_RUINS_1, - "NO_RUST" = NO_RUST, - "PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1, - "HOLOGRAM_1" = HOLOGRAM_1, - "TESLA_IGNORE_1" = TESLA_IGNORE_1, - "INITIALIZED_1" = INITIALIZED_1, - "ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1, - "PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1, - "RAD_PROTECT_CONTENTS_1" = RAD_PROTECT_CONTENTS_1, - "RAD_NO_CONTAMINATE_1" = RAD_NO_CONTAMINATE_1, - "IS_SPINNING_1" = IS_SPINNING_1, - ), - "clothing_flags" = list( - "LAVAPROTECT" = LAVAPROTECT, - "STOPSHIGHPRESSURE" = STOPSHIGHPRESSURE, - "STOPSLOWPRESSURE" = STOPSLOWPRESSURE, - "BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT, - "MASKINTERNALS" = MASKINTERNALS, - "NOSLIP" = NOSLIP, - "THICKMATERIAL" = THICKMATERIAL, - "VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE, - "VOICEBOX_DISABLED" = VOICEBOX_DISABLED, - "SCAN_REAGENTS" = SCAN_REAGENTS, - ), - "tesla_flags" = list( - "TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE, - "TESLA_OBJ_DAMAGE" = TESLA_OBJ_DAMAGE, - "TESLA_MOB_STUN" = TESLA_MOB_STUN, - "TESLA_ALLOW_DUPLICATES" = TESLA_ALLOW_DUPLICATES, - "TESLA_MACHINE_EXPLOSIVE" = TESLA_MACHINE_EXPLOSIVE, - ), - "smooth" = list( - "SMOOTH_TRUE" = SMOOTH_TRUE, - "SMOOTH_MORE" = SMOOTH_MORE, - "SMOOTH_DIAGONAL" = SMOOTH_DIAGONAL, - "SMOOTH_BORDER" = SMOOTH_BORDER, - "SMOOTH_QUEUED" = SMOOTH_QUEUED, - ), - "car_traits" = list( - "CAN_KIDNAP" = CAN_KIDNAP, - ), - "mobility_flags" = list( - "MOVE" = MOBILITY_MOVE, - "STAND" = MOBILITY_STAND, - "PICKUP" = MOBILITY_PICKUP, - "USE" = MOBILITY_USE, - "UI" = MOBILITY_UI, - "STORAGE" = MOBILITY_STORAGE, - "PULL" = MOBILITY_PULL, - ), - "disease_flags" = list ( - "CURABLE" = CURABLE, - "CAN_CARRY" = CAN_CARRY, - "CAN_RESIST" = CAN_RESIST - ), - "vis_flags" = list( - "VIS_INHERIT_ICON" = VIS_INHERIT_ICON, - "VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE, - "VIS_INHERIT_DIR" = VIS_INHERIT_DIR, - "VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER, - "VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE, - "VIS_INHERIT_ID" = VIS_INHERIT_ID, - "VIS_UNDERLAY" = VIS_UNDERLAY, - "VIS_HIDE" = VIS_HIDE - ) - )) +GLOBAL_LIST_INIT(bitfields, generate_bitfields()) + +/// Specifies a bitfield for smarter debugging +/datum/bitfield + /// The variable name that contains the bitfield + var/variable + + /// An associative list of the readable flag and its true value + var/list/flags + +/// Turns /datum/bitfield subtypes into a list for use in debugging +/proc/generate_bitfields() + var/list/bitfields = list() + for (var/_bitfield in subtypesof(/datum/bitfield)) + var/datum/bitfield/bitfield = new _bitfield + bitfields[bitfield.variable] = bitfield.flags + return bitfields + +DEFINE_BITFIELD(appearance_flags, list( + "LONG_GLIDE" = LONG_GLIDE, + "RESET_COLOR" = RESET_COLOR, + "RESET_ALPHA" = RESET_ALPHA, + "RESET_TRANSFORM" = RESET_TRANSFORM, + "NO_CLIENT_COLOR" = NO_CLIENT_COLOR, + "KEEP_TOGETHER" = KEEP_TOGETHER, + "KEEP_APART" = KEEP_APART, + "PLANE_MASTER" = PLANE_MASTER, + "TILE_BOUND" = TILE_BOUND, + "PIXEL_SCALE" = PIXEL_SCALE, +)) + +DEFINE_BITFIELD(sight, list( + "SEE_INFRA" = SEE_INFRA, + "SEE_SELF" = SEE_SELF, + "SEE_MOBS" = SEE_MOBS, + "SEE_OBJS" = SEE_OBJS, + "SEE_TURFS" = SEE_TURFS, + "SEE_PIXELS" = SEE_PIXELS, + "SEE_THRU" = SEE_THRU, + "SEE_BLACKNESS" = SEE_BLACKNESS, + "BLIND" = BLIND, +)) + +DEFINE_BITFIELD(obj_flags, list( + "EMAGGED" = EMAGGED, + "IN_USE" = IN_USE, + "CAN_BE_HIT" = CAN_BE_HIT, + "BEING_SHOCKED" = BEING_SHOCKED, + "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION, + "ON_BLUEPRINTS" = ON_BLUEPRINTS, + "UNIQUE_RENAME" = UNIQUE_RENAME, + "USES_TGUI" = USES_TGUI, + "FROZEN" = FROZEN, + "UNIQUE_REDESC" = UNIQUE_REDESC, + "CMAGGED" = CMAGGED, +)) + +DEFINE_BITFIELD(datum_flags, list( + "DF_USE_TAG" = DF_USE_TAG, + "DF_VAR_EDITED" = DF_VAR_EDITED, + "DF_ISPROCESSING" = DF_ISPROCESSING, +)) + +DEFINE_BITFIELD(item_flags, list( + "BEING_REMOVED" = BEING_REMOVED, + "IN_INVENTORY" = IN_INVENTORY, + "FORCE_STRING_OVERRIDE" = FORCE_STRING_OVERRIDE, + "HAND_ITEM" = HAND_ITEM, + "NEEDS_PERMIT" = NEEDS_PERMIT, + "SLOWS_WHILE_IN_HAND" = SLOWS_WHILE_IN_HAND, + "NO_MAT_REDEMPTION" = NO_MAT_REDEMPTION, + "DROPDEL" = DROPDEL, + "NOBLUDGEON" = NOBLUDGEON, + "ABSTRACT" = ABSTRACT, + "IN_STORAGE" = IN_STORAGE, + "UNCATCHABLE" = UNCATCHABLE, + "MEDRESIST" = MEDRESIST, +)) + +DEFINE_BITFIELD(admin_flags, list( + "BUILDMODE" = R_BUILDMODE, + "ADMIN" = R_ADMIN, + "BAN" = R_BAN, + "FUN" = R_FUN, + "SERVER" = R_SERVER, + "DEBUG" = R_DEBUG, + "POSSESS" = R_POSSESS, + "PERMISSIONS" = R_PERMISSIONS, + "STEALTH" = R_STEALTH, + "POLL" = R_POLL, + "VAREDIT" = R_VAREDIT, + "SOUNDS" = R_SOUNDS, + "SPAWN" = R_SPAWN, + "AUTOLOGIN" = R_AUTOLOGIN, + "DEV" = R_DEV, + "PERSISTPERMS" = R_PERSIST_PERMS, +)) + +DEFINE_BITFIELD(interaction_flags_atom, list( + "INTERACT_ATOM_REQUIRES_ANCHORED" = INTERACT_ATOM_REQUIRES_ANCHORED, + "INTERACT_ATOM_ATTACK_HAND" = INTERACT_ATOM_ATTACK_HAND, + "INTERACT_ATOM_UI_INTERACT" = INTERACT_ATOM_UI_INTERACT, + "INTERACT_ATOM_REQUIRES_DEXTERITY" = INTERACT_ATOM_REQUIRES_DEXTERITY, + "INTERACT_ATOM_IGNORE_INCAPACITATED" = INTERACT_ATOM_IGNORE_INCAPACITATED, + "INTERACT_ATOM_IGNORE_RESTRAINED" = INTERACT_ATOM_IGNORE_RESTRAINED, + "INTERACT_ATOM_CHECK_GRAB" = INTERACT_ATOM_CHECK_GRAB, + "INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND" = INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND, + "INTERACT_ATOM_NO_FINGERPRINT_INTERACT" = INTERACT_ATOM_NO_FINGERPRINT_INTERACT, +)) + +DEFINE_BITFIELD(interaction_flags_machine, list( + "INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN, + "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE, + "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN, + "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON, + "INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON, + "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON, + "INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE, +)) + +DEFINE_BITFIELD(interaction_flags_item, list( + "INTERACT_ITEM_ATTACK_HAND_PICKUP" = INTERACT_ITEM_ATTACK_HAND_PICKUP, +)) + +DEFINE_BITFIELD(pass_flags, list( + "PASSTABLE" = PASSTABLE, + "PASSGLASS" = PASSGLASS, + "PASSGRILLE" = PASSGRILLE, + "PASSBLOB" = PASSBLOB, + "PASSMOB" = PASSMOB, + "PASSCLOSEDTURF" = PASSCLOSEDTURF, + "LETPASSTHROW" = LETPASSTHROW, + "PASSDOOR" = PASSDOOR, + "PASSMACHINES" = PASSMACHINES, + "PASSCOMPUTER" = PASSCOMPUTER, + "PASSSTRUCTURE" = PASSSTRUCTURE, +)) + +DEFINE_BITFIELD(movement_type, list( + "GROUND" = GROUND, + "FLYING" = FLYING, + "VENTCRAWLING" = VENTCRAWLING, + "FLOATING" = FLOATING, + "UNSTOPPABLE" = UNSTOPPABLE, +)) + +DEFINE_BITFIELD(resistance_flags, list( + "LAVA_PROOF" = LAVA_PROOF, + "FIRE_PROOF" = FIRE_PROOF, + "FLAMMABLE" = FLAMMABLE, + "ON_FIRE" = ON_FIRE, + "UNACIDABLE" = UNACIDABLE, + "ACID_PROOF" = ACID_PROOF, + "INDESTRUCTIBLE" = INDESTRUCTIBLE, + "FREEZE_PROOF" = FREEZE_PROOF, +)) + +DEFINE_BITFIELD(flags_1, list( + "NOJAUNT_1" = NOJAUNT_1, + "UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1, + "CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1, + "HEAR_1" = HEAR_1, + "CHECK_RICOCHET_1" = CHECK_RICOCHET_1, + "CONDUCT_1" = CONDUCT_1, + "NO_LAVA_GEN_1" = NO_LAVA_GEN_1, + "NODECONSTRUCT_1" = NODECONSTRUCT_1, + "ON_BORDER_1" = ON_BORDER_1, + "NO_RUINS_1" = NO_RUINS_1, + "PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1, + "HOLOGRAM_1" = HOLOGRAM_1, + "TESLA_IGNORE_1" = TESLA_IGNORE_1, + "INITIALIZED_1" = INITIALIZED_1, + "ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1, + "PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1, + "RAD_PROTECT_CONTENTS_1" = RAD_PROTECT_CONTENTS_1, + "RAD_NO_CONTAMINATE_1" = RAD_NO_CONTAMINATE_1, + "IS_SPINNING_1" = IS_SPINNING_1, +)) + +DEFINE_BITFIELD(clothing_flags, list( + "LAVAPROTECT" = LAVAPROTECT, + "STOPSHIGHPRESSURE" = STOPSHIGHPRESSURE, + "STOPSLOWPRESSURE" = STOPSLOWPRESSURE, + "BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT, + "MASKINTERNALS" = MASKINTERNALS, + "NOSLIP" = NOSLIP, + "THICKMATERIAL" = THICKMATERIAL, + "VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE, + "VOICEBOX_DISABLED" = VOICEBOX_DISABLED, + "SCAN_REAGENTS" = SCAN_REAGENTS, +)) + +DEFINE_BITFIELD(tesla_flags, list( + "TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE, + "TESLA_OBJ_DAMAGE" = TESLA_OBJ_DAMAGE, + "TESLA_MOB_STUN" = TESLA_MOB_STUN, + "TESLA_ALLOW_DUPLICATES" = TESLA_ALLOW_DUPLICATES, + "TESLA_MACHINE_EXPLOSIVE" = TESLA_MACHINE_EXPLOSIVE, +)) + +DEFINE_BITFIELD(smooth, list( + "SMOOTH_TRUE" = SMOOTH_TRUE, + "SMOOTH_MORE" = SMOOTH_MORE, + "SMOOTH_DIAGONAL" = SMOOTH_DIAGONAL, + "SMOOTH_BORDER" = SMOOTH_BORDER, + "SMOOTH_QUEUED" = SMOOTH_QUEUED, +)) + +DEFINE_BITFIELD(car_traits, list( + "CAN_KIDNAP" = CAN_KIDNAP, +)) + +DEFINE_BITFIELD(mobility_flags, list( + "MOVE" = MOBILITY_MOVE, + "STAND" = MOBILITY_STAND, + "PICKUP" = MOBILITY_PICKUP, + "USE" = MOBILITY_USE, + "UI" = MOBILITY_UI, + "STORAGE" = MOBILITY_STORAGE, + "PULL" = MOBILITY_PULL, +)) + +DEFINE_BITFIELD(disease_flags, list( + "CURABLE" = CURABLE, + "CAN_CARRY" = CAN_CARRY, + "CAN_RESIST" = CAN_RESIST, +)) +DEFINE_BITFIELD(vis_flags, list( + "VIS_INHERIT_ICON" = VIS_INHERIT_ICON, + "VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE, + "VIS_INHERIT_DIR" = VIS_INHERIT_DIR, + "VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER, + "VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE, + "VIS_INHERIT_ID" = VIS_INHERIT_ID, + "VIS_UNDERLAY" = VIS_UNDERLAY, + "VIS_HIDE" = VIS_HIDE, +)) diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 8e606d35cfee..1162314ce15a 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -1,7 +1,4 @@ -/mob - var/list/screens = list() - /mob/proc/overlay_fullscreen(category, type, severity) var/atom/movable/screen/fullscreen/screen = screens[category] if (!screen || screen.type != type) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index e4097274e1d9..f60a5fa86cdc 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -127,9 +127,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list( return ..() -/mob - var/hud_type = /datum/hud - /mob/proc/create_mob_hud() if(!client || hud_used) return diff --git a/code/controllers/subsystem/vis_overlays.dm b/code/controllers/subsystem/vis_overlays.dm index d8b70abb3688..1afe1c62100c 100644 --- a/code/controllers/subsystem/vis_overlays.dm +++ b/code/controllers/subsystem/vis_overlays.dm @@ -3,12 +3,14 @@ SUBSYSTEM_DEF(vis_overlays) wait = 1 MINUTES priority = FIRE_PRIORITY_VIS init_order = INIT_ORDER_VIS - flags = SS_NO_INIT - var/list/vis_overlay_cache = list() - var/list/unique_vis_overlays = list() + var/list/vis_overlay_cache var/list/currentrun +/datum/controller/subsystem/vis_overlays/Initialize() + vis_overlay_cache = list() + return SS_INIT_SUCCESS + /datum/controller/subsystem/vis_overlays/fire(resumed = FALSE) if(!resumed) currentrun = vis_overlay_cache.Copy() @@ -26,7 +28,7 @@ SUBSYSTEM_DEF(vis_overlays) if(MC_TICK_CHECK) return -//the "thing" var can be anything with vis_contents which includes images +//the "thing" var can be anything with vis_contents which includes images - in the future someone should totally allow vis overlays to be passed in as an arg instead of all this bullshit /datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha = 255, add_appearance_flags = NONE, unique = FALSE) var/obj/effect/overlay/vis/overlay if(!unique) @@ -40,20 +42,19 @@ SUBSYSTEM_DEF(vis_overlays) else overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) overlay.cache_expiration = -1 - var/cache_id = "\ref[overlay]@{[world.time]}" - unique_vis_overlays += overlay + var/cache_id = "[text_ref(overlay)]@{[world.time]}" vis_overlay_cache[cache_id] = overlay . = overlay thing.vis_contents += overlay if(!isatom(thing)) // Automatic rotation is not supported on non atoms - return + return overlay if(!thing.managed_vis_overlays) thing.managed_vis_overlays = list(overlay) - RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, PROC_REF(rotate_vis_overlay)) else thing.managed_vis_overlays += overlay + return overlay /datum/controller/subsystem/vis_overlays/proc/_create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) var/obj/effect/overlay/vis/overlay = new @@ -74,20 +75,3 @@ SUBSYSTEM_DEF(vis_overlays) thing.managed_vis_overlays -= overlays if(!length(thing.managed_vis_overlays)) thing.managed_vis_overlays = null - UnregisterSignal(thing, COMSIG_ATOM_DIR_CHANGE) - -/datum/controller/subsystem/vis_overlays/proc/rotate_vis_overlay(atom/thing, old_dir, new_dir) - if(old_dir == new_dir) - return - var/rotation = dir2angle(old_dir) - dir2angle(new_dir) - var/list/overlays_to_remove = list() - for(var/i in thing.managed_vis_overlays - unique_vis_overlays) - var/obj/effect/overlay/vis/overlay = i - if(!overlay) - continue - add_vis_overlay(thing, overlay.icon, overlay.icon_state, overlay.layer, overlay.plane, turn(overlay.dir, rotation), overlay.alpha, overlay.appearance_flags) - overlays_to_remove += overlay - for(var/i in thing.managed_vis_overlays & unique_vis_overlays) - var/obj/effect/overlay/vis/overlay = i - overlay.dir = turn(overlay.dir, rotation) - remove_vis_overlay(thing, overlays_to_remove) diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm index 8f91f254b1d9..4309808910eb 100644 --- a/code/datums/components/overlay_lighting.dm +++ b/code/datums/components/overlay_lighting.dm @@ -5,21 +5,23 @@ #define GET_PARENT (parent_attached_to || parent) +#define SHORT_CAST 2 + /** - * Movable atom overlay-based lighting component. - * - * * Component works by applying a visual object to the parent target. - * - * * The component tracks the parent's loc to determine the current_holder. - * * The current_holder is either the parent or its loc, whichever is on a turf. If none, then the current_holder is null and the light is not visible. - * - * * Lighting works at its base by applying a dark overlay and "cutting" said darkness with light, adding (possibly colored) transparency. - * * This component uses the visible_mask visual object to apply said light mask on the darkness. - * - * * The main limitation of this system is that it uses a limited number of pre-baked geometrical shapes, but for most uses it does the job. - * - * * Another limitation is for big lights: you only see the light if you see the object emiting it. - * * For small objects this is good (you can't see them behind a wall), but for big ones this quickly becomes prety clumsy. + * Movable atom overlay-based lighting component. + * + * * Component works by applying a visual object to the parent target. + * + * * The component tracks the parent's loc to determine the current_holder. + * * The current_holder is either the parent or its loc, whichever is on a turf. If none, then the current_holder is null and the light is not visible. + * + * * Lighting works at its base by applying a dark overlay and "cutting" said darkness with light, adding (possibly colored) transparency. + * * This component uses the visible_mask visual object to apply said light mask on the darkness. + * + * * The main limitation of this system is that it uses a limited number of pre-baked geometrical shapes, but for most uses it does the job. + * + * * Another limitation is for big lights: you only see the light if you see the object emiting it. + * * For small objects this is good (you can't see them behind a wall), but for big ones this quickly becomes prety clumsy. */ /datum/component/overlay_lighting ///How far the light reaches, float. @@ -27,11 +29,7 @@ ///Ceiling of range, integer without decimal entries. var/lumcount_range = 0 ///How much this light affects the dynamic_lumcount of turfs. - var/real_lum_power = 0.5 - ///The lum power being used - var/used_lum_power = 0.5 - ///Transparency value. - var/set_alpha = 0 + var/lum_power = 0.5 ///For light sources that can be turned on and off. var/overlay_lighting_flags = NONE @@ -58,28 +56,46 @@ var/atom/movable/current_holder ///Movable atom the parent is attached to. For example, a flashlight into a helmet or gun. We'll need to track the thing the parent is attached to as if it were the parent itself. var/atom/movable/parent_attached_to - - -/datum/component/overlay_lighting/Initialize(_range, _power, _color, starts_on) + ///Whether we're a directional light + var/directional = FALSE + ///Whether we're a beam light + var/beam = FALSE + ///A cone overlay for directional light, it's alpha and color are dependant on the light + var/obj/effect/overlay/light_visible/cone/cone + ///Current tracked direction for the directional cast behaviour + var/current_direction + ///Tracks current directional x offset so we dont update unecessarily + var/directional_offset_x + ///Tracks current directional y offset so we dont update unecessarily + var/directional_offset_y + ///Cast range for the directional cast (how far away the atom is moved) + var/cast_range = 2 + +/datum/component/overlay_lighting/Initialize(range, power, color, starts_on, is_directional, is_beam) if(!ismovable(parent)) return COMPONENT_INCOMPATIBLE - var/atom/movable/movable_parent = parent - if(movable_parent.light_system != MOVABLE_LIGHT) - stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT] instead.") + if(movable_parent.light_system != MOVABLE_LIGHT && movable_parent.light_system != MOVABLE_LIGHT_DIRECTIONAL && movable_parent.light_system != MOVABLE_LIGHT_BEAM) + stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT], [MOVABLE_LIGHT_DIRECTIONAL] or [MOVABLE_LIGHT_BEAM] instead.") return COMPONENT_INCOMPATIBLE . = ..() - - visible_mask = new() - if(!isnull(_range)) - movable_parent.set_light_range(_range) + visible_mask = new(src) + if(is_directional) + directional = TRUE + cone = new(src) + cone.transform = cone.transform.Translate(-32, -32) + set_direction(movable_parent.dir) + if(is_beam) + beam = TRUE + if(!isnull(range)) + movable_parent.set_light_range(range) set_range(parent, movable_parent.light_range) - if(!isnull(_power)) - movable_parent.set_light_power(_power) + if(!isnull(power)) + movable_parent.set_light_power(power) set_power(parent, movable_parent.light_power) - if(!isnull(_color)) - movable_parent.set_light_color(_color) + if(!isnull(color)) + movable_parent.set_light_color(color) set_color(parent, movable_parent.light_color) if(!isnull(starts_on)) movable_parent.set_light_on(starts_on) @@ -87,19 +103,20 @@ /datum/component/overlay_lighting/RegisterWithParent() . = ..() + if(directional) + RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_parent_dir_change)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_RANGE, PROC_REF(set_range)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_POWER, PROC_REF(set_power)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_COLOR, PROC_REF(set_color)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_ON, PROC_REF(on_toggle)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_FLAGS, PROC_REF(on_light_flags_change)) + RegisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT, PROC_REF(on_parent_crafted)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_moved)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_RANGE, PROC_REF(set_range)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_POWER, PROC_REF(set_power)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_COLOR, PROC_REF(set_color)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_ON, PROC_REF(on_toggle)) - RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_FLAGS, PROC_REF(on_light_flags_change)) + RegisterSignal(parent, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_z_move)) var/atom/movable/movable_parent = parent if(movable_parent.light_flags & LIGHT_ATTACHED) overlay_lighting_flags |= LIGHTING_ATTACHED set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null) - if(movable_parent.light_flags & LIGHT_NO_LUMCOUNT) - overlay_lighting_flags |= LIGHT_NO_LUMCOUNT - set_lum_power(real_lum_power) check_holder() if(movable_parent.light_on) turn_on() @@ -112,12 +129,16 @@ clean_old_turfs() UnregisterSignal(parent, list( COMSIG_MOVABLE_MOVED, - COMSIG_ATOM_SET_LIGHT_RANGE, - COMSIG_ATOM_SET_LIGHT_POWER, - COMSIG_ATOM_SET_LIGHT_COLOR, - COMSIG_ATOM_SET_LIGHT_ON, - COMSIG_ATOM_SET_LIGHT_FLAGS, + COMSIG_MOVABLE_Z_CHANGED, + COMSIG_ATOM_UPDATE_LIGHT_RANGE, + COMSIG_ATOM_UPDATE_LIGHT_POWER, + COMSIG_ATOM_UPDATE_LIGHT_COLOR, + COMSIG_ATOM_UPDATE_LIGHT_ON, + COMSIG_ATOM_UPDATE_LIGHT_FLAGS, + COMSIG_ATOM_USED_IN_CRAFT, )) + if(directional) + UnregisterSignal(parent, COMSIG_ATOM_DIR_CHANGE) if(overlay_lighting_flags & LIGHTING_ON) turn_off() return ..() @@ -127,14 +148,16 @@ set_parent_attached_to(null) set_holder(null) clean_old_turfs() - QDEL_NULL(visible_mask) + visible_mask = null + cone = null + parent_attached_to = null return ..() ///Clears the affected_turfs lazylist, removing from its contents the effects of being near the light. /datum/component/overlay_lighting/proc/clean_old_turfs() for(var/turf/lit_turf as anything in affected_turfs) - lit_turf.dynamic_lumcount -= used_lum_power + lit_turf.dynamic_lumcount -= lum_power SSdemo.mark_turf(lit_turf) affected_turfs = null @@ -143,8 +166,10 @@ /datum/component/overlay_lighting/proc/get_new_turfs() if(!current_holder) return + . = list() for(var/turf/lit_turf in view(lumcount_range, get_turf(current_holder))) - lit_turf.dynamic_lumcount += used_lum_power + lit_turf.dynamic_lumcount += lum_power + . += lit_turf SSdemo.mark_turf(lit_turf) LAZYADD(affected_turfs, lit_turf) @@ -154,27 +179,32 @@ clean_old_turfs() if(!isturf(current_holder?.loc)) return + if(directional) + cast_directional_light() get_new_turfs() -///Adds the luminosity and source for the afected movable atoms to keep track of their visibility. -/datum/component/overlay_lighting/proc/add_dynamic_lumi(atom/movable/affected_movable) - LAZYSET(affected_movable.affected_dynamic_lights, src, lumcount_range + 1) - affected_movable.vis_contents += visible_mask - affected_movable.update_dynamic_luminosity() - - -///Removes the luminosity and source for the afected movable atoms to keep track of their visibility. -/datum/component/overlay_lighting/proc/remove_dynamic_lumi(atom/movable/affected_movable) - LAZYREMOVE(affected_movable.affected_dynamic_lights, src) - affected_movable.vis_contents -= visible_mask - affected_movable.update_dynamic_luminosity() +///Adds the luminosity and source for the affected movable atoms to keep track of their visibility. +/datum/component/overlay_lighting/proc/add_dynamic_lumi() + LAZYSET(current_holder.affected_dynamic_lights, src, lumcount_range + 1) + current_holder.underlays += visible_mask + current_holder.update_dynamic_luminosity() + if(directional) + current_holder.underlays += cone +///Removes the luminosity and source for the affected movable atoms to keep track of their visibility. +/datum/component/overlay_lighting/proc/remove_dynamic_lumi() + LAZYREMOVE(current_holder.affected_dynamic_lights, src) + current_holder.underlays -= visible_mask + current_holder.update_dynamic_luminosity() + if(directional) + current_holder.underlays -= cone ///Called to change the value of parent_attached_to. /datum/component/overlay_lighting/proc/set_parent_attached_to(atom/movable/new_parent_attached_to) if(new_parent_attached_to == parent_attached_to) return + . = parent_attached_to parent_attached_to = new_parent_attached_to if(.) @@ -198,17 +228,25 @@ if(current_holder) if(current_holder != parent && current_holder != parent_attached_to) UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) + if(directional) + UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE) if(overlay_lighting_flags & LIGHTING_ON) - remove_dynamic_lumi(current_holder) + remove_dynamic_lumi() current_holder = new_holder if(new_holder == null) clean_old_turfs() return - if(overlay_lighting_flags & LIGHTING_ON) - add_dynamic_lumi(new_holder) if(new_holder != parent && new_holder != parent_attached_to) RegisterSignal(new_holder, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel)) - RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) + if(overlay_lighting_flags & LIGHTING_ON) + RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) + if(directional) + RegisterSignal(new_holder, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_holder_dir_change)) + if(directional && current_direction != new_holder.dir) + current_direction = new_holder.dir + if(overlay_lighting_flags & LIGHTING_ON) + add_dynamic_lumi() + make_luminosity_update() ///Used to determine the new valid current_holder from the parent's loc. @@ -229,12 +267,18 @@ ///Called when the current_holder is qdeleted, to remove the light effect. /datum/component/overlay_lighting/proc/on_holder_qdel(atom/movable/source, force) + SIGNAL_HANDLER + if(QDELETED(current_holder)) + return UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) + if(directional) + UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE) set_holder(null) ///Called when current_holder changes loc. /datum/component/overlay_lighting/proc/on_holder_moved(atom/movable/source, OldLoc, Dir, Forced) + SIGNAL_HANDLER if(!(overlay_lighting_flags & LIGHTING_ON)) return make_luminosity_update() @@ -242,6 +286,7 @@ ///Called when parent changes loc. /datum/component/overlay_lighting/proc/on_parent_moved(atom/movable/source, OldLoc, Dir, Forced) + SIGNAL_HANDLER var/atom/movable/movable_parent = parent if(overlay_lighting_flags & LIGHTING_ATTACHED) set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null) @@ -250,10 +295,24 @@ return make_luminosity_update() +/datum/component/overlay_lighting/proc/on_z_move(atom/source) + SIGNAL_HANDLER + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= visible_mask + current_holder.underlays -= cone + visible_mask.plane = O_LIGHTING_VISUAL_PLANE + if(cone) + cone.plane = O_LIGHTING_VISUAL_PLANE + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + current_holder.underlays += cone ///Called when the current_holder is qdeleted, to remove the light effect. /datum/component/overlay_lighting/proc/on_parent_attached_to_qdel(atom/movable/source, force) + SIGNAL_HANDLER UnregisterSignal(parent_attached_to, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) + if(directional) + UnregisterSignal(parent_attached_to, COMSIG_ATOM_DIR_CHANGE) if(parent_attached_to == current_holder) set_holder(null) set_parent_attached_to(null) @@ -261,6 +320,7 @@ ///Called when parent_attached_to changes loc. /datum/component/overlay_lighting/proc/on_parent_attached_to_moved(atom/movable/source, OldLoc, Dir, Forced) + SIGNAL_HANDLER check_holder() if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder) return @@ -268,76 +328,114 @@ ///Changes the range which the light reaches. 0 means no light, 6 is the maximum value. -/datum/component/overlay_lighting/proc/set_range(atom/source, new_range) +/datum/component/overlay_lighting/proc/set_range(atom/source, old_range) + SIGNAL_HANDLER + var/new_range = source.light_range if(range == new_range) return - if(range == 0) + if(new_range == 0) turn_off() range = clamp(CEILING(new_range, 0.5), 1, 6) var/pixel_bounds = ((range - 1) * 64) + 32 lumcount_range = CEILING(range, 1) + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= visible_mask visible_mask.icon = light_overlays["[pixel_bounds]"] if(pixel_bounds == 32) - visible_mask.transform = null - return - var/offset = (pixel_bounds - 32) * 0.5 - var/matrix/transform = new - transform.Translate(-offset, -offset) - visible_mask.transform = transform + if(!directional) // it's important that we make it to the end of this function if we are a directional light + visible_mask.transform = null + return + else + var/offset = (pixel_bounds - 32) * 0.5 + var/matrix/transform = new + transform.Translate(-offset, -offset) + visible_mask.transform = transform + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + if(directional) + if(beam) + cast_range = max(round(new_range * 0.5), 1) + else + cast_range = clamp(round(new_range * 0.5), 1, 3) if(overlay_lighting_flags & LIGHTING_ON) make_luminosity_update() ///Changes the intensity/brightness of the light by altering the visual object's alpha. -/datum/component/overlay_lighting/proc/set_power(atom/source, new_power) - set_lum_power(new_power >= 0 ? 0.5 : -0.5) - set_alpha = min(230, (abs(new_power) * 120) + 30) - visible_mask.alpha = set_alpha +/datum/component/overlay_lighting/proc/set_power(atom/source, old_power) + SIGNAL_HANDLER + var/new_power = source.light_power + set_lum_power(new_power) + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= visible_mask + visible_mask.alpha = min(230, (abs(new_power) * 120) + 30) + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + if(!directional) + return + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= cone + cone.alpha = min(200, (abs(new_power) * 90) + 20) + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += cone ///Changes the light's color, pretty straightforward. -/datum/component/overlay_lighting/proc/set_color(atom/source, new_color) +/datum/component/overlay_lighting/proc/set_color(atom/source, old_color) + SIGNAL_HANDLER + var/new_color = source.light_color + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= visible_mask visible_mask.color = new_color + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + if(!directional) + return + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= cone + cone.color = new_color + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += cone ///Toggles the light on and off. -/datum/component/overlay_lighting/proc/on_toggle(atom/source, new_value) +/datum/component/overlay_lighting/proc/on_toggle(atom/source, old_value) + SIGNAL_HANDLER + var/new_value = source.light_on if(new_value) //Truthy value input, turn on. turn_on() return turn_off() //Falsey value, turn off. -///Triggered right before the parent light flags change. -/datum/component/overlay_lighting/proc/on_light_flags_change(atom/source, new_value) +///Triggered right after the parent light flags change. +/datum/component/overlay_lighting/proc/on_light_flags_change(atom/source, old_flags) + SIGNAL_HANDLER + var/new_flags = source.light_flags var/atom/movable/movable_parent = parent - if(new_value & LIGHT_ATTACHED) - if(!(movable_parent.light_flags & LIGHT_ATTACHED)) //Gained the LIGHT_ATTACHED property. - overlay_lighting_flags |= LIGHTING_ATTACHED - if(ismovable(movable_parent.loc)) - set_parent_attached_to(movable_parent.loc) - else if(movable_parent.light_flags & LIGHT_ATTACHED) //Lost the LIGHT_ATTACHED property. + if(!((new_flags ^ old_flags) & LIGHT_ATTACHED)) + return + + if(new_flags & LIGHT_ATTACHED) // Gained the [LIGHT_ATTACHED] property + overlay_lighting_flags |= LIGHTING_ATTACHED + if(ismovable(movable_parent.loc)) + set_parent_attached_to(movable_parent.loc) + else // Lost the [LIGHT_ATTACHED] property overlay_lighting_flags &= ~LIGHTING_ATTACHED set_parent_attached_to(null) - - if(new_value & LIGHT_NO_LUMCOUNT) - if(!(movable_parent.light_flags & LIGHT_NO_LUMCOUNT)) //Gained the NO_LUMCOUNT property - overlay_lighting_flags |= LIGHT_NO_LUMCOUNT - //Recalculate affecting - set_lum_power(real_lum_power) - else if(movable_parent.light_flags & LIGHT_NO_LUMCOUNT) //Lost the NO_LUMCOUNT property - overlay_lighting_flags &= ~LIGHT_NO_LUMCOUNT - //Recalculate affecting - set_lum_power(real_lum_power) ///Toggles the light on. /datum/component/overlay_lighting/proc/turn_on() if(overlay_lighting_flags & LIGHTING_ON) return - if(current_holder) - add_dynamic_lumi(current_holder) overlay_lighting_flags |= LIGHTING_ON + if(current_holder) + add_dynamic_lumi() + if(directional) + cast_directional_light() + if(current_holder && current_holder != parent && current_holder != parent_attached_to) + RegisterSignal(current_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) get_new_turfs() @@ -346,38 +444,109 @@ if(!(overlay_lighting_flags & LIGHTING_ON)) return if(current_holder) - remove_dynamic_lumi(current_holder) + remove_dynamic_lumi() overlay_lighting_flags &= ~LIGHTING_ON + if(current_holder && current_holder != parent && current_holder != parent_attached_to) + UnregisterSignal(current_holder, COMSIG_MOVABLE_MOVED) clean_old_turfs() ///Here we append the behavior associated to changing lum_power. /datum/component/overlay_lighting/proc/set_lum_power(new_lum_power) - //Get the simulated luminosity count (If we have no lumcount, this is set to 0) - var/simulated_lum_power = new_lum_power - if(overlay_lighting_flags & LIGHT_NO_LUMCOUNT) - simulated_lum_power = 0 - //The new lum power is the same - if(used_lum_power == simulated_lum_power) - //This light doesn't affect lumcount, but lum_power must be updated regardless - if(new_lum_power != simulated_lum_power) - . = real_lum_power - real_lum_power = new_lum_power + if(lum_power == new_lum_power) return - //Set the return value to the old lum power - . = real_lum_power - real_lum_power = new_lum_power - //Get the old used lum power - var/old_lum_power = used_lum_power - used_lum_power = simulated_lum_power - //Calculate the difference - var/difference = old_lum_power - used_lum_power - //Apply it to any turf we are affecting - for(var/t in affected_turfs) - var/turf/lit_turf = t + . = lum_power + lum_power = new_lum_power + var/difference = . - lum_power + for(var/turf/lit_turf as anything in affected_turfs) lit_turf.dynamic_lumcount -= difference +///Here we append the behavior associated to changing lum_power. +/datum/component/overlay_lighting/proc/cast_directional_light() + var/final_distance = cast_range + //Lower the distance by 1 if we're not looking at a cardinal direction, and we're not a short cast + if(final_distance > SHORT_CAST && !(ALL_CARDINALS & current_direction)) + final_distance -= 1 + var/turf/scanning = get_turf(current_holder) + for(var/i in 1 to final_distance) + var/turf/next_turf = get_step(scanning, current_direction) + if(isnull(next_turf) || IS_OPAQUE_TURF(next_turf)) + final_distance = i + break + scanning = next_turf + + current_holder.underlays -= visible_mask + + var/translate_x = -((range - 1) * 32) + var/translate_y = translate_x + var/scale_x = 1 + var/scale_y = 1 + switch(current_direction) + if(NORTH) + translate_y += 32 * final_distance + if(beam && range > 1) + scale_x = 1 / (range - (range/5)) + if(SOUTH) + translate_y += -32 * final_distance + if(beam && range > 1) + scale_x = 1 / (range - (range/5)) + if(EAST) + translate_x += 32 * final_distance + if(beam && range > 1) + scale_y = 1 / (range - (range/5)) + if(WEST) + translate_x += -32 * final_distance + if(beam && range > 1) + scale_y = 1 / (range - (range/5)) + + if((directional_offset_x != translate_x) || (directional_offset_y != translate_y)) + directional_offset_x = translate_x + directional_offset_y = translate_y + var/matrix/transform = matrix() + if(beam && range > 1) + transform.Scale(scale_x, scale_y) + transform.Translate(translate_x, translate_y) + visible_mask.transform = transform + if(overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + +///Called when current_holder changes loc. +/datum/component/overlay_lighting/proc/on_holder_dir_change(atom/movable/source, olddir, newdir) + SIGNAL_HANDLER + set_direction(newdir) + +///Called when parent changes loc. +/datum/component/overlay_lighting/proc/on_parent_dir_change(atom/movable/source, olddir, newdir) + SIGNAL_HANDLER + set_direction(newdir) + +///Sets a new direction for the directional cast, then updates luminosity +/datum/component/overlay_lighting/proc/set_direction(newdir) + if(!newdir) + return + if(current_direction == newdir) + return + current_direction = newdir + if(overlay_lighting_flags & LIGHTING_ON) + make_luminosity_update() + +/datum/component/overlay_lighting/proc/on_parent_crafted(datum/source, atom/movable/new_craft) + SIGNAL_HANDLER + + if(!istype(new_craft)) + return + + UnregisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT) + RegisterSignal(new_craft, COMSIG_ATOM_USED_IN_CRAFT, PROC_REF(on_parent_crafted)) + set_parent_attached_to(new_craft) + +/// Handles putting the source for overlay lights into the light eater queue since we aren't tracked by [/atom/var/light_sources] +/datum/component/overlay_lighting/proc/on_light_eater(datum/source, list/light_queue, datum/light_eater) + SIGNAL_HANDLER + light_queue[parent] = TRUE + return NONE #undef LIGHTING_ON #undef LIGHTING_ATTACHED #undef GET_PARENT +#undef SHORT_CAST diff --git a/code/datums/elements/light_blocking.dm b/code/datums/elements/light_blocking.dm new file mode 100644 index 000000000000..673838ad4f80 --- /dev/null +++ b/code/datums/elements/light_blocking.dm @@ -0,0 +1,42 @@ +/** + * Attached to movable atoms with opacity. Listens to them move and updates their old and new turf loc's opacity accordingly. + */ +/datum/element/light_blocking + element_flags = ELEMENT_DETACH_ON_HOST_DESTROY + + +/datum/element/light_blocking/Attach(datum/target) + . = ..() + if(!ismovable(target)) + return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_target_move)) + var/atom/movable/movable_target = target + if(!isturf(movable_target.loc)) + return + for(var/turf/turf_loc as anything in movable_target.locs) + turf_loc.add_opacity_source(target) + + +/datum/element/light_blocking/Detach(datum/target) + . = ..() + UnregisterSignal(target, list(COMSIG_MOVABLE_MOVED)) + var/atom/movable/movable_target = target + if(!isturf(movable_target.loc)) + return + for(var/turf/turf_loc as anything in movable_target.locs) + turf_loc.remove_opacity_source(target) + + +///Updates old and new turf loc opacities. +/datum/element/light_blocking/proc/on_target_move(atom/movable/source, atom/old_loc, dir, forced, list/old_locs) + SIGNAL_HANDLER + if(isturf(old_loc)) + if(old_locs) + for(var/turf/old_turf as anything in old_locs) + old_turf.remove_opacity_source(source) + else + var/turf/old_turf = old_loc + old_turf.remove_opacity_source(source) + if(isturf(source.loc)) + for(var/turf/new_turf as anything in source.locs) + new_turf.add_opacity_source(source) diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index c0280d80b7cf..804492f862e9 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -195,40 +195,41 @@ quality = POSITIVE text_gain_indication = span_notice("Your skin begins to glow softly.") instability = 5 - var/obj/effect/dummy/luminescent_glow/glowth //shamelessly copied from luminescents - var/glow = 3.5 - var/range = 2.5 - var/glow_color - var/current_nullify_timer // For veil yogstation\code\modules\antagonists\shadowling\shadowling_abilities.dm power_coeff = 1 conflicts = list(/datum/mutation/human/glow/anti, /datum/mutation/human/radiantburst) + var/glow_power = 3.5 + var/glow_range = 2.5 + var/glow_color + var/current_nullify_timer // For veil yogstation\code\modules\antagonists\shadowling\shadowling_abilities.dm + + var/obj/effect/dummy/lighting_obj/moblight/glow + /datum/mutation/human/glow/on_acquiring(mob/living/carbon/human/owner) . = ..() if(.) return glow_color = owner.dna.features["mcolor"] - glowth = new(owner) + glow = owner.mob_light() modify() // Override modify here without a parent call, because we don't actually give an action. /datum/mutation/human/glow/modify() - if(!glowth) + if(!glow) return - var/power = GET_MUTATION_POWER(src) - glowth.set_light_range_power_color(range * power, glow * power, glow_color) + glow.set_light_range_power_color(glow_range * GET_MUTATION_POWER(src), glow_power, glow_color) /datum/mutation/human/glow/on_losing(mob/living/carbon/human/owner) . = ..() if(.) return - QDEL_NULL(glowth) + QDEL_NULL(glow) /datum/mutation/human/glow/anti name = "Anti-Glow" desc = "Your skin seems to attract and absorb nearby light creating 'darkness' around you." text_gain_indication = span_notice("Your light around you seems to disappear.") - glow = -3.5 + glow_power = -3.5 conflicts = list(/datum/mutation/human/glow, /datum/mutation/human/radiantburst) locked = TRUE diff --git a/code/game/atoms.dm b/code/game/atoms.dm index f0e851f8a341..a1def6de5e72 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -44,6 +44,28 @@ var/datum/wires/wires = null var/obj/effect/abstract/particle_holder/master_holder + ///Light systems, both shouldn't be active at the same time. + var/light_system = STATIC_LIGHT + ///Range of the light in tiles. Zero means no light. + var/light_range = 0 + ///Intensity of the light. The stronger, the less shadows you will see on the lit area. + var/light_power = 1 + ///Hexadecimal RGB string representing the colour of the light. White by default. + var/light_color = COLOR_WHITE + /// Angle of light to show in light_dir + /// 360 is a circle, 90 is a cone, etc. + var/light_angle = 360 + /// What angle to project light in + var/light_dir = NORTH + ///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values. + var/light_on = TRUE + ///Bitflags to determine lighting-related atom properties. + var/light_flags = NONE + ///Our light source. Don't fuck with this directly unless you have a good reason! + var/tmp/datum/light_source/light + ///Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list. + var/tmp/list/light_sources + ///overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. var/list/priority_overlays /// a very temporary list of overlays to remove @@ -171,10 +193,6 @@ if (light_system == STATIC_LIGHT && light_power && light_range) update_light() - if (opacity && isturf(loc)) - var/turf/T = loc - T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. - if (canSmoothWith) canSmoothWith = typelist("canSmoothWith", canSmoothWith) @@ -1046,12 +1064,63 @@ * the object has been admin edited */ /atom/vv_edit_var(var_name, var_value) + var/old_light_flags = light_flags + // Disable frozen lights for now, so we can actually modify it + light_flags &= ~LIGHT_FROZEN + switch(var_name) + + if(NAMEOF(src, light_range)) + if(light_system == STATIC_LIGHT) + set_light(l_range = var_value) + else + set_light_range(var_value) + . = TRUE + if(NAMEOF(src, light_power)) + if(light_system == STATIC_LIGHT) + set_light(l_power = var_value) + else + set_light_power(var_value) + . = TRUE + if(NAMEOF(src, light_color)) + if(light_system == STATIC_LIGHT) + set_light(l_color = var_value) + else + set_light_color(var_value) + . = TRUE + if(NAMEOF(src, light_angle)) + if(light_system == STATIC_LIGHT) + set_light(l_angle = var_value) + . = TRUE + if(NAMEOF(src, light_dir)) + if(light_system == STATIC_LIGHT) + set_light(l_dir = var_value) + . = TRUE + if(NAMEOF(src, light_on)) + set_light_on(var_value) + . = TRUE + if(NAMEOF(src, light_flags)) + set_light_flags(var_value) + // I'm sorry + old_light_flags = var_value + . = TRUE + + light_flags = old_light_flags + if(!isnull(.)) + datum_flags |= DF_VAR_EDITED + return + if(!GLOB.Debug2) flags_1 |= ADMIN_SPAWNED_1 - . = ..() + + . = ..() + switch(var_name) - if("color") + if(NAMEOF(src, color)) add_atom_colour(color, ADMIN_COLOUR_PRIORITY) + update_appearance() + if(NAMEOF(src, opacity)) + set_opacity(var_value) + . = TRUE /** * Return the markup to for the dropdown list for the VV panel for this atom diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index caa5aa2f94d9..e1f80cde837e 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -61,7 +61,7 @@ var/affecting_dynamic_lumi = 0 -/atom/movable/Initialize(mapload) +/atom/movable/Initialize(mapload, ...) . = ..() switch(blocks_emissive) if(EMISSIVE_BLOCK_GENERIC) @@ -71,8 +71,16 @@ em_block = new(src, render_target) vis_contents += em_block - if(light_system == MOVABLE_LIGHT) - AddComponent(/datum/component/overlay_lighting) + if(opacity) + AddElement(/datum/element/light_blocking) + + switch(light_system) + if(MOVABLE_LIGHT) + AddComponent(/datum/component/overlay_lighting) + if(MOVABLE_LIGHT_DIRECTIONAL) + AddComponent(/datum/component/overlay_lighting, is_directional = TRUE) + if(MOVABLE_LIGHT_BEAM) + AddComponent(/datum/component/overlay_lighting, is_directional = TRUE, is_beam = TRUE) /atom/movable/Destroy(force) QDEL_NULL(proximity_monitor) @@ -87,6 +95,9 @@ CanAtmosPass = ATMOS_PASS_YES air_update_turf(TRUE) loc.handle_atom_del(src) + + if(opacity) + RemoveElement(/datum/element/light_blocking) invisibility = INVISIBILITY_ABSTRACT diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 7a57f1a3fe42..050e4f840d37 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -162,7 +162,7 @@ Class Procs: power_change() RegisterSignal(src, COMSIG_ENTER_AREA, PROC_REF(power_change)) -/obj/machinery/Destroy() +/obj/machinery/Destroy(force=FALSE) disconnect_from_network() GLOB.machines.Remove(src) if(!speed_process) diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm index 50682a895aea..bf0662c74313 100644 --- a/code/game/machinery/computer/_computer.dm +++ b/code/game/machinery/computer/_computer.dm @@ -103,9 +103,9 @@ if(!.) return // reduce unneeded light changes if(stat & NOPOWER) - set_light(FALSE) + set_light_on(FALSE) else - set_light(TRUE) + set_light_on(TRUE) /obj/machinery/computer/screwdriver_act(mob/living/user, obj/item/I) if(..()) @@ -133,7 +133,7 @@ . = ..() if(.) playsound(loc, 'sound/effects/glassbr3.ogg', 100, TRUE) - set_light(0) + set_light_on(FALSE) /obj/machinery/computer/emp_act(severity) . = ..() diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index 5204102cb6c1..158448fd889f 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -64,7 +64,7 @@ */ /obj/machinery/door/airlock/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/glass/incinerator @@ -82,28 +82,28 @@ id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR /obj/machinery/door/airlock/command/glass - opacity = 0 + opacity = FALSE glass = TRUE normal_integrity = 400 /obj/machinery/door/airlock/engineering/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/engineering/glass/critical critical_machine = TRUE //stops greytide virus from opening & bolting doors in critical positions, such as the SM chamber. /obj/machinery/door/airlock/security/glass - opacity = 0 + opacity = FALSE glass = TRUE normal_integrity = 400 /obj/machinery/door/airlock/medical/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/research/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/research/glass/incinerator @@ -121,30 +121,30 @@ id_tag = INCINERATOR_TOXMIX_AIRLOCK_EXTERIOR /obj/machinery/door/airlock/mining/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/atmos/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/atmos/glass/critical critical_machine = TRUE //stops greytide virus from opening & bolting doors in critical positions, such as the SM chamber. /obj/machinery/door/airlock/science/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/virology/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/maintenance/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/maintenance/external/glass - opacity = 0 + opacity = FALSE glass = TRUE normal_integrity = 200 @@ -159,7 +159,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_gold /obj/machinery/door/airlock/gold/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/silver @@ -168,7 +168,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_silver /obj/machinery/door/airlock/silver/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/diamond @@ -180,7 +180,7 @@ /obj/machinery/door/airlock/diamond/glass normal_integrity = 950 - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/uranium @@ -201,7 +201,7 @@ return /obj/machinery/door/airlock/uranium/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/plasma @@ -241,7 +241,7 @@ return ..() /obj/machinery/door/airlock/plasma/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/bananium @@ -252,7 +252,7 @@ doorOpen = 'sound/items/bikehorn.ogg' /obj/machinery/door/airlock/bananium/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/sandstone @@ -261,7 +261,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_sandstone /obj/machinery/door/airlock/sandstone/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/wood @@ -270,7 +270,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_wood /obj/machinery/door/airlock/wood/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/titanium @@ -283,7 +283,7 @@ /obj/machinery/door/airlock/titanium/glass normal_integrity = 350 - opacity = 0 + opacity = FALSE glass = TRUE ////////////////////////////////// @@ -297,7 +297,7 @@ assemblytype = /obj/structure/door_assembly/door_assembly_public /obj/machinery/door/airlock/public/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/public/glass/incinerator @@ -330,7 +330,7 @@ panel_attachment = "bottom" /obj/machinery/door/airlock/external/glass - opacity = 0 + opacity = FALSE glass = TRUE ////////////////////////////////// @@ -426,7 +426,7 @@ anim_parts = "rightu=11,0;left=-12,0;right=11,0" /obj/machinery/door/airlock/shuttle/glass - opacity = 0 + opacity = FALSE glass = TRUE /obj/machinery/door/airlock/abductor @@ -521,7 +521,7 @@ /obj/machinery/door/airlock/cult/glass glass = TRUE - opacity = 0 + opacity = FALSE /obj/machinery/door/airlock/cult/glass/friendly friendly = TRUE @@ -537,7 +537,7 @@ /obj/machinery/door/airlock/cult/unruned/glass glass = TRUE - opacity = 0 + opacity = FALSE /obj/machinery/door/airlock/cult/unruned/glass/friendly friendly = TRUE @@ -664,7 +664,7 @@ /obj/machinery/door/airlock/clockwork/brass glass = TRUE - opacity = 0 + opacity = FALSE ////////////////////////////////// /* @@ -678,7 +678,7 @@ mask_file = 'icons/obj/doors/airlocks/mask_64x32_airlocks.dmi' mask_x = 16 // byond is consistent and sane anim_parts = "left=-21,0;right=21,0;top=0,29" - opacity = 0 + opacity = FALSE assemblytype = null glass = TRUE bound_width = 64 // 2x1 diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm index 8d4b14b3edb1..4b83bf63ed93 100644 --- a/code/game/machinery/doors/alarmlock.dm +++ b/code/game/machinery/doors/alarmlock.dm @@ -2,7 +2,7 @@ name = "glass alarm airlock" icon = 'icons/obj/doors/airlocks/station2/glass.dmi' overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi' - opacity = 0 + opacity = FALSE assemblytype = /obj/structure/door_assembly/door_assembly_public glass = TRUE diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 20a82701e250..714947cdd5e0 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -3,7 +3,7 @@ desc = "It opens and closes." icon = 'icons/obj/doors/Doorint.dmi' icon_state = "door1" - opacity = 1 + opacity = TRUE density = TRUE move_resist = MOVE_FORCE_VERY_STRONG layer = OPEN_DOOR_LAYER @@ -103,7 +103,7 @@ else layer = initial(layer) -/obj/machinery/door/Destroy() +/obj/machinery/door/Destroy(force=FALSE) update_freelook_sight() GLOB.airlocks -= src if(spark_system) diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index 8d5c39cf8c1e..58640614c6e9 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -22,7 +22,7 @@ /obj/machinery/door/poddoor/preopen icon_state = "open" density = FALSE - opacity = 0 + opacity = FALSE /obj/machinery/door/poddoor/ert name = "ERT Armory door" diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index d4f383e0b925..6f71f57d5759 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -11,7 +11,7 @@ /obj/machinery/door/poddoor/shutters/preopen icon_state = "open" density = FALSE - opacity = 0 + opacity = FALSE /obj/machinery/door/poddoor/shutters/window name = "windowed shutters" diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm index 0f7fd4ec4da7..6e14893f9e8b 100644 --- a/code/game/machinery/doors/unpowered.dm +++ b/code/game/machinery/doors/unpowered.dm @@ -20,6 +20,6 @@ icon = 'icons/turf/shuttle.dmi' name = "door" icon_state = "door1" - opacity = 1 + opacity = TRUE density = TRUE explosion_block = 1 diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index edb6ef9f4a75..99712b02ac83 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -12,7 +12,7 @@ armor = list(MELEE = 60, BULLET = -40, LASER = 50, ENERGY = 50, BOMB = 10, BIO = 100, RAD = 100, FIRE = 70, ACID = 100) visible = FALSE flags_1 = ON_BORDER_1 - opacity = 0 + opacity = FALSE CanAtmosPass = ATMOS_PASS_PROC interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN var/obj/item/electronics/airlock/electronics = null diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index a55f51e7e99d..127b93e5af87 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -5,7 +5,7 @@ icon_state = "shield-old" density = TRUE move_resist = INFINITY - opacity = 0 + opacity = FALSE anchored = TRUE resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF max_integrity = 200 //The shield can only take so much beating (prevents perma-prisons) @@ -70,7 +70,7 @@ icon = 'icons/obj/objects.dmi' icon_state = "shieldoff" density = TRUE - opacity = 0 + opacity = FALSE anchored = FALSE pressure_resistance = 2*ONE_ATMOSPHERE req_access = list(ACCESS_ENGINE) diff --git a/code/game/mecha/combat/reticence.dm b/code/game/mecha/combat/reticence.dm index 7237237ccc6a..9a324986eae5 100644 --- a/code/game/mecha/combat/reticence.dm +++ b/code/game/mecha/combat/reticence.dm @@ -18,7 +18,7 @@ stepsound = null turnsound = null meleesound = FALSE - opacity = 0 + opacity = FALSE /obj/mecha/combat/reticence/Initialize(mapload) . = ..() diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 844c3d62d52d..df65db8ff4a2 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -18,7 +18,7 @@ desc = "Exosuit" icon = 'icons/mecha/mecha.dmi' density = TRUE //Dense. To raise the heat. - opacity = 1 ///opaque. Menacing. + opacity = TRUE ///opaque. Menacing. move_resist = MOVE_FORCE_EXTREMELY_STRONG //no pulling around. resistance_flags = FIRE_PROOF | ACID_PROOF layer = BELOW_MOB_LAYER//icon draw layer diff --git a/code/game/mecha/mecha_wreckage.dm b/code/game/mecha/mecha_wreckage.dm index 0043fb3e4e6d..034d32ab341c 100644 --- a/code/game/mecha/mecha_wreckage.dm +++ b/code/game/mecha/mecha_wreckage.dm @@ -9,7 +9,7 @@ icon = 'icons/mecha/mecha.dmi' density = TRUE anchored = FALSE - opacity = 0 + opacity = FALSE var/state = MECHA_WRECK_CUT var/orig_mecha var/can_be_reconstructed = FALSE diff --git a/code/game/movable_luminosity.dm b/code/game/movable_luminosity.dm index 7a6eaddafd9e..c3bf5ed2525d 100644 --- a/code/game/movable_luminosity.dm +++ b/code/game/movable_luminosity.dm @@ -11,7 +11,6 @@ affecting_dynamic_lumi = highest luminosity += affecting_dynamic_lumi - ///Helper to change several lighting overlay settings. /atom/movable/proc/set_light_range_power_color(range, power, color) set_light_range(range) diff --git a/code/game/objects/effects/alien_acid.dm b/code/game/objects/effects/alien_acid.dm index 18974a9a01aa..6d0ae81b5082 100644 --- a/code/game/objects/effects/alien_acid.dm +++ b/code/game/objects/effects/alien_acid.dm @@ -4,7 +4,7 @@ desc = "Burbling corrosive stuff." icon_state = "acid" density = FALSE - opacity = 0 + opacity = FALSE anchored = TRUE resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF layer = ABOVE_NORMAL_TURF_LAYER diff --git a/code/game/objects/effects/bump_teleporter.dm b/code/game/objects/effects/bump_teleporter.dm index 36320f29133b..426a4a37064e 100644 --- a/code/game/objects/effects/bump_teleporter.dm +++ b/code/game/objects/effects/bump_teleporter.dm @@ -7,7 +7,7 @@ invisibility = INVISIBILITY_ABSTRACT //nope, can't see this anchored = TRUE density = TRUE - opacity = 0 + opacity = FALSE var/static/list/AllTeleporters diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm index 35ba7c6f9c44..3839457dc634 100644 --- a/code/game/objects/effects/effect_system/effect_system.dm +++ b/code/game/objects/effects/effect_system/effect_system.dm @@ -25,7 +25,7 @@ would spawn and follow the beaker, even if it is carried or thrown. /datum/effect_system var/number = 3 - var/cardinals = FALSE + var/cardinals_only = FALSE var/turf/location var/atom/holder var/effect_type @@ -39,7 +39,7 @@ would spawn and follow the beaker, even if it is carried or thrown. /datum/effect_system/proc/set_up(number = 3, cardinals_only = FALSE, location) src.number = min(number, 10) - src.cardinals = cardinals_only + src.cardinals_only = cardinals_only src.location = get_turf(location) /datum/effect_system/proc/attach(atom/atom) @@ -59,7 +59,7 @@ would spawn and follow the beaker, even if it is carried or thrown. var/obj/effect/E = new effect_type(location) total_effects++ var/direction - if(cardinals) + if(cardinals_only) direction = pick(GLOB.cardinals) else direction = pick(GLOB.alldirs) diff --git a/code/game/objects/effects/effect_system/effects_explosion.dm b/code/game/objects/effects/effect_system/effects_explosion.dm index f264fa3a618b..e436ca851fbc 100644 --- a/code/game/objects/effects/effect_system/effects_explosion.dm +++ b/code/game/objects/effects/effect_system/effects_explosion.dm @@ -1,7 +1,7 @@ /obj/effect/particle_effect/expl_particles name = "fire" icon_state = "explosion_particle" - opacity = 1 + opacity = TRUE anchored = TRUE /obj/effect/particle_effect/expl_particles/Initialize(mapload) //yogs start: reverts harddel stuff so it doesn't break horribly @@ -23,7 +23,7 @@ name = "fire" icon = 'icons/effects/96x96.dmi' icon_state = "explosion" - opacity = 1 + opacity = TRUE anchored = TRUE mouse_opacity = MOUSE_OPACITY_TRANSPARENT pixel_x = -32 diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index 9efda705f3f0..ceaeb77375ff 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -5,13 +5,9 @@ // will always spawn at the items location. ///////////////////////////////////////////// -/proc/do_sparks(n, c, source) - // n - number of sparks - // c - cardinals, bool, do the sparks only move in cardinal directions? - // source - source of the sparks. - +/proc/do_sparks(number, cardinal_only, datum/source) var/datum/effect_system/spark_spread/sparks = new - sparks.set_up(n, c, source) + sparks.set_up(number, cardinal_only, source) sparks.autocleanup = TRUE sparks.start() @@ -24,7 +20,6 @@ light_range = 2 light_power = 0.5 light_color = LIGHT_COLOR_FIRE - light_flags = LIGHT_NO_LUMCOUNT var/duration = 2 SECONDS var/volume = 100 var/sound = "sparks" diff --git a/code/game/objects/effects/forcefields.dm b/code/game/objects/effects/forcefields.dm index 2216f16b6ef2..429e064b0b6b 100644 --- a/code/game/objects/effects/forcefields.dm +++ b/code/game/objects/effects/forcefields.dm @@ -3,7 +3,7 @@ desc = "A space wizard's magic wall." icon_state = "m_shield" anchored = TRUE - opacity = 0 + opacity = FALSE density = TRUE CanAtmosPass = ATMOS_PASS_DENSITY /// If set, how long the force field lasts after it's created. Set to 0 to have infinite duration forcefields. diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index cb24dad4edbe..c7de6a2597cc 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -79,16 +79,16 @@ light_range = MINIMUM_USEFUL_LIGHT_RANGE mouse_opacity = MOUSE_OPACITY_TRANSPARENT -/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration) +/obj/effect/dummy/lighting_obj/Initialize(mapload, range, power, color, duration) . = ..() - if(!isnull(_range)) - set_light_range(_range) - if(!isnull(_power)) - set_light_power(_power) - if(!isnull(_color)) - set_light_color(_color) - if(_duration) - QDEL_IN(src, _duration) + if(!isnull(range)) + set_light_range(range) + if(!isnull(power)) + set_light_power(power) + if(!isnull(color)) + set_light_color(color) + if(duration) + QDEL_IN(src, duration) /obj/effect/dummy/lighting_obj/moblight name = "mob lighting fx" @@ -98,6 +98,9 @@ if(!ismob(loc)) return INITIALIZE_HINT_QDEL +/obj/effect/dummy/lighting_obj/moblight/species + name = "species lighting" + /obj/effect/dusting_anim icon = 'icons/effects/filters.dmi' icon_state = "nothing" diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index 906425b34252..dfd44008cdbb 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -50,7 +50,7 @@ /obj/effect/overlay/vis mouse_opacity = MOUSE_OPACITY_TRANSPARENT anchored = TRUE - vis_flags = NONE + vis_flags = VIS_INHERIT_DIR var/unused = 0 //When detected to be unused it gets set to world.time, after a while it gets removed var/cache_expiration = 2 MINUTES // overlays which go unused for 2 minutes get cleaned up vis_flags = VIS_INHERIT_ID @@ -88,3 +88,7 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT alpha = 0 vis_flags = NONE + +/obj/effect/overlay/light_visible/cone + icon = 'icons/effects/light_overlays/light_cone.dmi' + alpha = 110 diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index 3c25133864f1..c547a7078779 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -12,7 +12,7 @@ RLD /obj/item/construction name = "not for ingame use" desc = "A device used to rapidly build and deconstruct. Reload with metal, plasteel, glass or compressed matter cartridges." - opacity = 0 + opacity = FALSE density = FALSE anchored = FALSE flags_1 = CONDUCT_1 diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm index dce2f155e9e7..a497be7a27c2 100644 --- a/code/game/objects/items/RSF.dm +++ b/code/game/objects/items/RSF.dm @@ -13,7 +13,7 @@ RSF var/spent_icon_state = "rsf_empty" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - opacity = 0 + opacity = FALSE density = FALSE anchored = FALSE item_flags = NOBLUDGEON diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 6b538bff266a..e5a6611c0df1 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -32,6 +32,7 @@ set_light_on(on) if(light_system == STATIC_LIGHT) update_light() + /obj/item/flashlight/attack_self(mob/user) on = !on update_brightness(user) @@ -236,6 +237,7 @@ force = 9 // Not as good as a stun baton. light_range = 5 // A little better than the standard flashlight. hitsound = 'sound/weapons/genhit1.ogg' + light_system = MOVABLE_LIGHT_DIRECTIONAL // the desk lamps are a bit special /obj/item/flashlight/lamp diff --git a/code/game/objects/items/grenades/flashbang.dm b/code/game/objects/items/grenades/flashbang.dm index a66c2cdec5c8..bfa0f46dcfe9 100644 --- a/code/game/objects/items/grenades/flashbang.dm +++ b/code/game/objects/items/grenades/flashbang.dm @@ -13,7 +13,7 @@ return do_sparks(rand(5, 9), FALSE, src) playsound(flashbang_turf, 'sound/weapons/flashbang.ogg', 100, TRUE, 8, 0.9) - new /obj/effect/dummy/lighting_obj (flashbang_turf, flashbang_range + 2, 4, COLOR_WHITE, 2) + new /obj/effect/dummy/lighting_obj(flashbang_turf, flashbang_range + 2, 4, COLOR_WHITE, 2) for(var/mob/living/M in get_hearers_in_view(flashbang_range, flashbang_turf)) bang(get_turf(M), M) qdel(src) diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index f96ffbdfefc2..00840c1a3993 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -859,12 +859,13 @@ force = 0 // How often we forget throwforce = 0 // Faith without works is... attack_verb = list("blessed") + menutab = MENU_MISC + additional_desc = "A holy icon, praying to it will allow it to weaken and burn those that draw your god's ire." + var/held_up = FALSE var/mutable_appearance/holy_glow_fx - var/obj/effect/dummy/lighting_obj/moblight/holy_glow_light COOLDOWN_DECLARE(holy_notification) - menutab = MENU_MISC - additional_desc = "A holy icon, praying to it will allow it to weaken and burn those that draw your god's ire." + var/obj/effect/dummy/lighting_obj/moblight/holy_glow_light /obj/item/nullrod/cross/attack_self(mob/living/user) . = ..() @@ -879,7 +880,7 @@ slot_flags = 0 holy_glow_fx = mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER) user.add_overlay(holy_glow_fx) - holy_glow_light = user.mob_light(_color = LIGHT_COLOR_HOLY_MAGIC, _range = 2) + holy_glow_light = user.mob_light(range = 2, color = LIGHT_COLOR_HOLY_MAGIC) RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(unwield)) RegisterSignal(src, COMSIG_ITEM_PREDROPPED, PROC_REF(drop_unwield)) START_PROCESSING(SSfastprocess, src) diff --git a/code/game/objects/items/implants/implantchair.dm b/code/game/objects/items/implants/implantchair.dm index e3aadfe0fe34..77bc76d2b0a5 100644 --- a/code/game/objects/items/implants/implantchair.dm +++ b/code/game/objects/items/implants/implantchair.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/machines/implantchair.dmi' icon_state = "implantchair" density = TRUE - opacity = 0 + opacity = FALSE var/ready = TRUE var/replenishing = FALSE diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm index 7b301ddadc60..f8dc7141cdba 100644 --- a/code/game/objects/structures/aliens.dm +++ b/code/game/objects/structures/aliens.dm @@ -55,7 +55,7 @@ icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi' icon_state = "smooth" density = TRUE - opacity = 1 + opacity = TRUE anchored = TRUE canSmoothWith = list(/obj/structure/alien/resin) max_integrity = 200 @@ -89,7 +89,7 @@ desc = "Resin just thin enough to let light pass through." icon = 'icons/obj/smooth_structures/alien/resin_membrane.dmi' icon_state = "smooth" - opacity = 0 + opacity = FALSE max_integrity = 160 resintype = "membrane" canSmoothWith = list(/obj/structure/alien/resin/wall, /obj/structure/alien/resin/membrane) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index 874b1a6c51a8..96f9f9f91983 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -9,7 +9,7 @@ icon_state = "wall" layer = CLOSED_TURF_LAYER density = TRUE - opacity = 1 + opacity = TRUE max_integrity = 100 canSmoothWith = list( diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm index 3d998428ee39..399d554f2102 100644 --- a/code/game/objects/structures/fluff.dm +++ b/code/game/objects/structures/fluff.dm @@ -7,7 +7,7 @@ icon_state = "minibar" anchored = TRUE density = FALSE - opacity = 0 + opacity = FALSE var/deconstructible = TRUE /obj/structure/fluff/attackby(obj/item/I, mob/living/user, params) diff --git a/code/game/objects/structures/guncase.dm b/code/game/objects/structures/guncase.dm index 6d969b87dd78..4eee49f9990c 100644 --- a/code/game/objects/structures/guncase.dm +++ b/code/game/objects/structures/guncase.dm @@ -6,7 +6,7 @@ icon_state = "shotguncase" anchored = FALSE density = TRUE - opacity = 0 + opacity = FALSE var/case_type = "" var/gun_category = /obj/item/gun var/open = TRUE diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index 7391d088457f..912a4dac333a 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -1,7 +1,7 @@ /obj/structure/sign icon = 'icons/obj/decals.dmi' anchored = TRUE - opacity = 0 + opacity = FALSE density = FALSE layer = SIGN_LAYER max_integrity = 100 diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 3ff6fd6ee3ba..2a9eeee4defe 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -386,7 +386,7 @@ alpha = 200 //Mappers can also just set this to 255 if they want curtains that can't be seen through layer = SIGN_LAYER anchored = TRUE - opacity = 0 + opacity = FALSE density = FALSE var/open = TRUE @@ -401,14 +401,14 @@ layer = WALL_OBJ_LAYER density = TRUE open = FALSE - opacity = TRUE + set_opacity(TRUE) else icon_state = "open" layer = SIGN_LAYER density = FALSE open = TRUE - opacity = FALSE + set_opacity(FALSE) /obj/structure/curtain/attackby(obj/item/W, mob/user) if (istype(W, /obj/item/toy/crayon)) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 81d1abfe700e..587c4746861c 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -613,7 +613,7 @@ /obj/structure/window/reinforced/tinted name = "tinted window" icon_state = "twindow" - opacity = 1 + opacity = TRUE /obj/structure/window/reinforced/tinted/frosted name = "frosted window" icon_state = "fwindow" diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm index 582780f10a59..098efd8fc44f 100644 --- a/code/game/shuttle_engines.dm +++ b/code/game/shuttle_engines.dm @@ -99,7 +99,7 @@ name = "propulsion engine" icon_state = "propulsion" desc = "A standard reliable bluespace engine used by many forms of shuttles." - opacity = 1 + opacity = TRUE /obj/structure/shuttle/engine/propulsion/left name = "left propulsion engine" @@ -132,7 +132,7 @@ /obj/structure/shuttle/engine/large name = "engine" - opacity = 1 + opacity = TRUE icon = 'icons/obj/2x2.dmi' icon_state = "large_engine" desc = "A very large bluespace engine used to propel very large ships." @@ -142,7 +142,7 @@ /obj/structure/shuttle/engine/huge name = "engine" - opacity = 1 + opacity = TRUE icon = 'icons/obj/3x3.dmi' icon_state = "huge_engine" desc = "An extremely large bluespace engine used to propel extremely large ships." diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 329502913482..6bc5d80d4385 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -2,7 +2,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( /turf/open/space, /turf/baseturf_bottom, - ))) +))) /turf/proc/empty(turf_type=/turf/open/space, baseturf_type, list/ignore_typecache, flags) // Remove all atoms except observers, landmarks, docking ports @@ -71,13 +71,13 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( if(flags & CHANGETURF_SKIP) return new path(src) - var/old_opacity = opacity var/old_dynamic_lighting = dynamic_lighting var/old_lighting_object = lighting_object var/old_lighting_corner_NE = lighting_corner_NE var/old_lighting_corner_SE = lighting_corner_SE var/old_lighting_corner_SW = lighting_corner_SW var/old_lighting_corner_NW = lighting_corner_NW + var/old_directional_opacity = directional_opacity var/old_exl = explosion_level var/old_exi = explosion_id @@ -118,10 +118,9 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( lighting_corner_NW = old_lighting_corner_NW if(SSlighting.initialized) - recalc_atom_opacity() lighting_object = old_lighting_object - if (old_opacity != opacity || dynamic_lighting != old_dynamic_lighting) - reconsider_lights() + directional_opacity = old_directional_opacity + recalculate_directional_opacity() if (dynamic_lighting != old_dynamic_lighting) if (IS_DYNAMIC_LIGHTING(src)) diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index a35d4930ddec..65d94a5a4aeb 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -1,6 +1,6 @@ /turf/closed layer = CLOSED_TURF_LAYER - opacity = 1 + opacity = TRUE density = TRUE blocks_air = TRUE flags_1 = RAD_PROTECT_CONTENTS_1 | RAD_NO_CONTAMINATE_1 @@ -107,7 +107,7 @@ /turf/closed/indestructible/fakeglass name = "window" icon_state = "fake_window" - opacity = 0 + opacity = FALSE smooth = SMOOTH_TRUE icon = 'icons/obj/smooth_structures/reinforced_window.dmi' @@ -120,7 +120,7 @@ /turf/closed/indestructible/opsglass name = "window" icon_state = "plastitanium_window" - opacity = 0 + opacity = FALSE smooth = SMOOTH_TRUE icon = 'icons/obj/smooth_structures/plastitanium_window.dmi' diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index c319f4542997..1f5725f38fa4 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -10,7 +10,7 @@ canSmoothWith = null baseturfs = /turf/open/floor/plating/asteroid/airless initial_gas_mix = AIRLESS_ATMOS - opacity = 1 + opacity = TRUE density = TRUE layer = EDGED_TURF_LAYER temperature = TCMB diff --git a/code/game/turfs/simulated/wall/reinf_walls.dm b/code/game/turfs/simulated/wall/reinf_walls.dm index e32864e5d785..94e94e57333f 100644 --- a/code/game/turfs/simulated/wall/reinf_walls.dm +++ b/code/game/turfs/simulated/wall/reinf_walls.dm @@ -3,7 +3,7 @@ desc = "A huge chunk of reinforced metal used to separate rooms." icon = 'icons/turf/walls/reinforced_wall.dmi' icon_state = "r_wall" - opacity = 1 + opacity = TRUE density = TRUE var/d_state = INTACT diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index eb437da4683f..f45f1085b16f 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -51,7 +51,7 @@ update_light() if (opacity) - has_opaque_atom = TRUE + directional_opacity = ALL_CARDINALS return INITIALIZE_HINT_NORMAL diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index bf0afac73c78..57df5c8c6f31 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -3,6 +3,9 @@ GLOBAL_LIST_EMPTY(station_turfs) /turf icon = 'icons/turf/floors.dmi' level = 1 + luminosity = 1 + + var/dynamic_lighting = DYNAMIC_LIGHTING_ENABLED var/intact = 1 @@ -19,9 +22,6 @@ GLOBAL_LIST_EMPTY(station_turfs) var/blocks_air = FALSE - ///Which directions does this turf block the vision of, taking into account both the turf's opacity and the movable opacity_sources. - var/directional_opacity = NONE - flags_1 = CAN_BE_DIRTY_1 var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes @@ -39,6 +39,24 @@ GLOBAL_LIST_EMPTY(station_turfs) var/tiled_dirt = FALSE // use smooth tiled dirt decal + ///Lumcount added by sources other than lighting datum objects, such as the overlay lighting component. + var/dynamic_lumcount = 0 + + var/tmp/lighting_corners_initialised = FALSE + + ///Our lighting object. + var/tmp/datum/lighting_object/lighting_object + ///Lighting Corner datums. + var/tmp/datum/lighting_corner/lighting_corner_NE + var/tmp/datum/lighting_corner/lighting_corner_SE + var/tmp/datum/lighting_corner/lighting_corner_SW + var/tmp/datum/lighting_corner/lighting_corner_NW + + ///Which directions does this turf block the vision of, taking into account both the turf's opacity and the movable opacity_sources. + var/directional_opacity = NONE + ///Lazylist of movable atoms providing opacity sources. + var/list/atom/movable/opacity_sources + /turf/vv_edit_var(var_name, new_value) var/static/list/banned_edits = list("x", "y", "z") if(var_name in banned_edits) @@ -87,7 +105,7 @@ GLOBAL_LIST_EMPTY(station_turfs) SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, UP) if (opacity) - has_opaque_atom = TRUE + directional_opacity = ALL_CARDINALS if(color) add_atom_colour(color, FIXED_COLOUR_PRIORITY) @@ -267,14 +285,6 @@ GLOBAL_LIST_EMPTY(station_turfs) if(QDELETED(mover)) return FALSE //We were deleted. -/turf/Entered(atom/movable/AM) - ..() - - // If an opaque movable atom moves around we need to potentially update visibility. - if (AM.opacity) - has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case. - reconsider_lights() - /turf/open/Entered(atom/movable/AM) ..() //melting diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index 7178befd2ad3..480c1ed139b7 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -5,7 +5,7 @@ light_range = 2 desc = "A thick wall of writhing tendrils." density = FALSE //this being false causes two bugs, being able to attack blob tiles behind other blobs and being unable to move on blob tiles in no gravity, but turning it to 1 causes the blob mobs to be unable to path through blobs, which is probably worse. - opacity = 0 + opacity = FALSE anchored = TRUE layer = BELOW_MOB_LAYER CanAtmosPass = ATMOS_PASS_PROC diff --git a/code/modules/antagonists/clockcult/clock_effect.dm b/code/modules/antagonists/clockcult/clock_effect.dm index a788677eb162..237a15c72763 100644 --- a/code/modules/antagonists/clockcult/clock_effect.dm +++ b/code/modules/antagonists/clockcult/clock_effect.dm @@ -7,7 +7,7 @@ icon_state = "ratvars_flame" anchored = TRUE density = FALSE - opacity = 0 + opacity = FALSE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF /obj/effect/clockwork/Initialize(mapload) diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 558b3d5cace4..f8c9196488a5 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -423,12 +423,12 @@ user.visible_message(span_warning("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!"), \ span_cultitalic("You attempt to stun [L] with the spell!")) - user.mob_light(_range = 3, _color = LIGHT_COLOR_BLOOD_MAGIC, _duration = 0.2 SECONDS) + user.mob_light(range = 3, color = LIGHT_COLOR_BLOOD_MAGIC, duration = 0.2 SECONDS) var/anti_magic_source = L.can_block_magic() if(anti_magic_source) - L.mob_light(_range = 2, _color = LIGHT_COLOR_HOLY_MAGIC, _duration = 10 SECONDS) + L.mob_light(range = 2, color = LIGHT_COLOR_HOLY_MAGIC, duration = 10 SECONDS) var/mutable_appearance/forbearance = mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER) L.add_overlay(forbearance) addtimer(CALLBACK(L, TYPE_PROC_REF(/atom, cut_overlay), forbearance), 100) diff --git a/code/modules/antagonists/eldritch_cult/eldritch_gun.dm b/code/modules/antagonists/eldritch_cult/eldritch_gun.dm index 38b94e060142..2f902acbc474 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_gun.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_gun.dm @@ -120,7 +120,7 @@ BB.stamina *= 2 BB.knockdown = 0.5 SECONDS BB.stutter = 6 SECONDS - BB.projectile_phasing = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF | PASSMACHINES | PASSSTRUCTURE | PASSDOORS + BB.projectile_phasing = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF | PASSMACHINES | PASSSTRUCTURE | PASSDOOR BB.homing = TRUE BB.homing_turn_speed = 80 diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index ab5068eb1373..1fd2e701d888 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -254,7 +254,7 @@ /turf/proc/conductivity_directions() if(archived_cycle < SSair.times_fired) archive() - return NORTH|SOUTH|EAST|WEST + return ALL_CARDINALS /turf/open/conductivity_directions() if(blocks_air) diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm index 5e995528d4a2..0078cedfeaf7 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm @@ -20,7 +20,7 @@ return ..() /obj/machinery/atmospherics/pipe/heat_exchanging/manifold/SetInitDirections() - initialize_directions = NORTH|SOUTH|EAST|WEST + initialize_directions = ALL_CARDINALS initialize_directions &= ~dir /obj/machinery/atmospherics/pipe/heat_exchanging/manifold/update_overlays() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm index 22d73b285bc7..73f05668f576 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm @@ -7,7 +7,7 @@ name = "4-way pipe manifold" desc = "A manifold composed of heat-exchanging pipes." - initialize_directions = NORTH|SOUTH|EAST|WEST + initialize_directions = ALL_CARDINALS device_type = QUATERNARY diff --git a/code/modules/atmospherics/machinery/pipes/manifold.dm b/code/modules/atmospherics/machinery/pipes/manifold.dm index 625ebf4ecae9..81060821e445 100644 --- a/code/modules/atmospherics/machinery/pipes/manifold.dm +++ b/code/modules/atmospherics/machinery/pipes/manifold.dm @@ -29,7 +29,7 @@ return ..() /obj/machinery/atmospherics/pipe/manifold/SetInitDirections() - initialize_directions = NORTH|SOUTH|EAST|WEST + initialize_directions = ALL_CARDINALS initialize_directions &= ~dir /obj/machinery/atmospherics/pipe/manifold/update_overlays() diff --git a/code/modules/atmospherics/machinery/pipes/manifold4w.dm b/code/modules/atmospherics/machinery/pipes/manifold4w.dm index 1ad4d090b130..68c89c4a9b50 100644 --- a/code/modules/atmospherics/machinery/pipes/manifold4w.dm +++ b/code/modules/atmospherics/machinery/pipes/manifold4w.dm @@ -7,7 +7,7 @@ name = "4-way pipe manifold" desc = "A manifold composed of regular pipes." - initialize_directions = NORTH|SOUTH|EAST|WEST + initialize_directions = ALL_CARDINALS device_type = QUATERNARY diff --git a/code/modules/client/client_colour.dm b/code/modules/client/client_colour.dm index ba7fcdbcebd4..c59259bc307b 100644 --- a/code/modules/client/client_colour.dm +++ b/code/modules/client/client_colour.dm @@ -15,9 +15,6 @@ var/colour = "" //Any client.color-valid value var/priority = 1 //Since only one client.color can be rendered on screen, we take the one with the highest priority value: //eg: "Bloody screen" > "goggles colour" as the former is much more important -/mob - var/list/client_colours = list() - /* diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index 4e7e5b6b3e97..f6361de4d6b3 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -246,7 +246,7 @@ density = FALSE anchored = TRUE invisibility = INVISIBILITY_ABSTRACT - opacity = 0 + opacity = FALSE mouse_opacity = MOUSE_OPACITY_TRANSPARENT var/mob/holder var/phase_time = 0 diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index 3d9a7e170a89..7567b647a12d 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -198,7 +198,7 @@ ..() if(istype(G) && ispath(G.trash, /obj/item/grown)) return - var/obj/item/seeds/seed = G.seed + var/obj/item/seeds/seed = G.get_plant_seed() var/stun_len = seed.potency * rate if(!istype(G, /obj/item/grown/bananapeel) && (!G.reagents || !G.reagents.has_reagent(/datum/reagent/lube))) @@ -256,16 +256,20 @@ trait_id = "glow" var/glow_color = "#C3E381" -/datum/plant_gene/trait/glow/proc/glow_range(obj/item/seeds/S) - return 1.4 + S.potency*rate +/datum/plant_gene/trait/glow/proc/glow_range(obj/item/seeds/seed) + return 1.4 + seed.potency * rate -/datum/plant_gene/trait/glow/proc/glow_power(obj/item/seeds/S) - return max(S.potency*(rate + 0.01), 0.1) +/datum/plant_gene/trait/glow/proc/glow_power(obj/item/seeds/seed) + return max(seed.potency * (rate + 0.01), 0.1) -/datum/plant_gene/trait/glow/on_new(obj/item/reagent_containers/food/snacks/grown/G, newloc) +/datum/plant_gene/trait/glow/on_new(obj/item/our_plant, newloc) . = ..() - G.light_system = MOVABLE_LIGHT - G.AddComponent(/datum/component/overlay_lighting, glow_range(G.seed), glow_power(G.seed), glow_color) + if(!.) + return + + var/obj/item/seeds/our_seed = our_plant.get_plant_seed() + our_plant.light_system = MOVABLE_LIGHT + our_plant.AddComponent(/datum/component/overlay_lighting, glow_range(our_seed), glow_power(our_seed), glow_color) /datum/plant_gene/trait/glow/shadow //makes plant emit slightly purple shadows diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 1ffb5349e54a..f4f415cf0be9 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -437,3 +437,21 @@ genes += P else qdel(P) + +/* + * Both `/item/food/grown` and `/item/grown` implement a seed variable which tracks + * plant statistics, genes, traits, etc. This proc gets the seed for either grown food or + * grown inedibles and returns it, or returns null if it's not a plant. + * + * Returns an `/obj/item/seeds` ref for grown foods or grown inedibles. + * - returned seed CAN be null in weird cases but in all applications it SHOULD NOT be. + * Returns null if it is not a plant. + */ +/obj/item/proc/get_plant_seed() + return null + +/obj/item/grown/get_plant_seed() + return seed + +/obj/item/reagent_containers/food/snacks/grown/get_plant_seed() + return seed diff --git a/code/modules/keybindings/focus.dm b/code/modules/keybindings/focus.dm index 205b293e9a1a..d542b4926700 100644 --- a/code/modules/keybindings/focus.dm +++ b/code/modules/keybindings/focus.dm @@ -1,6 +1,3 @@ -/mob - var/datum/focus //What receives our keyboard inputs. src by default - /mob/proc/set_focus(datum/new_focus) if(focus == new_focus) return diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 0fa649ac58f1..70542eee66fb 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -17,7 +17,7 @@ desc = "A great place for storing knowledge." anchored = FALSE density = TRUE - opacity = 0 + opacity = FALSE resistance_flags = FLAMMABLE max_integrity = 200 armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 50, ACID = 0) diff --git a/code/modules/lighting/lighting_area.dm b/code/modules/lighting/lighting_area.dm index ce3b6b70f4c9..58ee031d3281 100644 --- a/code/modules/lighting/lighting_area.dm +++ b/code/modules/lighting/lighting_area.dm @@ -1,5 +1,5 @@ /area - luminosity = TRUE + luminosity = TRUE var/dynamic_lighting = DYNAMIC_LIGHTING_ENABLED /area/proc/set_dynamic_lighting(new_dynamic_lighting = DYNAMIC_LIGHTING_ENABLED) diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm index 55b14cb513d7..6ffa5121b925 100644 --- a/code/modules/lighting/lighting_atom.dm +++ b/code/modules/lighting/lighting_atom.dm @@ -1,54 +1,48 @@ - -/atom - ///Light systems, both shouldn't be active at the same time. - var/light_system = STATIC_LIGHT - ///Range of the light in tiles. Zero means no light. - var/light_range = 0 - ///Intensity of the light. The stronger, the less shadows you will see on the lit area. - var/light_power = 1 - ///Hexadecimal RGB string representing the colour of the light. White by default. - var/light_color = COLOR_WHITE - ///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values. - var/light_on = TRUE - ///Bitflags to determine lighting-related atom properties. - var/light_flags = NONE - ///Our light source. Don't fuck with this directly unless you have a good reason! - var/tmp/datum/light_source/light - ///Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list. - var/tmp/list/light_sources - // The proc you should always use to set the light of this atom. -// Nonesensical value for l_color default, so we can detect if it gets set to null. -#define NONSENSICAL_VALUE -99999 -/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE) +/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE, l_angle, l_dir, l_on) + // We null everything but l_dir, because we don't want to allow for modifications while frozen + if(light_flags & LIGHT_FROZEN) + l_range = null + l_power = null + l_color = null + l_on = null + l_angle = null + if(l_range > 0 && l_range < MINIMUM_USEFUL_LIGHT_RANGE) - l_range = MINIMUM_USEFUL_LIGHT_RANGE //Brings the range up to 1.4, which is just barely brighter than the soft lighting that surrounds players. - if (l_power != null) - light_power = l_power + l_range = MINIMUM_USEFUL_LIGHT_RANGE //Brings the range up to 1.4, which is just barely brighter than the soft lighting that surrounds players. + + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT, l_range, l_power, l_color, l_on) & COMPONENT_BLOCK_LIGHT_UPDATE) + return - if (l_range != null) - light_range = l_range + if(!isnull(l_power)) + set_light_power(l_power) - if (l_color != NONSENSICAL_VALUE) - light_color = l_color + if(!isnull(l_range)) + set_light_range(l_range) - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT, l_range, l_power, l_color) + if(l_color != NONSENSICAL_VALUE) + set_light_color(l_color) - update_light() + if(!isnull(l_angle)) + set_light_angle(l_angle) + + if(!isnull(l_dir)) + set_light_dir(l_dir) + + if(!isnull(l_on)) + set_light_on(l_on) -#undef NONSENSICAL_VALUE + update_light() -// Will update the light (duh). -// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf... +/// Will update the light (duh). +/// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf... /atom/proc/update_light() - set waitfor = FALSE - if (QDELETED(src)) - return + SHOULD_NOT_SLEEP(TRUE) if(light_system != STATIC_LIGHT) CRASH("update_light() for [src] with following light_system value: [light_system]") - if (!light_power || !light_range) // We won't emit light anyways, destroy the light source. + if (!light_power || !light_range || !light_on) // We won't emit light anyways, destroy the light source. QDEL_NULL(light) else if (!ismovable(loc)) // We choose what atom should be the top atom of the light here. @@ -60,71 +54,37 @@ light.update(.) else light = new/datum/light_source(src, .) - -// If we have opacity, make sure to tell (potentially) affected light sources. -/atom/movable/Destroy() - var/turf/T = loc - . = ..() - if (opacity && istype(T)) - var/old_has_opaque_atom = T.has_opaque_atom - T.recalc_atom_opacity() - if (old_has_opaque_atom != T.has_opaque_atom) - T.reconsider_lights() - -// Should always be used to change the opacity of an atom. -// It notifies (potentially) affected light sources so they can update (if needed). + return . + +/** + * Updates the atom's opacity value. + * + * This exists to act as a hook for associated behavior. + * It notifies (potentially) affected light sources so they can update (if needed). + */ /atom/proc/set_opacity(new_opacity) - if (new_opacity == opacity) + if (new_opacity == opacity || light_flags & LIGHT_FROZEN) return - + SEND_SIGNAL(src, COMSIG_ATOM_SET_OPACITY, new_opacity) + . = opacity opacity = new_opacity - var/turf/T = loc - if (!isturf(T)) + return . + +/atom/movable/set_opacity(new_opacity) + . = ..() + if(isnull(.) || !isturf(loc)) return - if (new_opacity == TRUE) - T.has_opaque_atom = TRUE - T.reconsider_lights() + if(opacity) + AddElement(/datum/element/light_blocking) else - var/old_has_opaque_atom = T.has_opaque_atom - T.recalc_atom_opacity() - if (old_has_opaque_atom != T.has_opaque_atom) - T.reconsider_lights() - + RemoveElement(/datum/element/light_blocking) -/atom/movable/Moved(atom/OldLoc, Dir) +/turf/set_opacity(new_opacity) . = ..() - for (var/datum/light_source/light as anything in light_sources) // Cycle through the light sources on this atom and tell them to update. - light.source_atom.update_light() - -/atom/vv_edit_var(var_name, var_value) - switch (var_name) - if ("light_range") - if(light_system == STATIC_LIGHT) - set_light(l_range = var_value) - else - set_light_range(var_value) - datum_flags |= DF_VAR_EDITED - return TRUE - - if ("light_power") - if(light_system == STATIC_LIGHT) - set_light(l_power = var_value) - else - set_light_power(var_value) - datum_flags |= DF_VAR_EDITED - return TRUE - - if ("light_color") - if(light_system == STATIC_LIGHT) - set_light(l_color = var_value) - else - set_light_color(var_value) - datum_flags |= DF_VAR_EDITED - return TRUE - - return ..() - + if(isnull(.)) + return + recalculate_directional_opacity() /atom/proc/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) return @@ -132,59 +92,96 @@ /turf/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) if(!_duration) stack_trace("Lighting FX obj created on a turf without a duration") - new /obj/effect/dummy/lighting_obj (src, _range, _power, _color, _duration) + new /obj/effect/dummy/lighting_obj(src, _range, _power, _color, _duration) /obj/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) if(!_duration) stack_trace("Lighting FX obj created on a obj without a duration") - new /obj/effect/dummy/lighting_obj (get_turf(src), _range, _power, _color, _duration) - + new /obj/effect/dummy/lighting_obj(get_turf(src), _range, _power, _color, _duration) /mob/living/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) mob_light(_range, _power, _color, _duration) - -/mob/living/proc/mob_light(_range, _power, _color, _duration) - var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new (src, _range, _power, _color, _duration) +/mob/living/proc/mob_light(range, power, color, duration, light_type = /obj/effect/dummy/lighting_obj/moblight) + var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new light_type(src, range, power, color, duration) return mob_light_obj - +/// Setter for the light range of this atom. /atom/proc/set_light_range(new_range) - if(new_range == light_range) + if(new_range == light_range || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_RANGE, new_range) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_RANGE, new_range) . = light_range light_range = new_range + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_RANGE, .) + return . +/// Setter for the light power of this atom. /atom/proc/set_light_power(new_power) - if(new_power == light_power) + if(new_power == light_power || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_POWER, new_power) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_POWER, new_power) . = light_power light_power = new_power + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_POWER, .) + return . - +/// Setter for the light color of this atom. /atom/proc/set_light_color(new_color) - if(new_color == light_color) + if(new_color == light_color || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_COLOR, new_color) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_COLOR, new_color) . = light_color light_color = new_color + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_COLOR, .) + return . +/// Setter for the light angle of this atom +/atom/proc/set_light_angle(new_value) + if(new_value == light_angle || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ANGLE, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_angle + light_angle = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_ANGLE, .) + return . + +/// Setter for the light direction of this atom +/atom/proc/set_light_dir(new_value) + // No frozen check here because we allow direction changes in a freeze + if(new_value == light_dir) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_DIR, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_dir + light_dir = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_DIR, .) + return . +/// Setter for whether or not this atom's light is on. /atom/proc/set_light_on(new_value) - if(new_value == light_on) + if(new_value == light_on || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ON, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ON, new_value) . = light_on light_on = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_ON, .) + return . - +/// Setter for the light flags of this atom. /atom/proc/set_light_flags(new_value) - if(new_value == light_flags) + if(new_value == light_flags || (light_flags & LIGHT_FROZEN && new_value & LIGHT_FROZEN)) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_FLAGS, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) return - SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_FLAGS, new_value) . = light_flags light_flags = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_FLAGS, .) + return . diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 3eec3be05a23..93839a8a6e79 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -219,7 +219,7 @@ var/oldlum = source_turf.luminosity source_turf.luminosity = CEILING(light_range, 1) for(var/turf/T in view(CEILING(light_range, 1), source_turf)) - if(!T.has_opaque_atom) + if(!IS_OPAQUE_TURF(T)) if (!T.lighting_corners_initialised) T.generate_missing_corners() corners[T.lighting_corner_NE] = 0 diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index 406ed0ae09d0..871099973730 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -1,22 +1,3 @@ -/turf - var/dynamic_lighting = TRUE - luminosity = 1 - - var/tmp/lighting_corners_initialised = FALSE - - var/tmp/datum/lighting_object/lighting_object // Our lighting object. - - ///Lighting Corner datums. - var/tmp/datum/lighting_corner/lighting_corner_NE - var/tmp/datum/lighting_corner/lighting_corner_SE - var/tmp/datum/lighting_corner/lighting_corner_SW - var/tmp/datum/lighting_corner/lighting_corner_NW - - var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile. - - ///Lumcount added by sources other than lighting datum objects, such as the overlay lighting component. - var/dynamic_lumcount = 0 - // Causes any affecting light sources to be queued for a visibility update, for example a door got opened. /turf/proc/reconsider_lights() lighting_corner_NE?.vis_update() @@ -78,21 +59,39 @@ return !luminosity -// Can't think of a good name, this proc will recalculate the has_opaque_atom variable. -/turf/proc/recalc_atom_opacity() - has_opaque_atom = opacity - if (!has_opaque_atom) - for (var/atom/A in src.contents) // Loop through every movable atom on our tile PLUS ourselves (we matter too...) - if (A.opacity) - has_opaque_atom = TRUE - break +///Proc to add movable sources of opacity on the turf and let it handle lighting code. +/turf/proc/add_opacity_source(atom/movable/new_source) + LAZYADD(opacity_sources, new_source) + if(opacity) + return + recalculate_directional_opacity() -/turf/Exited(atom/movable/Obj, atom/newloc) - . = ..() - if (Obj && Obj.opacity) - recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates. - reconsider_lights() +///Proc to remove movable sources of opacity on the turf and let it handle lighting code. +/turf/proc/remove_opacity_source(atom/movable/old_source) + LAZYREMOVE(opacity_sources, old_source) + if(opacity) //Still opaque, no need to worry on updating. + return + recalculate_directional_opacity() + +///Calculate on which directions this turfs block view. +/turf/proc/recalculate_directional_opacity() + . = directional_opacity + if(opacity) + directional_opacity = ALL_CARDINALS + if(. != directional_opacity) + reconsider_lights() + return + directional_opacity = NONE + if(opacity_sources) + for(var/atom/movable/opacity_source as anything in opacity_sources) + if(opacity_source.flags_1 & ON_BORDER_1) + directional_opacity |= opacity_source.dir + else //If fulltile and opaque, then the whole tile blocks view, no need to continue checking. + directional_opacity = ALL_CARDINALS + break + if(. != directional_opacity && (. == ALL_CARDINALS || directional_opacity == ALL_CARDINALS)) + reconsider_lights() //The lighting system only cares whether the tile is fully concealed from all directions or not. /turf/proc/change_area(area/old_area, area/new_area) if(SSlighting.initialized) diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index 1187abb2c9d7..341a4ca9ab97 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -53,15 +53,12 @@ smells_like = "crackling sweetness" - var/obj/effect/dummy/lighting_obj/ethereal_light - + var/obj/effect/dummy/lighting_obj/moblight/species/ethereal_light /datum/species/ethereal/Destroy(force) - if(ethereal_light) - QDEL_NULL(ethereal_light) + QDEL_NULL(ethereal_light) return ..() - /datum/species/ethereal/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) . = ..() if(!ishuman(C)) @@ -70,7 +67,7 @@ var/mob/living/carbon/human/ethereal = C setup_color(ethereal) - ethereal_light = ethereal.mob_light() + ethereal_light = ethereal.mob_light(light_type = /obj/effect/dummy/lighting_obj/moblight/species) spec_updatehealth(ethereal) var/obj/item/organ/heart/ethereal/ethereal_heart = ethereal.getorganslot(ORGAN_SLOT_HEART) diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index eb87263056ab..0d21310381a0 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -442,19 +442,25 @@ id = "lum" say_mod = "says" var/glow_intensity = LUMINESCENT_DEFAULT_GLOW - var/obj/effect/dummy/luminescent_glow/glow var/obj/item/slime_extract/current_extract var/datum/action/innate/integrate_extract/integrate_extract var/datum/action/innate/use_extract/extract_minor var/datum/action/innate/use_extract/major/extract_major var/extract_cooldown = 0 + /// Internal dummy used to glow (very cool) + var/obj/effect/dummy/lighting_obj/moblight/species/glow + +/datum/species/jelly/luminescent/Destroy(force, ...) + . = ..() + QDEL_NULL(glow) + /datum/species/jelly/luminescent/on_species_loss(mob/living/carbon/C) ..() if(current_extract) current_extract.forceMove(C.drop_location()) current_extract = null - qdel(glow) + QDEL_NULL(glow) if(integrate_extract) integrate_extract.Remove(C) if(extract_minor) @@ -464,7 +470,7 @@ /datum/species/jelly/luminescent/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() - glow = new(C) + glow = C.mob_light(light_type = /obj/effect/dummy/lighting_obj/moblight/species) update_glow(C) integrate_extract = new(src) integrate_extract.Grant(C) @@ -484,20 +490,6 @@ glow_intensity = intensity glow.set_light_range_power_color(glow_intensity, glow_intensity, C.dna.features["mcolor"]) -/obj/effect/dummy/luminescent_glow - name = "luminescent glow" - desc = "Tell a coder if you're seeing this." - icon_state = "nothing" - light_color = "#FFFFFF" - light_range = LUMINESCENT_DEFAULT_GLOW - light_system = MOVABLE_LIGHT - light_power = 2.5 - -/obj/effect/dummy/luminescent_glow/Initialize(mapload) - . = ..() - if(!isliving(loc)) - return INITIALIZE_HINT_QDEL - /datum/action/innate/integrate_extract name = "Integrate Extract" desc = "Eat a slime extract to use its properties." diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 17afcab90d30..9fb6a32b9d80 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -9,6 +9,9 @@ mob_size = MOB_SIZE_TINY desc = "A generic pAI mobile hard-light holographics emitter. It seems to be deactivated." weather_immunities = list(WEATHER_ASH) + light_on = FALSE + light_flags = LIGHT_ATTACHED + light_system = MOVABLE_LIGHT health = 500 maxHealth = 500 layer = BELOW_MOB_LAYER diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm index 57d2045c373e..23c911e36ee2 100644 --- a/code/modules/mob/living/silicon/pai/pai_shell.dm +++ b/code/modules/mob/living/silicon/pai/pai_shell.dm @@ -34,7 +34,6 @@ if(client) client.perspective = EYE_PERSPECTIVE client.eye = src - set_light(0) icon_state = "[chassis]" held_state = "[chassis]" visible_message(span_boldnotice("[src] folds out its holochassis emitter and forms a holoshell around itself!")) @@ -63,7 +62,6 @@ forceMove(card) mobility_flags = NONE density = FALSE - set_light(0) holoform = FALSE set_resting(resting) @@ -93,12 +91,9 @@ return FALSE /mob/living/silicon/pai/proc/toggle_integrated_light() - if(!light_range) - set_light(brightness_power) - to_chat(src, span_notice("You enable your integrated light.")) - else - set_light(0) - to_chat(src, span_notice("You disable your integrated light.")) + set_light_on(!light_on) + set_light_range(brightness_power) + to_chat(src, span_notice("You [light_on ? "enable" : "disable"] your integrated light.")) /mob/living/silicon/pai/mob_try_pickup(mob/living/user) if(!possible_chassis[chassis]) diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm index da68ff11f309..6aa83963a038 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm @@ -55,7 +55,7 @@ /obj/guardian_bomb/proc/disguise(obj/A) A.forceMove(src) stored_obj = A - opacity = A.opacity + set_opacity(A.opacity) anchored = A.anchored density = A.density appearance = A.appearance diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index abf942d702fb..adfcd9c49fb9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -478,7 +478,7 @@ Difficulty: Medium icon = 'icons/effects/fire.dmi' icon_state = "1" anchored = TRUE - opacity = 0 + opacity = FALSE density = TRUE CanAtmosPass = ATMOS_PASS_DENSITY duration = 8.2 SECONDS diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 1ab5b77515ad..4ed3901312fe 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -14,7 +14,7 @@ icon = 'icons/effects/spacevines.dmi' icon_state = "flower_bud" layer = SPACEVINE_MOB_LAYER - opacity = 0 + opacity = FALSE canSmoothWith = list() smooth = SMOOTH_FALSE /// The amount of time it takes to create a venus human trap, in deciseconds diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 447b4b306f58..469261640cb2 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -221,4 +221,16 @@ var/list/alerts = list() // contains /atom/movable/screen/alert only // On /mob so clientless mobs will throw alerts properly + ///Contains the fullscreen overlays the mob can see (from 'code/_onclick/hud/fullscreen.dm') + var/list/screens = list() + + ///The HUD type the mob will gain on Initialize. (from 'code/_onclick/hud/hud.dm') + var/hud_type = /datum/hud + + ///The client colors the mob is looking at. (from 'code/modules/client/client_color.dm') + var/list/client_colours = list() + + ///What receives our keyboard inputs. src by default. (from 'code/modules/keybindings/focus.dm') + var/datum/focus + var/fake_client = FALSE // Currently only used for examines diff --git a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm index 42a4a73d74af..aa44118c5123 100644 --- a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm +++ b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm @@ -10,7 +10,7 @@ It is possible to destroy the net by the occupant or someone else. icon_state = "energynet" density = TRUE//Can't pass through. - opacity = 0//Can see through. + opacity = FALSE//Can see through. mouse_opacity = MOUSE_OPACITY_ICON//So you can hit it with stuff. anchored = TRUE//Can't drag/grab the net. layer = ABOVE_ALL_MOB_LAYER diff --git a/code/modules/pai/actions.dm b/code/modules/pai/actions.dm deleted file mode 100644 index 99f312dc917c..000000000000 --- a/code/modules/pai/actions.dm +++ /dev/null @@ -1,62 +0,0 @@ -/datum/action/innate/pai - name = "PAI Action" - background_icon = 'icons/mob/actions/actions_silicon.dmi' - var/mob/living/silicon/pai/pai_owner - -/datum/action/innate/pai/Trigger(trigger_flags) - if(!ispAI(owner)) - return FALSE - pai_owner = owner - -/datum/action/innate/pai/software - name = "Software Interface" - button_icon_state = "pai" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/software/Trigger(trigger_flags) - ..() - pai_owner.ui_act() - -/datum/action/innate/pai/shell - name = "Toggle Holoform" - button_icon_state = "pai_holoform" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/shell/Trigger(trigger_flags) - ..() - if(pai_owner.holoform) - pai_owner.fold_in(0) - else - pai_owner.fold_out() - -/datum/action/innate/pai/chassis - name = "Holochassis Appearance Composite" - button_icon_state = "pai_chassis" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/chassis/Trigger(trigger_flags) - ..() - pai_owner.choose_chassis() - -/datum/action/innate/pai/rest - name = "Rest" - button_icon_state = "pai_rest" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/rest/Trigger(trigger_flags) - ..() - var/mob/living/silicon/pai/pAI = usr - if(!pAI.resting) - pAI.set_resting(TRUE) - else - pAI.set_resting(FALSE) - -/datum/action/innate/pai/light - name = "Toggle Integrated Lights" - background_icon = 'icons/mob/actions/actions_spells.dmi' - button_icon_state = "emp" - background_icon_state = "bg_tech" - -/datum/action/innate/pai/light/Trigger(trigger_flags) - ..() - pai_owner.toggle_integrated_light() diff --git a/code/modules/pai/camera.dm b/code/modules/pai/camera.dm deleted file mode 100644 index 30b1918651e4..000000000000 --- a/code/modules/pai/camera.dm +++ /dev/null @@ -1,58 +0,0 @@ -/mob/living/silicon/pai/ClickOn(atom/target, params) - ..() - if(!camera?.in_camera_mode) - return FALSE - //pAI picture taking - camera.toggle_camera_mode(sound = FALSE) - camera.captureimage(target, usr, camera.picture_size_x - 1, camera.picture_size_y - 1) - return TRUE - -/obj/item/camera/siliconcam/pai_camera - name = "pAI photo camera" - light_color = COLOR_PAI_GREEN - -/obj/item/camera/siliconcam/pai_camera/after_picture(mob/user, datum/picture/picture) - var/number = length(stored) - picture.picture_name = "Image [number] (taken by [loc.name])" - stored[picture] = TRUE - playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, TRUE, -3) - balloon_alert(user, "image recorded") - -/** - * Handles selecting and printing stored images. - * - * @param {mob} user - The pAI. - * - * @returns {boolean} - TRUE if the pAI prints an image, - * FALSE otherwise. -*/ -/obj/item/camera/siliconcam/pai_camera/proc/pai_print(mob/user) - var/mob/living/silicon/pai/pai = loc - var/datum/picture/selection = selectpicture(user) - if(!istype(selection)) - balloon_alert(user, "invalid image") - return FALSE - printpicture(user, selection) - user.visible_message(span_notice("A picture appears on top of the chassis of [pai.name]!"), span_notice("You print a photograph.")) - return TRUE - -/** - * All inclusive camera proc. Zooms, snaps, prints. - * - * @param {mob} user - The pAI requesting the camera. - * - * @param {string} mode - The camera option to toggle. - * - * @returns {boolean} - TRUE if the camera worked. - */ -/mob/living/silicon/pai/proc/use_camera(mob/user, mode) - if(!camera || isnull(mode)) - return FALSE - switch(mode) - if(PAI_PHOTO_MODE_CAMERA) - camera.toggle_camera_mode(user) - if(PAI_PHOTO_MODE_PRINTER) - camera.pai_print(user) - if(PAI_PHOTO_MODE_ZOOM) - camera.adjust_zoom(user) - return TRUE diff --git a/code/modules/pai/candidate.dm b/code/modules/pai/candidate.dm deleted file mode 100644 index 6455492e1379..000000000000 --- a/code/modules/pai/candidate.dm +++ /dev/null @@ -1,35 +0,0 @@ -/** - * #pAI Candidate - * - * Created when a user opens the pAI submit interface. - * Stores the candidate in an associative list of ckey: candidate objects. - */ -/datum/pai_candidate - /// User inputted OOC comments - var/comments - /// User inputted behavior description - var/description - /// User's ckey - var/ckey - /// User's pAI name. If blank, ninja name. - var/name - /// If the user has hit "submit" - var/ready = FALSE - -/datum/pai_candidate/New(ckey) - src.ckey = ckey - -/** - * Checks if a candidate is ready so that they may be displayed or - * downloaded. Removes any invalid entries. - * - * @returns {boolean} - TRUE if the candidate is ready, FALSE if not - */ -/datum/pai_candidate/proc/check_ready() - var/mob/candidate_mob = get_mob_by_key(ckey) - if(!candidate_mob?.client || !isobserver(candidate_mob) || is_banned_from(ckey, ROLE_PAI)) - SSpai.candidates -= ckey - return FALSE - if(!ready) - return FALSE - return TRUE diff --git a/code/modules/pai/card.dm b/code/modules/pai/card.dm deleted file mode 100644 index fc50e1a2c04b..000000000000 --- a/code/modules/pai/card.dm +++ /dev/null @@ -1,260 +0,0 @@ -/obj/item/pai_card - name = "personal AI device" - desc = "Downloads personal AI assistants to accompany its owner or others." - icon = 'icons/obj/aicards.dmi' - icon_state = "pai" - item_state = "electronic" - lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' - resistance_flags = FIRE_PROOF | ACID_PROOF | INDESTRUCTIBLE - w_class = WEIGHT_CLASS_SMALL - slot_flags = ITEM_SLOT_BELT - cryo_preserve = TRUE - /// Spam alert prevention - var/alert_cooldown - /// The emotion icon displayed. - var/emotion_icon = "off" - /// Any pAI personalities inserted - var/mob/living/silicon/pai/pai - /// Prevents a crew member from hitting "request pAI" repeatedly - var/request_spam = FALSE - -/obj/item/pai_card/attackby(obj/item/used, mob/user, params) - if(pai && istype(used, /obj/item/encryptionkey)) - if(!pai.encrypt_mod) - to_chat(user, span_alert("Encryption Key ports not configured.")) - return - user.set_machine(src) - pai.radio.attackby(used, user, params) - to_chat(user, span_notice("You insert [used] into the [src].")) - return - return ..() - -/obj/item/pai_card/attack_self(mob/user) - if(!in_range(src, user)) - return - user.set_machine(src) - ui_interact(user) - -/obj/item/pai_card/Destroy() - //Will stop people throwing friend pAIs into the singularity so they can respawn - SSpai.pai_card_list.Remove(src) - if(!QDELETED(pai)) - QDEL_NULL(pai) - return ..() - -/obj/item/pai_card/emag_act(mob/user, obj/item/card/emag/emag_card) - if(!pai) - return FALSE - return pai.handle_emag(user, emag_card) - -/obj/item/pai_card/emp_act(severity) - . = ..() - if (. & EMP_PROTECT_SELF) - return - if(pai && !pai.holoform) - pai.emp_act(severity) - -/obj/item/pai_card/handle_atom_del(atom/thing) - if(thing == pai) //double check /mob/living/silicon/pai/Destroy() if you change these. - pai = null - emotion_icon = initial(emotion_icon) - update_appearance(UPDATE_ICON) - return ..() - -/obj/item/pai_card/Initialize(mapload) - . = ..() - update_appearance(UPDATE_ICON) - SSpai.pai_card_list += src - -/obj/item/pai_card/suicide_act(mob/living/user) - user.visible_message(span_suicide("[user] is staring sadly at [src]! [user.p_they()] can't keep living without real human intimacy!")) - return OXYLOSS - -/obj/item/pai_card/update_overlays() - . = ..() - . += "pai-[emotion_icon]" - if(pai?.hacking_cable) - . += "[initial(icon_state)]-connector" - -/obj/item/pai_card/vv_edit_var(vname, vval) - . = ..() - if(vname == NAMEOF(src, emotion_icon)) - update_appearance(UPDATE_ICON) - -/obj/item/pai_card/ui_interact(mob/user, datum/tgui/ui) - . = ..() - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "PaiCard") - ui.open() - -/obj/item/pai_card/ui_status(mob/user) - if(user in get_nested_locs(src)) - return UI_INTERACTIVE - return ..() - -/obj/item/pai_card/ui_data(mob/user) - . = ..() - var/list/data = list() - if(!pai) - data["candidates"] = pool_candidates() || list() - return data - data["pai"] = list( - can_holo = pai.can_holo, - dna = pai.master_dna, - emagged = pai.emagged, - laws = pai.laws.supplied, - master = pai.master_name, - name = pai.name, - transmit = pai.can_transmit, - receive = pai.can_receive, - ) - return data - -/obj/item/pai_card/ui_act(action, list/params, datum/tgui/ui) - . = ..() - if(.) - return TRUE - // Actions that don't require a pAI - if(action == "download") - download_candidate(usr, params["ckey"]) - return TRUE - if(action == "request") - find_pai(usr) - return TRUE - // pAI specific actions. - if(!pai) - return FALSE - switch(action) - if("fix_speech") - pai.fix_speech() - return TRUE - if("reset_software") - pai.reset_software() - return TRUE - if("set_dna") - pai.set_dna(usr) - return TRUE - if("set_laws") - pai.set_laws(usr) - return TRUE - if("toggle_holo") - pai.toggle_holo() - return TRUE - if("toggle_radio") - pai.toggle_radio(params["option"]) - return TRUE - if("wipe_pai") - pai.wipe_pai(usr) - ui.close() - return TRUE - return FALSE - -/** Flashes the pai card screen */ -/obj/item/pai_card/proc/add_alert() - if(pai) - return - add_overlay( - list(mutable_appearance(icon, "[initial(icon_state)]-alert"), - mutable_appearance(icon, "[initial(icon_state)]-alert", src, alpha = src.alpha))) - -/** Removes any overlays */ -/obj/item/pai_card/proc/remove_alert() - if(pai) - return - cut_overlays() - -/** Alerts pAI cards that someone has submitted candidacy */ -/obj/item/pai_card/proc/alert_update() - if(!COOLDOWN_FINISHED(src, alert_cooldown)) - return - COOLDOWN_START(src, alert_cooldown, 5 SECONDS) - add_alert() - addtimer(CALLBACK(src, PROC_REF(remove_alert)), 5 SECONDS) - playsound(src, 'sound/machines/ping.ogg', 30, TRUE) - visible_message(span_notice("[src] flashes a message across its screen: New personalities available for download!"), blind_message = span_notice("[src] vibrates with an alert.")) - -/** - * Downloads a candidate from the list and removes them from SSpai.candidates - * - * @param {string} ckey The ckey of the candidate to download - * - * @returns {boolean} - TRUE if the candidate was downloaded, FALSE if not - */ -/obj/item/pai_card/proc/download_candidate(mob/user, ckey) - if(pai) - return FALSE - var/datum/pai_candidate/candidate = SSpai.candidates[ckey] - if(!candidate?.check_ready()) - balloon_alert(user, "download interrupted") - return FALSE - var/mob/living/silicon/pai/new_pai = new(src) - new_pai.name = candidate.name || pick(GLOB.ninja_names) - new_pai.real_name = new_pai.name - new_pai.key = candidate.ckey - set_personality(new_pai) - SSpai.candidates -= ckey - return TRUE - -/** - * Pings ghosts to announce that someone is requesting a pAI - * - * @param {mob} user - The user who is requesting a pAI - * - * @returns {boolean} - TRUE if the pAI was requested, FALSE if not - */ -/obj/item/pai_card/proc/find_pai(mob/user) - if(pai) - return FALSE - if(!(GLOB.ghost_role_flags & GHOSTROLE_SILICONS)) - balloon_alert(user, "unavailable: NT blacklisted") - return FALSE - if(request_spam) - balloon_alert(user, "request sent too recently") - return FALSE - request_spam = TRUE - playsound(src, 'sound/machines/ping.ogg', 20, TRUE) - balloon_alert(user, "pAI assistance requested") - var/mutable_appearance/alert_overlay = mutable_appearance('icons/obj/aicards.dmi', "pai") - notify_ghosts("[user] is requesting a pAI companion! Use the pAI button to submit yourself as one.", source = user, alert_overlay = alert_overlay, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "pAI Request!", ignore_key = POLL_IGNORE_PAI) - addtimer(VARSET_CALLBACK(src, request_spam, FALSE), PAI_SPAM_TIME, TIMER_UNIQUE | TIMER_STOPPABLE | TIMER_CLIENT_TIME | TIMER_DELETE_ME) - return TRUE - -/** - * Gathers a list of candidates to display in the download candidate - * window. If the candidate isn't marked ready, ie they have not - * pressed submit, they will be skipped over. - * - * @returns - An array of candidate objects. - */ -/obj/item/pai_card/proc/pool_candidates() - var/list/candidates = list() - if(pai || !length(SSpai?.candidates)) - return candidates - for(var/key in SSpai.candidates) - var/datum/pai_candidate/candidate = SSpai.candidates[key] - if(!candidate?.check_ready()) - continue - candidates += list(list( - ckey = candidate.ckey, - comments = candidate.comments, - description = candidate.description, - name = candidate.name, - )) - return candidates - -/** - * Sets the personality on the current pai_card - * - * @param {silicon/pai} downloaded - The new pAI to load into the card. - */ -/obj/item/pai_card/proc/set_personality(mob/living/silicon/pai/downloaded) - if(pai) - return FALSE - pai = downloaded - emotion_icon = "null" - update_appearance(UPDATE_ICON) - playsound(src, 'sound/effects/pai_boot.ogg', 50, TRUE, -1) - audible_message("[src] plays a cheerful startup noise!") - return TRUE diff --git a/code/modules/pai/death.dm b/code/modules/pai/death.dm deleted file mode 100644 index 2168f46796fb..000000000000 --- a/code/modules/pai/death.dm +++ /dev/null @@ -1,19 +0,0 @@ -/mob/living/silicon/pai/death(gibbed) - if(stat == DEAD) - return - set_stat(DEAD) - update_sight() - clear_fullscreens() - /** - * New pAI's get a brand new mind to prevent meta stuff from their previous - * life. This new mind causes problems down the line if it's not deleted here. - */ - ghostize() - - if (!QDELETED(card) && loc != card) - card.forceMove(drop_location()) - card.pai = null - card.emotion_icon = initial(card.emotion_icon) - card.update_appearance(UPDATE_ICON) - - qdel(src) diff --git a/code/modules/pai/debug.dm b/code/modules/pai/debug.dm deleted file mode 100644 index 63d6a8eb5020..000000000000 --- a/code/modules/pai/debug.dm +++ /dev/null @@ -1,45 +0,0 @@ -/client/proc/makepAI(turf/target in GLOB.mob_list) - set category = "Admin.Fun" - set name = "Make pAI" - set desc = "Specify a location to spawn a pAI device, then specify a key to play that pAI" - - var/list/available = list() - for(var/mob/player as anything in GLOB.player_list) - if(player.client && player.key) - available.Add(player) - var/mob/choice = tgui_input_list(usr, "Choose a player to play the pAI", "Spawn pAI", available) - if(isnull(choice)) - return - - var/chosen_name = input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text|null - if (isnull(chosen_name)) - return - - if(!isobserver(choice)) - var/confirm = tgui_alert(usr, "[choice.key] isn't ghosting right now. Are you sure you want to yank them out of their body and place them in this pAI?", "Spawn pAI Confirmation", list("Yes", "No")) - if(confirm != "Yes") - return - var/obj/item/pai_card/card = new(target) - var/mob/living/silicon/pai/pai = new(card) - - pai.name = chosen_name - pai.real_name = pai.name - pai.key = choice.key - card.set_personality(pai) - if(SSpai.candidates[key]) - SSpai.candidates -= key - SSblackbox.record_feedback("tally", "admin_verb", 1, "Make pAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/** - * Creates a new pAI. - * - * @param {boolean} delete_old - If TRUE, deletes the old pAI. - */ -/mob/proc/make_pai(delete_old) - var/obj/item/pai_card/card = new(src) - var/mob/living/silicon/pai/pai = new(card) - pai.key = key - pai.name = name - card.set_personality(pai) - if(delete_old) - qdel(src) diff --git a/code/modules/pai/defense.dm b/code/modules/pai/defense.dm deleted file mode 100644 index cfe1211778ed..000000000000 --- a/code/modules/pai/defense.dm +++ /dev/null @@ -1,90 +0,0 @@ -/mob/living/silicon/pai/blob_act(obj/structure/blob/B) - return FALSE - -/mob/living/silicon/pai/emp_act(severity) - . = ..() - if(. & EMP_PROTECT_SELF) - return - take_holo_damage(50 / severity) - Stun(40 SECONDS / severity) - if(holoform) - fold_in(force = TRUE) - //Need more effects that aren't instadeath or permanent law corruption. - //Ask and you shall receive - switch(rand(1, 3)) - if(1) - stuttering = 1 MINUTES / severity - to_chat(src, span_danger("Warning: Feedback loop detected in speech module.")) - if(2) - slurring = INFINITY - to_chat(src, span_danger("Warning: Audio synthesizer CPU stuck.")) - if(3) - derpspeech = INFINITY - to_chat(src, span_danger("Warning: Vocabulary databank corrupted.")) - if(prob(40)) - mind.language_holder.selected_language = get_random_spoken_language() - - -/mob/living/silicon/pai/ex_act(severity, target) - take_holo_damage(50 * severity) - switch(severity) - if(EXPLODE_DEVASTATE) //RIP - qdel(card) - qdel(src) - if(EXPLODE_HEAVY) - fold_in(force = 1) - Paralyze(400) - if(EXPLODE_LIGHT) - fold_in(force = 1) - Paralyze(200) - -/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user, list/modifiers) - if(user.a_intent == INTENT_HELP) - visible_message(span_notice("[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.")) - return - user.do_attack_animation(src) - if(user.name != master_name) - visible_message(span_danger("[user] stomps on [src]!.")) - take_holo_damage(2) - return - visible_message(span_notice("Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence.")) - if(!do_after(user, 1 SECONDS, src)) - return - fold_in() - if(user.put_in_hands(card)) - user.visible_message(span_notice("[user] promptly scoops up [user.p_their()] pAI's card.")) - -/mob/living/silicon/pai/bullet_act(obj/projectile/Proj) - if(Proj.stun) - fold_in(force = TRUE) - src.visible_message(span_warning("The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!")) - . = ..(Proj) - -/mob/living/silicon/pai/ignite_mob(silent) - return FALSE - -/mob/living/silicon/pai/proc/take_holo_damage(amount) - holochassis_health = clamp((holochassis_health - amount), -50, HOLOCHASSIS_MAX_HEALTH) - if(holochassis_health < 0) - fold_in(force = TRUE) - if(amount > 0) - to_chat(src, span_userdanger("The impact degrades your holochassis!")) - return amount - -/mob/living/silicon/pai/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_status) - return take_holo_damage(amount) - -/mob/living/silicon/pai/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, required_status) - return take_holo_damage(amount) - -/mob/living/silicon/pai/adjustStaminaLoss(amount, updating_stamina, forced = FALSE, required_status) - if(forced) - take_holo_damage(amount) - else - take_holo_damage(amount * 0.25) - -/mob/living/silicon/pai/getBruteLoss() - return HOLOCHASSIS_MAX_HEALTH - holochassis_health - -/mob/living/silicon/pai/getFireLoss() - return HOLOCHASSIS_MAX_HEALTH - holochassis_health diff --git a/code/modules/pai/door_jack.dm b/code/modules/pai/door_jack.dm deleted file mode 100644 index 75cf0fe9b442..000000000000 --- a/code/modules/pai/door_jack.dm +++ /dev/null @@ -1,129 +0,0 @@ -#define CABLE_LENGTH 2 - -/** - * Switch that handles door jack operations. - * - * @param {string} mode - The requested operation of the door jack. - * - * @returns {boolean} - TRUE if the door jack state was switched, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/door_jack(mode) - if(isnull(mode)) - return FALSE - switch(mode) - if(PAI_DOOR_JACK_CABLE) - extend_cable() - return TRUE - if(PAI_DOOR_JACK_HACK) - hack_door() - return TRUE - if(PAI_DOOR_JACK_CANCEL) - QDEL_NULL(hacking_cable) - visible_message(span_notice("The cable retracts into the pAI.")) - return TRUE - return FALSE - -/** - * #Extend cable supporting proc - * - * When doorjack is installed, allows the pAI to drop - * a cable which is placed either on the floor or in - * someone's hands based (on distance). - * - * @returns {boolean} - TRUE if the cable was dropped, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/extend_cable() - QDEL_NULL(hacking_cable) //clear any old cables - hacking_cable = new - var/mob/living/carbon/hacker = get_holder() - if(iscarbon(hacker) && hacker.put_in_hands(hacking_cable)) //important to double check since get_holder can return non-null values that aren't carbons. - hacker.visible_message(span_notice("A port on [src] opens to reveal a cable, which [hacker] quickly grabs."), span_notice("A port on [src] opens to reveal a cable, which you quickly grab."), span_hear("You hear the soft click of a plastic component and manage to catch the falling cable.")) - track_pai() - track_thing(hacking_cable) - return TRUE - hacking_cable.forceMove(drop_location()) - hacking_cable.visible_message(message = span_notice("A port on [src] opens to reveal a cable, which promptly falls to the floor."), blind_message = span_hear("You hear the soft click of a plastic component fall to the ground.")) - track_pai() - track_thing(hacking_cable) - return TRUE - -/** Tracks the associated pai */ -/mob/living/silicon/pai/proc/track_pai() - RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move)) - RegisterSignal(card, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move)) - -/** Untracks the associated pai */ -/mob/living/silicon/pai/proc/untrack_pai() - UnregisterSignal(src, COMSIG_MOVABLE_MOVED) - UnregisterSignal(card, COMSIG_MOVABLE_MOVED) - -/** Tracks the associated hacking_cable */ -/mob/living/silicon/pai/proc/track_thing(atom/movable/thing) - RegisterSignal(thing, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move)) - var/list/locations = get_nested_locs(thing, include_turf = FALSE) - for(var/atom/movable/location in locations) - RegisterSignal(location, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move)) - -/** Untracks the associated hacking */ -/mob/living/silicon/pai/proc/untrack_thing(atom/movable/thing) - UnregisterSignal(thing, COMSIG_MOVABLE_MOVED) - var/list/locations = get_nested_locs(thing, include_turf = FALSE) - for(var/atom/movable/location in locations) - UnregisterSignal(location, COMSIG_MOVABLE_MOVED) - -/** - * A periodic check to see if the source pAI is nearby. - * Deletes the extended cable if the source pAI is not nearby. - */ -/mob/living/silicon/pai/proc/handle_move(atom/movable/source, atom/movable/old_loc) - if(ismovable(old_loc)) - untrack_thing(old_loc) - if(hacking_cable && (!IN_GIVEN_RANGE(src, hacking_cable, CABLE_LENGTH))) - retract_cable() - return - if(ismovable(source.loc)) - track_thing(source.loc) - -/** - * Handles deleting the hacking cable and notifying the user. - */ -/mob/living/silicon/pai/proc/retract_cable() - balloon_alert(src, "cable retracted") - untrack_pai() - QDEL_NULL(hacking_cable) - return TRUE - -/** - * #Door jacking supporting proc - * - * After a 15 second timer, the door will crack open, - * provided they don't move out of the way. - * - * @returns {boolean} - TRUE if the door was jacked, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/hack_door() - if(!hacking_cable) - return FALSE - if(!hacking_cable.machine) - balloon_alert(src, "nothing connected") - return FALSE - playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, TRUE) - balloon_alert(src, "overriding...") - // Now begin hacking - if(!do_after(src, 15 SECONDS, hacking_cable.machine, timed_action_flags = NONE, progress = TRUE)) - balloon_alert(src, "failed! retracting...") - untrack_pai() - untrack_thing(hacking_cable) - QDEL_NULL(hacking_cable) - if(!QDELETED(card)) - card.update_appearance(UPDATE_ICON) - return FALSE - var/obj/machinery/door/door = hacking_cable.machine - balloon_alert(src, "success") - door.open() - untrack_pai() - untrack_thing(hacking_cable) - QDEL_NULL(hacking_cable) - return TRUE - -#undef CABLE_LENGTH diff --git a/code/modules/pai/hud.dm b/code/modules/pai/hud.dm deleted file mode 100644 index 3c53c96395a3..000000000000 --- a/code/modules/pai/hud.dm +++ /dev/null @@ -1,267 +0,0 @@ -#define PAI_MISSING_SOFTWARE_MESSAGE span_warning("You must download the required software to use this.") - -/atom/movable/screen/pai - icon = 'icons/mob/screen_pai.dmi' - var/required_software - -/atom/movable/screen/pai/Click() - if(isobserver(usr) || usr.incapacitated()) - return FALSE - var/mob/living/silicon/pai/user = usr - if(required_software && !user.installed_software.Find(required_software)) - to_chat(user, PAI_MISSING_SOFTWARE_MESSAGE) - return FALSE - return TRUE - -/atom/movable/screen/pai/software - name = "Software Interface" - icon_state = "pai" - -/atom/movable/screen/pai/software/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.ui_interact(pAI) - -/atom/movable/screen/pai/shell - name = "Toggle Holoform" - icon_state = "pai_holoform" - -/atom/movable/screen/pai/shell/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - if(pAI.holoform) - pAI.fold_in(0) - else - pAI.fold_out() - -/atom/movable/screen/pai/chassis - name = "Holochassis Appearance Composite" - icon_state = "pai_chassis" - -/atom/movable/screen/pai/chassis/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.choose_chassis() - -/atom/movable/screen/pai/rest - name = "Rest" - icon_state = "pai_rest" - -/atom/movable/screen/pai/rest/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - if(pAI.resting) - pAI.set_resting(FALSE) - else - pAI.set_resting(TRUE) - -/atom/movable/screen/pai/light - name = "Toggle Integrated Lights" - icon_state = "light" - -/atom/movable/screen/pai/light/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.toggle_integrated_light() - -/atom/movable/screen/pai/newscaster - name = "pAI Newscaster" - icon_state = "newscaster" - required_software = "Newscaster" - -/atom/movable/screen/pai/newscaster/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.newscaster.ui_interact(usr) - -/atom/movable/screen/pai/host_monitor - name = "Host Health Scan" - icon_state = "host_monitor" - required_software = "Host Scan" - -/atom/movable/screen/pai/host_monitor/Click(location, control, params) - . = ..() - if(!.) - return - var/mob/living/silicon/pai/pAI = usr - pAI.host_scan(PAI_SCAN_TARGET) - return TRUE - -/atom/movable/screen/pai/crew_manifest - name = "Crew Manifest" - icon_state = "manifest" - required_software = "Crew Manifest" - -/atom/movable/screen/pai/crew_manifest/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.ai_roster() - -/atom/movable/screen/pai/state_laws - name = "State Laws" - icon_state = "state_laws" - -/atom/movable/screen/pai/state_laws/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.checklaws() - -/atom/movable/screen/pai/modpc - name = "Messenger" - icon_state = "pda_send" - required_software = "Digital Messenger" - var/mob/living/silicon/pai/pAI - -/atom/movable/screen/pai/modpc/Click() - . = ..() - if(!.) // this works for some reason. - return - pAI.modularInterface?.interact(pAI) - -/atom/movable/screen/pai/internal_gps - name = "Internal GPS" - icon_state = "internal_gps" - required_software = "Internal GPS" - -/atom/movable/screen/pai/internal_gps/Click() - . = ..() - if(!.) - return - var/mob/living/silicon/pai/pAI = usr - if(!pAI.internal_gps) - pAI.internal_gps = new(pAI) - pAI.internal_gps.attack_self(pAI) - -/atom/movable/screen/pai/image_take - name = "Take Image" - icon_state = "take_picture" - required_software = "Photography Module" - -/atom/movable/screen/pai/image_take/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.camera.toggle_camera_mode(usr) - -/atom/movable/screen/pai/image_view - name = "View Images" - icon_state = "view_images" - required_software = "Photography Module" - -/atom/movable/screen/pai/image_view/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.camera.viewpictures(usr) - -/atom/movable/screen/pai/radio - name = "radio" - icon = 'icons/mob/screen_cyborg.dmi' - icon_state = "radio" - -/atom/movable/screen/pai/radio/Click() - if(!..()) - return - var/mob/living/silicon/pai/pAI = usr - pAI.radio.interact(usr) - -/datum/hud/pai/New(mob/living/silicon/pai/owner) - ..() - var/atom/movable/screen/using - var/mob/living/silicon/pai/mypai = mymob - -// Software menu - using = new /atom/movable/screen/pai/software(src) - using.screen_loc = ui_pai_software - static_inventory += using - -// Holoform - using = new /atom/movable/screen/pai/shell(src) - using.screen_loc = ui_pai_shell - static_inventory += using - -// Chassis Select Menu - using = new /atom/movable/screen/pai/chassis(src) - using.screen_loc = ui_pai_chassis - static_inventory += using - -// Rest - using = new /atom/movable/screen/pai/rest(src) - using.screen_loc = ui_pai_rest - static_inventory += using - -// Integrated Light - using = new /atom/movable/screen/pai/light(src) - using.screen_loc = ui_pai_light - static_inventory += using - -// Newscaster - using = new /atom/movable/screen/pai/newscaster(src) - using.screen_loc = ui_pai_newscaster - static_inventory += using - -// Language menu - using = new /atom/movable/screen/language_menu(src) - using.screen_loc = ui_pai_language_menu - static_inventory += using - -// Host Monitor - using = new /atom/movable/screen/pai/host_monitor(src) - using.screen_loc = ui_pai_host_monitor - static_inventory += using - -// Crew Manifest - using = new /atom/movable/screen/pai/crew_manifest(src) - using.screen_loc = ui_pai_crew_manifest - static_inventory += using - -// Laws - using = new /atom/movable/screen/pai/state_laws(src) - using.screen_loc = ui_pai_state_laws - static_inventory += using - -// Modular Interface - using = new /atom/movable/screen/pai/modpc(src) - using.screen_loc = ui_pai_mod_int - static_inventory += using - mypai.pda_button = using - var/atom/movable/screen/pai/modpc/tablet_button = using - tablet_button.pAI = mypai - -// Internal GPS - using = new /atom/movable/screen/pai/internal_gps(src) - using.screen_loc = ui_pai_internal_gps - static_inventory += using - -// Take image - using = new /atom/movable/screen/pai/image_take(src) - using.screen_loc = ui_pai_take_picture - static_inventory += using - -// View images - using = new /atom/movable/screen/pai/image_view(src) - using.screen_loc = ui_pai_view_images - static_inventory += using - -// Radio - using = new /atom/movable/screen/pai/radio(src) - using.screen_loc = ui_pai_radio - static_inventory += using - - update_software_buttons() - -/datum/hud/pai/proc/update_software_buttons() - var/mob/living/silicon/pai/owner = mymob - for(var/atom/movable/screen/pai/button in static_inventory) - if(button.required_software) - button.color = owner.installed_software.Find(button.required_software) ? null : "#808080" - -#undef PAI_MISSING_SOFTWARE_MESSAGE diff --git a/code/modules/pai/login.dm b/code/modules/pai/login.dm deleted file mode 100644 index 0f418c4bf32b..000000000000 --- a/code/modules/pai/login.dm +++ /dev/null @@ -1,10 +0,0 @@ -/mob/living/silicon/pai/Login() - . = ..() - if(!. || !client) - return FALSE - - client.perspective = EYE_PERSPECTIVE - if(holoform) - client.eye = src - else - client.eye = card diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm deleted file mode 100644 index 022802f46da2..000000000000 --- a/code/modules/pai/pai.dm +++ /dev/null @@ -1,412 +0,0 @@ -/mob/living/silicon/pai - can_be_held = TRUE - density = FALSE - desc = "A generic pAI hard-light holographics emitter." - health = 500 - held_lh = 'icons/mob/pai_item_lh.dmi' - held_rh = 'icons/mob/pai_item_rh.dmi' - held_icon = 'icons/mob/pai_item_head.dmi' - hud_type = /datum/hud/pai - icon = 'icons/mob/pai.dmi' - icon_state = "repairbot" - job = "Personal AI" - layer = BELOW_MOB_LAYER - light_color = COLOR_PAI_GREEN - light_flags = LIGHT_ATTACHED - light_on = FALSE - light_range = 3 - light_system = MOVABLE_LIGHT - maxHealth = 500 - mob_size = MOB_SIZE_TINY - mobility_flags = MOBILITY_FLAGS_DEFAULT - mouse_opacity = MOUSE_OPACITY_ICON - move_force = 0 - move_resist = 0 - name = "pAI" - pass_flags = PASSTABLE | PASSMOB - pull_force = 0 - radio = /obj/item/radio/headset/silicon/pai - worn_slot_flags = ITEM_SLOT_HEAD - - /// If someone has enabled/disabled the pAIs ability to holo - var/can_holo = TRUE - /// Whether this pAI can recieve radio messages - var/can_receive = TRUE - /// Whether this pAI can transmit radio messages - var/can_transmit = TRUE - /// The card we inhabit - var/obj/item/pai_card/card - /// The current chasis that will appear when in holoform - var/chassis = "repairbot" - /// Toggles whether the pAI can hold encryption keys or not - var/encrypt_mod = FALSE - /// The cable we produce when hacking a door - var/obj/item/pai_cable/hacking_cable - /// The current health of the holochassis - var/holochassis_health = 20 - /// Holochassis available to use - var/holochassis_ready = FALSE - /// Whether we are currently holoformed - var/holoform = FALSE - /// Installed software on the pAI - var/list/installed_software = list() - /// Toggles whether universal translator has been activated. Cannot be reversed - var/languages_granted = FALSE - /// Reference of the bound master - var/datum/weakref/master_ref - /// The master's name string - var/master_name - /// DNA string for owner verification - var/master_dna - /// Toggles whether the Medical HUD is active or not - var/medHUD = FALSE - /// Used as currency to purchase different abilities - var/ram = 100 - /// Toggles whether the Security HUD is active or not - var/secHUD = FALSE - - // Onboard Items - /// Atmospheric analyzer - var/obj/item/analyzer/atmos_analyzer - /// Health analyzer - var/obj/item/healthanalyzer/host_scan - /// GPS - var/obj/item/gps/internal/internal_gps - /// Music Synthesizer - var/obj/item/instrument/piano_synth/instrument - /// Newscaster - var/obj/machinery/newscaster/pai/newscaster - /// PDA - var/atom/movable/screen/ai/modpc/pda_button - /// Photography module - var/obj/item/camera/siliconcam/pai_camera/camera - /// Remote signaler - var/obj/item/assembly/signaler/internal/signaler - - // Static lists - /// List of all available downloads - var/static/list/available_software = list( - "Atmospheric Sensor" = 5, - "Crew Manifest" = 5, - "Digital Messenger" = 5, - "Photography Module" = 5, - "Encryption Slot" = 10, - "Music Synthesizer" = 10, - "Newscaster" = 10, - "Remote Signaler" = 10, - "Host Scan" = 20, - "Medical HUD" = 20, - "Security HUD" = 20, - "Crew Monitor" = 35, - "Door Jack" = 35, - "Internal GPS" = 35, - "Universal Translator" = 35, - ) - /// List of all possible chasises. TRUE means the pAI can be picked up in this chasis. - var/static/list/possible_chassis = list( - "cat" = TRUE, - "corgi" = FALSE, - "fox" = FALSE, - "monkey" = TRUE, - "mouse" = TRUE, - "rabbit" = TRUE, - ) - /// List of all available card overlays. - var/static/list/possible_overlays = list( - "null", - "angry", - "cat", - "extremely-happy", - "face", - "happy", - "laugh", - "off", - "sad", - "sunglasses", - "what" - ) - -/mob/living/silicon/pai/add_sensors() //pAIs have to buy their HUDs - return - -/mob/living/silicon/pai/can_interact_with(atom/target) - if(target == signaler) // Bypass for signaler - return TRUE - if(target == modularInterface) - return TRUE - return ..() - -/mob/living/silicon/pai/Destroy() - QDEL_NULL(atmos_analyzer) - QDEL_NULL(camera) - QDEL_NULL(hacking_cable) - QDEL_NULL(host_scan) - QDEL_NULL(instrument) - QDEL_NULL(internal_gps) - QDEL_NULL(newscaster) - QDEL_NULL(signaler) - card = null - GLOB.pai_list.Remove(src) - return ..() - -/mob/living/silicon/pai/emag_act(mob/user, obj/item/card/emag/emag_card) - return handle_emag(user, emag_card) - -/mob/living/silicon/pai/examine(mob/user) - . = ..() - . += "Its master ID string seems to be [(!master_name || emagged) ? "empty" : master_name]." - -/mob/living/silicon/pai/get_status_tab_items() - . += ..() - if(!stat) - . += text("Emitter Integrity: [holochassis_health * (100 / HOLOCHASSIS_MAX_HEALTH)].") - else - . += text("Systems nonfunctional.") - -/mob/living/silicon/pai/handle_atom_del(atom/deleting_atom) - if(deleting_atom == hacking_cable) - untrack_pai() - untrack_thing(hacking_cable) - hacking_cable = null - SStgui.update_user_uis(src) - if(!QDELETED(card)) - card.update_appearance(UPDATE_ICON) - if(deleting_atom == atmos_analyzer) - atmos_analyzer = null - if(deleting_atom == camera) - camera = null - if(deleting_atom == host_scan) - host_scan = null - if(deleting_atom == internal_gps) - internal_gps = null - if(deleting_atom == instrument) - instrument = null - if(deleting_atom == newscaster) - newscaster = null - if(deleting_atom == signaler) - signaler = null - return ..() - -/mob/living/silicon/pai/Initialize(mapload) - . = ..() - START_PROCESSING(SSfastprocess, src) - GLOB.pai_list += src - make_laws() - for(var/law in laws.inherent) - lawcheck += law - var/obj/item/pai_card/pai_card = loc - if(!istype(pai_card)) // when manually spawning a pai, we create a card to put it into. - var/newcardloc = pai_card - pai_card = new(newcardloc) - pai_card.set_personality(src) - forceMove(pai_card) - card = pai_card - addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_INIT_TIME) - if(!holoform) - Immobilize(50 MINUTES) - desc = "A pAI hard-light holographics emitter. This one appears in the form of a [chassis]." - - RegisterSignal(src, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(on_cult_sacrificed)) - -/mob/living/silicon/pai/make_laws() - laws = new /datum/ai_laws/pai() - return TRUE - -/mob/living/silicon/pai/process(delta_time) - holochassis_health = clamp((holochassis_health + (HOLOCHASSIS_REGEN_PER_SECOND * delta_time)), -50, HOLOCHASSIS_MAX_HEALTH) - -/mob/living/silicon/pai/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) - . = ..() - if(!.) - add_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK, update = TRUE, priority = 100, multiplicative_slowdown = 2) - return TRUE - remove_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK, TRUE) - return TRUE - -/mob/living/silicon/pai/screwdriver_act(mob/living/user, obj/item/tool) - return radio.screwdriver_act(user, tool) - -/mob/living/silicon/pai/updatehealth() - if(status_flags & GODMODE) - return - set_health(maxHealth - getBruteLoss() - getFireLoss()) - update_stat() - SEND_SIGNAL(src, COMSIG_LIVING_HEALTH_UPDATE) - -/** - * Resolves the weakref of the pai's master. - * If the master has been deleted, calls reset_software(). - * - * @returns {mob/living || FALSE} - The master mob, or - * FALSE if the master is gone. - */ -/mob/living/silicon/pai/proc/find_master() - if(!master_ref) - return FALSE - var/mob/living/resolved_master = master_ref?.resolve() - if(!resolved_master) - reset_software() - return FALSE - return resolved_master - -/** - * Fixes weird speech issues with the pai. - * - * @returns {boolean} - TRUE if successful. - */ -/mob/living/silicon/pai/proc/fix_speech() - var/mob/living/silicon/pai = src - balloon_alert(pai, "speech modulation corrected") - stuttering = 0 - slurring = 0 - derpspeech = 0 - - return TRUE - -/** - * Gets the current holder of the pAI if its - * being carried in card or holoform. - * - * @returns {living/carbon || FALSE} - The holder of the pAI, - * or FALSE if the pAI is not being carried. - */ -/mob/living/silicon/pai/proc/get_holder() - var/mob/living/carbon/holder - if(!holoform && iscarbon(card.loc)) - holder = card.loc - if(holoform && ispickedupmob(loc) && iscarbon(loc.loc)) - holder = loc.loc - if(!holder || !iscarbon(holder)) - return FALSE - return holder - -/** - * Handles the pai card or the pai itself being hit with an emag. - * This replaces any current laws, masters, and DNA. - * - * @param {living/carbon} attacker - The user performing the action. - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/handle_emag(mob/living/carbon/attacker, obj/item/card/emag/emag_card) - if(!isliving(attacker)) - return FALSE - balloon_alert(attacker, "directive override complete") - balloon_alert(src, "directive override detected") - log_game("[key_name(attacker)] emagged [key_name(src)], wiping their master DNA and supplemental directive.") - emagged = TRUE - master_ref = WEAKREF(attacker) - master_name = "The Syndicate" - master_dna = "Untraceable Signature" - // Sets supplemental directive to this - laws.supplied[1] = "Do not interfere with the operations of the Syndicate." - return TRUE - -/** - * Resets the pAI and any emagged status. - * - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/reset_software() - emagged = FALSE - if(!master_ref) - return FALSE - master_ref = null - master_name = null - master_dna = null - add_supplied_law(0, "None.") - balloon_alert(src, "software rebooted") - return TRUE - -/** - * Imprints your DNA onto the downloaded pAI - * - * @param {mob} user - The user performing the imprint. - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/set_dna(mob/user) - if(!iscarbon(user)) - balloon_alert(user, "incompatible DNA signature") - balloon_alert(src, "incompatible DNA signature") - return FALSE - if(emagged) - balloon_alert(user, "directive system malfunctional") - return FALSE - var/mob/living/carbon/master = user - master_ref = WEAKREF(master) - master_name = master.real_name - master_dna = master.dna.unique_enzymes - to_chat(src, span_boldannounce("You have been bound to a new master: [user.real_name]!")) - holochassis_ready = TRUE - return TRUE - -/** - * Opens a tgui alert that allows someone to enter laws. - * - * @param {mob} user - The user performing the law change. - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/set_laws(mob/user) - if(!master_ref) - balloon_alert(user, "access denied: no master") - return FALSE - var/new_laws = tgui_input_text(user, "Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", laws.supplied[1], 300) - if(!new_laws || !master_ref) - return FALSE - add_supplied_law(0, new_laws) - to_chat(src, span_notice(new_laws)) - return TRUE - -/** - * Toggles the ability of the pai to enter holoform - * - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/toggle_holo() - balloon_alert(src, "holomatrix [can_holo ? "disabled" : "enabled"]") - can_holo = !can_holo - return TRUE - -/** - * Toggles the radio settings on and off. - * - * @param {string} option - The option being toggled. - */ -/mob/living/silicon/pai/proc/toggle_radio(option) - // it can't be both so if we know it's not transmitting it must be receiving. - var/transmitting = option == "transmit" - var/transmit_holder = (transmitting ? WIRE_TX : WIRE_RX) - if(transmitting) - can_transmit = !can_transmit - else //receiving - can_receive = !can_receive - radio.wires.cut(transmit_holder)//wires.cut toggles cut and uncut states - transmit_holder = (transmitting ? can_transmit : can_receive) //recycling can be fun! - balloon_alert(src, "[transmitting ? "outgoing" : "incoming"] radio [transmit_holder ? "enabled" : "disabled"]") - return TRUE - -/** - * Wipes the current pAI on the card. - * - * @param {mob} user - The user performing the action. - * - * @returns {boolean} - TRUE if successful, FALSE if not. - */ -/mob/living/silicon/pai/proc/wipe_pai(mob/user) - if(tgui_alert(user, "Are you certain you wish to delete the current personality? This action cannot be undone.", "Personality Wipe", list("Yes", "No")) != "Yes") - return FALSE - to_chat(src, span_warning("You feel yourself slipping away from reality.")) - to_chat(src, span_danger("Byte by byte you lose your sense of self.")) - to_chat(src, span_userdanger("Your mental faculties leave you.")) - to_chat(src, span_rose("oblivion... ")) - balloon_alert(user, "personality wiped") - playsound(src, "sound/machines/buzz-two.ogg", 30, TRUE) - qdel(src) - return TRUE - -/// Signal proc for [COMSIG_LIVING_CULT_SACRIFICED] to give a funny message when a pai is attempted to be sac'd -/mob/living/silicon/pai/proc/on_cult_sacrificed(datum/source, list/invokers) - SIGNAL_HANDLER - - for(var/mob/living/cultist as anything in invokers) - to_chat(cultist, span_cultitalic("You don't think this is what Nar'Sie had in mind when She asked for blood sacrifices...")) - return STOP_SACRIFICE diff --git a/code/modules/pai/personality.dm b/code/modules/pai/personality.dm deleted file mode 100644 index 92cf5747801f..000000000000 --- a/code/modules/pai/personality.dm +++ /dev/null @@ -1,56 +0,0 @@ -/** - * name - * key - * description - * role - * comments - * ready = TRUE - */ - -/datum/pai_candidate/proc/savefile_path(mob/user) - return "data/player_saves/[user.ckey[1]]/[user.ckey]/pai.sav" - -/datum/pai_candidate/proc/savefile_save(mob/user) - if(is_guest_key(user.key)) - to_chat(usr, span_warning("You cannot save pAI information as a guest.")) - return FALSE - var/savefile/F = new /savefile(src.savefile_path(user)) - WRITE_FILE(F["name"], name) - WRITE_FILE(F["description"], description) - WRITE_FILE(F["comments"], comments) - WRITE_FILE(F["version"], 1) - to_chat(usr, span_boldnotice("You have saved pAI information locally.")) - return TRUE - -// loads the savefile corresponding to the mob's ckey -// if silent=true, report incompatible savefiles -// returns TRUE if loaded (or file was incompatible) -// returns FALSE if savefile did not exist - -/datum/pai_candidate/proc/savefile_load(mob/user, silent = TRUE) - if (is_guest_key(user.key)) - return FALSE - - var/path = savefile_path(user) - - if (!fexists(path)) - return FALSE - - var/savefile/F = new /savefile(path) - - if(!F) - return //Not everyone has a pai savefile. - - var/version = null - F["version"] >> version - - if (isnull(version) || version != 1) - fdel(path) - if (!silent) - tgui_alert(user, "Your savefile was incompatible with this version and was deleted.") - return FALSE - - F["name"] >> src.name - F["description"] >> src.description - F["comments"] >> src.comments - return TRUE diff --git a/code/modules/pai/say.dm b/code/modules/pai/say.dm deleted file mode 100644 index b35abfe7f9d8..000000000000 --- a/code/modules/pai/say.dm +++ /dev/null @@ -1,2 +0,0 @@ -/mob/living/silicon/pai/binarycheck() - return radio?.translate_binary diff --git a/code/modules/pai/shell.dm b/code/modules/pai/shell.dm deleted file mode 100644 index 66e2e8bfb279..000000000000 --- a/code/modules/pai/shell.dm +++ /dev/null @@ -1,169 +0,0 @@ -/mob/living/silicon/pai/mob_try_pickup(mob/living/user, instant=FALSE) - if(!possible_chassis[chassis]) - to_chat(user, span_warning("[src]'s current form isn't able to be carried!")) - return FALSE - return ..() - -/mob/living/silicon/pai/start_pulling(atom/movable/thing, state, force = move_force, supress_message = FALSE) - return FALSE - -/mob/living/silicon/pai/update_resting() - . = ..() - if(resting) - icon_state = "[chassis]_rest" - else - icon_state = "[chassis]" - if(loc != card) - visible_message(span_notice("[src] [resting? "lays down for a moment..." : "perks up from the ground."]")) - -/mob/living/silicon/pai/wabbajack_act(what_to_randomize, change_flags = WABBAJACK) - if(length(possible_chassis) < 2) - return FALSE - var/holochassis = pick(possible_chassis - chassis) - set_holochassis(holochassis) - balloon_alert(src, "[holochassis] composite engaged") - return TRUE - -/** - * Checks if we are allowed to interact with a radial menu - * - * @param {atom} anchor - The atom that is anchoring the menu. - * - * @returns {boolean} - TRUE if we are allowed to interact with the menu, - * FALSE otherwise. - */ -/mob/living/silicon/pai/proc/check_menu(atom/anchor) - if(incapacitated()) - return FALSE - if(get_turf(src) != get_turf(anchor)) - return FALSE - if(!isturf(loc) && loc != card) - balloon_alert(src, "can't do that here") - return FALSE - return TRUE - -/** - * Sets a new holochassis skin based on a pAI's choice. - * - * @returns {boolean} - True if the skin was successfully set. - * FALSE otherwise. - */ -/mob/living/silicon/pai/proc/choose_chassis() - var/list/skins = list() - for(var/holochassis_option in possible_chassis) - var/image/item_image = image(icon = src.icon, icon_state = holochassis_option) - skins += list("[holochassis_option]" = item_image) - var/atom/anchor = get_atom_on_turf(src) - var/choice = show_radial_menu(src, anchor, skins, custom_check = CALLBACK(src, PROC_REF(check_menu), anchor), radius = 40, require_near = TRUE) - if(!choice) - return FALSE - set_holochassis(choice) - balloon_alert(src, "[choice] composite engaged") - update_resting() - return TRUE - -/** - * Returns the pAI to card mode. - * - * @param {boolean} force - If TRUE, the pAI will be forced to card mode. - * - * @returns {boolean} - TRUE if the pAI was forced to card mode. - * FALSE otherwise. - */ -/mob/living/silicon/pai/proc/fold_in(force = FALSE) - holochassis_ready = FALSE - if(!force) - addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_COOLDOWN) - else - addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_OVERLOAD_COOLDOWN) - icon_state = "[chassis]" - if(!holoform) - . = fold_out(force) - return FALSE - visible_message(span_notice("[src] deactivates its holochassis emitter and folds back into a compact card!")) - stop_pulling() - if(ispickedupmob(loc)) - var/obj/item/clothing/mob_holder/mob_head = loc - mob_head.release(display_messages = FALSE) - if(client) - client.perspective = EYE_PERSPECTIVE - var/turf/target = drop_location() - card.forceMove(target) - forceMove(card) - Immobilize(30 MINUTES) - set_density(FALSE) - set_light_on(FALSE) - holoform = FALSE - set_resting(resting) - return TRUE - -/** - * Engage holochassis form. - * - * @param {boolean} force - Force the form to engage. - * - * @returns {boolean} - TRUE if the form was successfully engaged. - * FALSE otherwise. - */ -/mob/living/silicon/pai/proc/fold_out(force = FALSE) - if(holochassis_health < 0) - balloon_alert(src, "emitter repair incomplete") - return FALSE - if(!can_holo && !force) - balloon_alert(src, "emitters are disabled") - return FALSE - if(holoform) - . = fold_in(force) - return - if(!holochassis_ready) - balloon_alert(src, "emitters recycling...") - return FALSE - holochassis_ready = FALSE - addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_COOLDOWN) - SetImmobilized(0) - set_density(TRUE) - if(istype(card.loc, /obj/item/modular_computer)) - var/obj/item/modular_computer/pc = card.loc - pc.inserted_pai = null - pc.visible_message(span_notice("[src] ejects itself from [pc]!")) - if(isliving(card.loc)) - var/mob/living/living_holder = card.loc - if(!living_holder.temporarilyRemoveItemFromInventory(card)) - balloon_alert(src, "unable to expand") - return FALSE - forceMove(get_turf(card)) - card.forceMove(src) - if(client) - client.perspective = EYE_PERSPECTIVE - client.eye = src - set_light_on(FALSE) - icon_state = "[chassis]" - held_state = "[chassis]" - visible_message(span_boldnotice("[src] folds out its holochassis emitter and forms a holoshell around itself!")) - holoform = TRUE - return TRUE - -/** - * Sets the holochassis skin and updates the icons - * - * @param {string} choice - The skin that will be used for the pAI holoform - * - * @returns {boolean} - TRUE if the skin was successfully set. FALSE otherwise. - */ -/mob/living/silicon/pai/proc/set_holochassis(choice) - if(!choice) - return FALSE - chassis = choice - icon_state = "[chassis]" - held_state = "[chassis]" - desc = "A pAI mobile hard-light holographics emitter. This one appears in the form of a [chassis]." - return TRUE - -/** - * Toggles the onboard light - * - * @returns {boolean} - TRUE if the light was toggled. - */ -/mob/living/silicon/pai/proc/toggle_integrated_light() - set_light_on(!light_on) - return TRUE diff --git a/code/modules/pai/software.dm b/code/modules/pai/software.dm deleted file mode 100644 index 9fb5cf109e78..000000000000 --- a/code/modules/pai/software.dm +++ /dev/null @@ -1,242 +0,0 @@ -/mob/living/silicon/pai/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "PaiInterface", name) - ui.open() - ui.set_autoupdate(FALSE) - -/mob/living/silicon/pai/ui_data(mob/user) - var/list/data = list() - data["door_jack"] = hacking_cable - data["image"] = card.emotion_icon - data["installed"] = installed_software - data["ram"] = ram - return data - -/mob/living/silicon/pai/ui_static_data(mob/user) - var/list/data = list() - data["available"] = available_software - data["directives"] = laws.supplied - data["emagged"] = emagged - data["languages"] = languages_granted - data["master_name"] = master_name - data["master_dna"] = master_dna - return data - -/mob/living/silicon/pai/ui_act(action, list/params, datum/tgui/ui) - . = ..() - if(.) - return TRUE - if(action == "buy") - buy_software(params["selection"]) - return TRUE - if(action == "change image") - change_image() - return TRUE - if(action == "check dna") - check_dna() - return TRUE - // Software related ui actions - if(available_software[action] && !installed_software.Find(action)) - balloon_alert(usr, "software unavailable") - return FALSE - switch(action) - if("Atmospheric Sensor") - atmos_analyzer.attack_self(src) - return TRUE - if("Crew Manifest") - ai_roster() - return TRUE - if("Crew Monitor") - GLOB.crewmonitor.show(usr, src) - return TRUE - if("Digital Messenger") - modularInterface?.interact(usr) - return TRUE - if("Door Jack") - // Look to door_jack.dm for implementation - door_jack(params["mode"]) - return TRUE - if("Encryption Slot") - balloon_alert(usr, "radio frequencies [!encrypt_mod ? "enabled" : "disabled"]") - encrypt_mod = !encrypt_mod - radio.subspace_transmission = !radio.subspace_transmission - return TRUE - if("Host Scan") - host_scan(params["mode"]) - return TRUE - if("Internal GPS") - internal_gps.attack_self(src) - return TRUE - if("Music Synthesizer") - instrument.interact(src) - return TRUE - if("Medical HUD") - toggle_hud(PAI_TOGGLE_MEDICAL_HUD) - return TRUE - if("Newscaster") - newscaster.ui_interact(src) - return TRUE - if("Photography Module") - // Look to pai_camera.dm for implementation - use_camera(usr, params["mode"]) - return TRUE - if("Remote Signaler") - signaler.ui_interact(src) - return TRUE - if("Security HUD") - toggle_hud(PAI_TOGGLE_SECURITY_HUD) - return TRUE - if("Universal Translator") - grant_languages() - ui.send_full_update() - return TRUE - return FALSE - -/** - * Purchases the selected software from the list and deducts their - * available ram. - * - * @param {string} selection - The software to purchase. - * - * @returns {boolean} - TRUE if the software was purchased, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/buy_software(selection) - if(!available_software[selection] || installed_software.Find(selection)) - return FALSE - var/cost = available_software[selection] - if(ram < cost) - return FALSE - installed_software.Add(selection) - ram -= cost - var/datum/hud/pai/pAIhud = hud_used - pAIhud?.update_software_buttons() - switch(selection) - if("Atmospheric Sensor") - atmos_analyzer = new(src) - if("Digital Messenger") - create_modularInterface() - if("Host Scan") - host_scan = new(src) - if("Internal GPS") - internal_gps = new(src) - if("Music Synthesizer") - instrument = new(src) - if("Newscaster") - newscaster = new(src) - if("Photography Module") - camera = new(src) - if("Remote Signaler") - signaler = new(src) - return TRUE - -/** - * Changes the image displayed on the pAI. - * - * @param {mob} user - The user who is changing the image. - * - * @returns {boolean} - TRUE if the image was changed, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/change_image() - var/new_image = tgui_input_list(src, "Select your new display image", "Display Image", possible_overlays) - if(isnull(new_image)) - return FALSE - card.emotion_icon = new_image - card.update_appearance(UPDATE_ICON) - return TRUE - -/** - * Supporting proc for the pAI to prick it's master's hand - * or... whatever. It must be held in order to work - * Gives the owner a popup if they want to get the jab. - * - * @returns {boolean} - TRUE if a sample was taken, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/check_dna() - if(emagged) // Their master DNA signature is scrambled anyway - to_chat(src, span_syndradio("You are not at liberty to do this! All agents are clandestine.")) - return FALSE - var/mob/living/carbon/holder = get_holder() - if(!iscarbon(holder)) - balloon_alert(src, "not being carried") - return FALSE - balloon_alert(src, "requesting dna sample") - if(tgui_alert(holder, "[src] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "Checking DNA", list("Yes", "No")) != "Yes") - balloon_alert(src, "dna sample refused!") - return FALSE - holder.visible_message(span_notice("[holder] presses [holder.p_their()] thumb against [src]."), span_notice("You press your thumb against [src]."), span_notice("[src] makes a sharp clicking sound as it extracts DNA material from [holder].")) - if(!holder.has_dna()) - balloon_alert(src, "no dna detected!") - return FALSE - to_chat(src, span_boldannounce(("[holder]'s UE string: [holder.dna.unique_enzymes]"))) - to_chat(src, span_notice("DNA [holder.dna.unique_enzymes == master_dna ? "matches" : "does not match"] our stored Master's DNA.")) - return TRUE - -/** - * Grant all languages to the current pAI. - * - * @returns {boolean} - TRUE if the languages were granted, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/grant_languages() - if(languages_granted) - return FALSE - grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_SOFTWARE) - languages_granted = TRUE - return TRUE - -/** - * Host scan supporting proc - * - * Allows the pAI to scan its host's health vitals - * using an integrated health analyzer. - * - * @returns {boolean} - TRUE if the scan was successful, FALSE otherwise. - */ -/mob/living/silicon/pai/proc/host_scan(mode) - if(isnull(mode)) - return FALSE - if(mode == PAI_SCAN_TARGET) - var/mob/living/target = get_holder() - if(!target || !isliving(target)) - balloon_alert(src, "not being carried") - return FALSE - host_scan.attack(target, src) - return TRUE - if(mode == PAI_SCAN_MASTER) - if(!master_ref) - balloon_alert(src, "no master detected") - return FALSE - var/mob/living/resolved_master = find_master() - if(!resolved_master) - balloon_alert(src, "cannot locate master") - return FALSE - if(!is_valid_z_level(get_turf(src), get_turf(resolved_master))) - balloon_alert(src, "master out of range") - return FALSE - host_scan.attack(resolved_master, src) - return TRUE - return FALSE - -/** - * Proc that toggles any active huds based on the option. - * - * @param {string} mode - The hud to toggle. - */ -/mob/living/silicon/pai/proc/toggle_hud(mode) - if(isnull(mode)) - return FALSE - var/datum/atom_hud/hud - var/hud_on - if(mode == PAI_TOGGLE_MEDICAL_HUD) - hud = GLOB.huds[med_hud] - medHUD = !medHUD - hud_on = medHUD - if(mode == PAI_TOGGLE_SECURITY_HUD) - hud = GLOB.huds[sec_hud] - secHUD = !secHUD - hud_on = secHUD - if(hud_on) - hud.show_to(src) - else - hud.hide_from(src) - return TRUE diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 7c9f48b664a3..ede43e165e3c 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -9,8 +9,8 @@ #define LIGHT_BROKEN 2 #define LIGHT_BURNED 3 -#define BROKEN_SPARKS_MIN (30 SECONDS) -#define BROKEN_SPARKS_MAX (90 SECONDS) +#define BROKEN_SPARKS_MIN (3 MINUTES) +#define BROKEN_SPARKS_MAX (9 MINUTES) #define LIGHT_ON_DELAY_UPPER 3 SECONDS #define LIGHT_ON_DELAY_LOWER 1 SECONDS @@ -488,7 +488,7 @@ update() /obj/machinery/light/proc/broken_sparks(start_only=FALSE) - if(status == LIGHT_BROKEN && has_power() && Master.current_runlevel) + if(!QDELETED(src) && status == LIGHT_BROKEN && has_power() && Master.current_runlevel) if(!start_only) do_sparks(3, TRUE, src) var/delay = rand(BROKEN_SPARKS_MIN, BROKEN_SPARKS_MAX) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index fd9b2520b42d..4056f1421fe0 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -14,7 +14,6 @@ light_system = MOVABLE_LIGHT light_range = 2 light_color = LIGHT_COLOR_RED - light_flags = LIGHT_NO_LUMCOUNT ricochets_max = 50 //Honk! ricochet_chance = 80 reflectable = REFLECT_NORMAL diff --git a/code/modules/projectiles/projectile/special/plasma.dm b/code/modules/projectiles/projectile/special/plasma.dm index 3e027fcee9c8..b98bba4951d8 100644 --- a/code/modules/projectiles/projectile/special/plasma.dm +++ b/code/modules/projectiles/projectile/special/plasma.dm @@ -13,7 +13,6 @@ impact_type = /obj/effect/projectile/impact/plasma_cutter light_system = MOVABLE_LIGHT light_color = LIGHT_COLOR_PURPLE - light_flags = LIGHT_NO_LUMCOUNT light_range = 2 /obj/projectile/plasma/weak diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 78b7b6d14d72..dd838e18ccfb 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -377,7 +377,7 @@ on_mob.forceMove(scanning) for(var/i in 1 to light_beam_distance) scanning = get_step(scanning, scandir) - if(scanning.opacity || scanning.has_opaque_atom) + if(IS_OPAQUE_TURF(scanning)) stop = TRUE var/obj/effect/abstract/eye_lighting/L = LAZYACCESS(eye_lighting, i) if(stop) diff --git a/icons/effects/light_overlays/light_cone.dmi b/icons/effects/light_overlays/light_cone.dmi new file mode 100644 index 000000000000..75f322a93717 Binary files /dev/null and b/icons/effects/light_overlays/light_cone.dmi differ diff --git a/yogstation.dme b/yogstation.dme index bd31f5205480..e935c6d4c486 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -17,6 +17,7 @@ #include "code\__byond_version_compat.dm" #include "code\_compile_options.dm" #include "code\world.dm" +#include "code\__DEFINES\_bitfields.dm" #include "code\__DEFINES\_click.dm" #include "code\__DEFINES\_globals.dm" #include "code\__DEFINES\_helpers.dm" @@ -184,7 +185,6 @@ #include "code\__DEFINES\{yogs_defines}\atmospherics.dm" #include "code\__DEFINES\{yogs_defines}\components.dm" #include "code\__DEFINES\{yogs_defines}\DNA.dm" -#include "code\__DEFINES\{yogs_defines}\flags.dm" #include "code\__DEFINES\{yogs_defines}\flavor_misc.dm" #include "code\__DEFINES\{yogs_defines}\is_helpers.dm" #include "code\__DEFINES\{yogs_defines}\logging.dm" @@ -663,6 +663,7 @@ #include "code\datums\elements\footstep_override.dm" #include "code\datums\elements\frozen.dm" #include "code\datums\elements\life_drain.dm" +#include "code\datums\elements\light_blocking.dm" #include "code\datums\elements\movetype_handler.dm" #include "code\datums\elements\regenerator.dm" #include "code\datums\elements\rust.dm" diff --git a/yogstation/code/game/machinery/doors/poddoor.dm b/yogstation/code/game/machinery/doors/poddoor.dm index 22b1f3a9b15f..2ca22fb2a4bf 100644 --- a/yogstation/code/game/machinery/doors/poddoor.dm +++ b/yogstation/code/game/machinery/doors/poddoor.dm @@ -3,28 +3,28 @@ layer = CLOSED_DOOR_LAYER closingLayer = CLOSED_DOOR_LAYER -/obj/machinery/door/poddoor/multi_tile/New() +/obj/machinery/door/poddoor/multi_tile/Initialize(mapload) . = ..() apply_opacity_to_my_turfs(opacity) +/obj/machinery/door/poddoor/multi_tile/Destroy(force=FALSE) + apply_opacity_to_my_turfs(0) + return ..() + /obj/machinery/door/poddoor/multi_tile/open() - if(..()) + . = ..() + if(.) apply_opacity_to_my_turfs(opacity) - /obj/machinery/door/poddoor/multi_tile/close() - if(..()) + . = ..() + if(.) apply_opacity_to_my_turfs(opacity) -/obj/machinery/door/poddoor/multi_tile/Destroy() - apply_opacity_to_my_turfs(0) - return ..() - //Multi-tile poddoors don't turn invisible automatically, so we change the opacity of the turfs below instead one by one. /obj/machinery/door/poddoor/multi_tile/proc/apply_opacity_to_my_turfs(new_opacity) for(var/turf/T in locs) - T.opacity = new_opacity - T.has_opaque_atom = new_opacity + T.set_opacity(new_opacity) T.reconsider_lights() T.air_update_turf(1) update_freelook_sight() diff --git a/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm b/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm index db2087d4c817..4990a34d07d3 100644 --- a/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm +++ b/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm @@ -136,12 +136,12 @@ var/mob/living/carbon/M = H var/datum/mutation/human/glow/G = M.dna.get_mutation(GLOWY) if(G) - G.glowth.set_light(0, 0) // Set glowy to no light + G.glow.set_light_range_power_color(range = 0, power = 0) // Set glowy to no light if(G.current_nullify_timer) deltimer(G.current_nullify_timer) // Stacks - G.current_nullify_timer = addtimer(CALLBACK(src, PROC_REF(giveGlowyBack), M), 40 SECONDS, TIMER_STOPPABLE) + G.current_nullify_timer = addtimer(CALLBACK(src, PROC_REF(give_glow_back), M), 40 SECONDS, TIMER_STOPPABLE) -/datum/action/cooldown/spell/aoe/proc/giveGlowyBack(mob/living/carbon/M) +/datum/action/cooldown/spell/aoe/proc/give_glow_back(mob/living/carbon/M) if(!M) return var/datum/mutation/human/glow/G = M.dna.get_mutation(GLOWY) diff --git a/yogstation/code/modules/spacepods/spacepod.dm b/yogstation/code/modules/spacepods/spacepod.dm index 5e12e48dbacb..73b9bf4e6306 100644 --- a/yogstation/code/modules/spacepods/spacepod.dm +++ b/yogstation/code/modules/spacepods/spacepod.dm @@ -12,7 +12,7 @@ GLOBAL_LIST_INIT(spacepods_list, list()) icon = 'goon/icons/obj/spacepods/construction_2x2.dmi' icon_state = "pod_1" density = 1 - opacity = 0 + opacity = FALSE dir = NORTH // always points north because why not layer = SPACEPOD_LAYER bound_width = 64