* pee * strange reagent fix * smell mop * throwing? * evaporation + more effects * Update pyrotechnic_reagents.dm * doors/airlocks * smell mop * Update liquid_groups.dm * borbop changes * breathing in liquids * fixes liquids going into dense tiles * increases mopcap to 45 * liquids fixes * lol * more liquid stuff * fixes this * more changes * fix all this stupid stuff * fix phantom pixel * liquid pump fix * gives you better ability to scoop things up * fix liquid pump * BUUURN BABY BURN + blud * slipping reaction checking * change liquid push reaction * removes liquid_fire_power
@@ -303,6 +303,7 @@ GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0))
|
||||
#define LAVALAND_DEFAULT_ATMOS "o2=14;n2=23;TEMP=300"
|
||||
#define ICEMOON_DEFAULT_ATMOS "o2=14;n2=23;TEMP=180"
|
||||
#define JUNGLELAND_DEFAULT_ATMOS "o2=44;n2=164;TEMP=300" //yogs edit
|
||||
#define OCEAN_DEFAULT_ATMOS "o2=10;co2=10;TEMP=293.15"
|
||||
|
||||
//ATMOSIA GAS MONITOR TAGS
|
||||
#define ATMOS_GAS_MONITOR_INPUT_O2 "o2_in"
|
||||
|
||||
@@ -44,3 +44,4 @@
|
||||
#define COMSIG_ATOM_SECONDARY_TOOL_ACT(tooltype) "tool_secondary_act_[tooltype]"
|
||||
// We have the same returns here as COMSIG_ATOM_TOOL_ACT
|
||||
// #define COMPONENT_BLOCK_TOOL_ATTACK (1<<0)
|
||||
#define COMSIG_ATOM_DOOR_OPEN "atom_door_open"
|
||||
|
||||
@@ -47,3 +47,13 @@
|
||||
#define COMSIG_TURF_IGNITED "turf_ignited"
|
||||
///Prevents hotspots and turf fires
|
||||
#define SUPPRESS_FIRE (1<<0)
|
||||
|
||||
///called on liquid creation
|
||||
#define COMSIG_TURF_LIQUIDS_CREATION "turf_liquids_creation"
|
||||
|
||||
#define COMSIG_TURF_MOB_FALL "turf_mob_fall"
|
||||
|
||||
///this is called whenever a turf is destroyed
|
||||
#define COMSIG_TURF_DESTROY "turf_destroy"
|
||||
///this is called whenever a turfs air is updated
|
||||
#define COMSIG_TURF_UPDATE_AIR "turf_air_change"
|
||||
|
||||
@@ -165,6 +165,8 @@ DEFINE_BITFIELD(smoothing_junction, list(
|
||||
#define SMOOTH_GROUP_BAMBOO_WALLS S_TURF(17) //![/turf/closed/wall/mineral/bamboo, /obj/structure/falsewall/bamboo]
|
||||
#define SMOOTH_GROUP_PLASTINUM_WALLS S_TURF(18) //![turf/closed/indestructible/riveted/plastinum]
|
||||
#define SMOOTH_GROUP_CLOCKWORK_WALLS S_TURF(19) //![/turf/closed/wall/clockwork, /obj/structure/falsewall/brass]
|
||||
#define SMOOTH_GROUP_ELEVATED_PLASTEEL S_TURF(20)
|
||||
#define SMOOTH_GROUP_LOWERED_PLASTEEL S_TURF(21)
|
||||
|
||||
#define SMOOTH_GROUP_PAPERFRAME S_OBJ(21) ///obj/structure/window/paperframe, /obj/structure/mineral_door/paperframe
|
||||
|
||||
@@ -208,6 +210,8 @@ DEFINE_BITFIELD(smoothing_junction, list(
|
||||
|
||||
#define SMOOTH_GROUP_GAS_TANK S_OBJ(72)
|
||||
|
||||
#define SMOOTH_GROUP_WATER S_OBJ(73) ///obj/effect/abstract/liquid_turf
|
||||
|
||||
|
||||
/// Performs the work to set smoothing_groups and canSmoothWith.
|
||||
/// An inlined function used in both turf/Initialize and atom/Initialize.
|
||||
|
||||
@@ -83,3 +83,5 @@
|
||||
#define MOVESPEED_ID_RESIN_FOAM "RESIN_FOAM"
|
||||
|
||||
#define MOVESPEED_ID_SYNTH_SUSPICION "SYNTH_SUSPICION"
|
||||
|
||||
#define MOVESPEED_ID_LIQUID "LIQUID"
|
||||
|
||||
@@ -332,3 +332,13 @@
|
||||
//Wardrobe callback master list indexes
|
||||
#define WARDROBE_CALLBACK_INSERT 1
|
||||
#define WARDROBE_CALLBACK_REMOVE 2
|
||||
|
||||
///liquid defines
|
||||
#define SSLIQUIDS_RUN_TYPE_TURFS 1
|
||||
#define SSLIQUIDS_RUN_TYPE_GROUPS 2
|
||||
#define SSLIQUIDS_RUN_TYPE_IMMUTABLES 3
|
||||
#define SSLIQUIDS_RUN_TYPE_EVAPORATION 4
|
||||
#define SSLIQUIDS_RUN_TYPE_FIRE 5
|
||||
#define SSLIQUIDS_RUN_TYPE_OCEAN 6
|
||||
#define SSLIQUIDS_RUN_TYPE_TEMPERATURE 7
|
||||
#define SSLIQUIDS_RUN_TYPE_CACHED_EDGES 8
|
||||
|
||||
@@ -285,3 +285,6 @@
|
||||
|
||||
///reduces the cooldown of all used /datum/action/cooldown by 25%
|
||||
#define TRAIT_FAST_COOLDOWNS "short_spell_cooldowns"
|
||||
|
||||
/// One can breath under water, you get me?
|
||||
#define TRAIT_WATER_BREATHING "water_breathing"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#define CHANGETURF_DEFER_CHANGE (1<<0)
|
||||
#define CHANGETURF_IGNORE_AIR (1<<1) // This flag prevents changeturf from gathering air from nearby turfs to fill the new turf with an approximation of local air
|
||||
#define CHANGETURF_FORCEOP (1<<2)
|
||||
#define CHANGETURF_SKIP (1<<3) // A flag for PlaceOnTop to just instance the new turf instead of calling ChangeTurf. Used for uninitialized turfs NOTHING ELSE
|
||||
#define CHANGETURF_SKIP (1<<3) // A flag for place_on_top to just instance the new turf instead of calling ChangeTurf. Used for uninitialized turfs NOTHING ELSE
|
||||
#define CHANGETURF_INHERIT_AIR (1<<4) // Inherit air from previous turf. Implies CHANGETURF_IGNORE_AIR
|
||||
#define CHANGETURF_RECALC_ADJACENT (1<<5) //Immediately recalc adjacent atmos turfs instead of queuing.
|
||||
#define CHANGETURF_TRAPDOOR_INDUCED (1<<6) // Caused by a trapdoor, for trapdoor to know that this changeturf was caused by itself
|
||||
|
||||
86
code/__DEFINES/{yogs_defines}/liquids.dm
Normal file
@@ -0,0 +1,86 @@
|
||||
#define WATER_HEIGH_DIFFERENCE_SOUND_CHANCE 50
|
||||
#define WATER_HEIGH_DIFFERENCE_DELTA_SPLASH 7 //Delta needed for the splash effect to be made in 1 go
|
||||
|
||||
#define REQUIRED_MEMBER_PROCESSES 10
|
||||
|
||||
#define REQUIRED_EVAPORATION_PROCESSES 20
|
||||
#define EVAPORATION_CHANCE 50
|
||||
|
||||
#define REQUIRED_FIRE_PROCESSES 10
|
||||
#define REQUIRED_FIRE_POWER_PER_UNIT 5
|
||||
#define FIRE_BURN_PERCENT 10
|
||||
|
||||
#define REQUIRED_OCEAN_PROCESSES 5
|
||||
|
||||
#define PARTIAL_TRANSFER_AMOUNT 0.3
|
||||
|
||||
#define LIQUID_MUTUAL_SHARE 1
|
||||
#define LIQUID_NOT_MUTUAL_SHARE 2
|
||||
|
||||
#define LIQUID_GIVER 1
|
||||
#define LIQUID_TAKER 2
|
||||
|
||||
//Required amount of a reagent to be simulated on turf exposures from liquids (to prevent gaming the system with cheap dillutions)
|
||||
#define LIQUID_REAGENT_THRESHOLD_TURF_EXPOSURE 5
|
||||
|
||||
//Threshold at which the difference of height makes us need to climb/blocks movement/allows to fall down
|
||||
#define TURF_HEIGHT_BLOCK_THRESHOLD 20
|
||||
|
||||
#define LIQUID_HEIGHT_DIVISOR 10
|
||||
|
||||
#define ONE_LIQUIDS_HEIGHT LIQUID_HEIGHT_DIVISOR
|
||||
|
||||
#define LIQUID_ATTRITION_TO_STOP_ACTIVITY 2
|
||||
|
||||
//Percieved heat capacity for calculations with atmos sharing
|
||||
#define REAGENT_HEAT_CAPACITY 5
|
||||
|
||||
#define LIQUID_STATE_PUDDLE 1
|
||||
#define LIQUID_STATE_ANKLES 2
|
||||
#define LIQUID_STATE_WAIST 3
|
||||
#define LIQUID_STATE_SHOULDERS 4
|
||||
#define LIQUID_STATE_FULLTILE 5
|
||||
#define TOTAL_LIQUID_STATES 5
|
||||
#define LYING_DOWN_SUBMERGEMENT_STATE_BONUS 2
|
||||
|
||||
#define LIQUID_STATE_FOR_HEAT_EXCHANGERS LIQUID_STATE_WAIST
|
||||
|
||||
#define LIQUID_ANKLES_LEVEL_HEIGHT 8
|
||||
#define LIQUID_WAIST_LEVEL_HEIGHT 19
|
||||
#define LIQUID_SHOULDERS_LEVEL_HEIGHT 29
|
||||
#define LIQUID_FULLTILE_LEVEL_HEIGHT 39
|
||||
|
||||
#define LIQUID_FIRE_STATE_NONE 0
|
||||
#define LIQUID_FIRE_STATE_SMALL 1
|
||||
#define LIQUID_FIRE_STATE_MILD 2
|
||||
#define LIQUID_FIRE_STATE_MEDIUM 3
|
||||
#define LIQUID_FIRE_STATE_HUGE 4
|
||||
#define LIQUID_FIRE_STATE_INFERNO 5
|
||||
|
||||
//Threshold at which we "choke" on the water, instead of holding our breath
|
||||
#define OXYGEN_DAMAGE_CHOKING_THRESHOLD 15
|
||||
|
||||
#define IMMUTABLE_LIQUID_SHARE 1
|
||||
|
||||
#define LIQUID_RECURSIVE_LOOP_SAFETY 255
|
||||
|
||||
//Height at which we consider the tile "full" and dont drop liquids on it from the upper Z level
|
||||
#define LIQUID_HEIGHT_CONSIDER_FULL_TILE 50
|
||||
|
||||
#define LIQUID_GROUP_DECAY_TIME 3
|
||||
|
||||
//Scaled with how much a person is submerged
|
||||
#define SUBMERGEMENT_REAGENTS_TOUCH_AMOUNT 60
|
||||
|
||||
#define CHOKE_REAGENTS_INGEST_ON_FALL_AMOUNT 4
|
||||
|
||||
#define CHOKE_REAGENTS_INGEST_ON_BREATH_AMOUNT 2
|
||||
|
||||
#define SUBMERGEMENT_PERCENT(carbon, liquids) min(1,(!MOBILITY_STAND ? liquids.liquid_group.group_overlay_state+LYING_DOWN_SUBMERGEMENT_STATE_BONUS : liquids.liquid_group.group_overlay_state)/TOTAL_LIQUID_STATES)
|
||||
|
||||
#define LIQUID_PROTECTION "liquid_protection"
|
||||
|
||||
GLOBAL_LIST_INIT(liquid_blacklist, list(
|
||||
/datum/reagent/sorium,
|
||||
/datum/reagent/liquid_dark_matter
|
||||
))
|
||||
@@ -878,7 +878,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
CRASH("Bad op: area/drop_location() called")
|
||||
|
||||
/// A hook so areas can modify the incoming args (of what??)
|
||||
/area/proc/PlaceOnTopReact(list/new_baseturfs, turf/fake_turf_type, flags)
|
||||
/area/proc/place_on_topReact(list/new_baseturfs, turf/fake_turf_type, flags)
|
||||
return flags
|
||||
|
||||
/// Called when a living mob that spawned here, joining the round, receives the player client.
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
///list of miners & their mining points from gems to be given once all exports are processed, used by supply shuttles
|
||||
var/list/gem_payout = list()
|
||||
|
||||
/area/shuttle/PlaceOnTopReact(list/new_baseturfs, turf/fake_turf_type, flags)
|
||||
/area/shuttle/place_on_topReact(list/new_baseturfs, turf/fake_turf_type, flags)
|
||||
. = ..()
|
||||
if(length(new_baseturfs) > 1 || fake_turf_type)
|
||||
return // More complicated larger changes indicate this isn't a player
|
||||
|
||||
@@ -1341,6 +1341,7 @@
|
||||
locked = !locked
|
||||
if(welded)
|
||||
welded = !welded
|
||||
SEND_SIGNAL(src, COMSIG_AIRLOCK_OPEN, forced)
|
||||
operating = TRUE
|
||||
update_icon(state = AIRLOCK_OPENING, override = TRUE)
|
||||
sleep(0.1 SECONDS)
|
||||
@@ -1357,6 +1358,7 @@
|
||||
if(delayed_close_requested)
|
||||
delayed_close_requested = FALSE
|
||||
addtimer(CALLBACK(src, PROC_REF(close)), 1)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_DOOR_OPEN) /// this is different because we need one that covers all doors
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -1386,6 +1388,20 @@
|
||||
if(killthis)
|
||||
SSexplosions.med_mov_atom += killthis
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_AIRLOCK_CLOSE, forced)
|
||||
|
||||
var/turf/open/open_turf = get_turf(src)
|
||||
if(open_turf.liquids)
|
||||
var/datum/liquid_group/turfs_group = open_turf.liquids.liquid_group
|
||||
turfs_group.remove_from_group(open_turf)
|
||||
qdel(open_turf.liquids)
|
||||
turfs_group.try_split(open_turf)
|
||||
for(var/dir in GLOB.cardinals)
|
||||
var/turf/open/direction_turf = get_step(open_turf, dir)
|
||||
if(!isopenturf(direction_turf) || !direction_turf.liquids)
|
||||
continue
|
||||
turfs_group.check_edges(direction_turf)
|
||||
|
||||
operating = TRUE
|
||||
update_icon(state = AIRLOCK_CLOSING, override = TRUE)
|
||||
layer = CLOSED_DOOR_LAYER
|
||||
|
||||
@@ -379,6 +379,7 @@
|
||||
operating = FALSE
|
||||
air_update_turf()
|
||||
update_freelook_sight()
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_DOOR_OPEN)
|
||||
if(autoclose)
|
||||
spawn(autoclose)
|
||||
close()
|
||||
@@ -399,6 +400,19 @@
|
||||
operating = TRUE
|
||||
|
||||
do_animate("closing")
|
||||
|
||||
var/turf/open/open_turf = get_turf(src)
|
||||
if(open_turf.liquids)
|
||||
var/datum/liquid_group/turfs_group = open_turf.liquids.liquid_group
|
||||
turfs_group.remove_from_group(open_turf)
|
||||
qdel(open_turf.liquids)
|
||||
turfs_group.try_split(open_turf)
|
||||
for(var/dir in GLOB.cardinals)
|
||||
var/turf/open/direction_turf = get_step(open_turf, dir)
|
||||
if(!isopenturf(direction_turf) || !direction_turf.liquids)
|
||||
continue
|
||||
turfs_group.check_edges(direction_turf)
|
||||
|
||||
layer = closingLayer
|
||||
if(air_tight)
|
||||
density = TRUE
|
||||
|
||||
@@ -163,3 +163,14 @@
|
||||
user.gib()
|
||||
playsound(src, 'sound/items/eatfood.ogg', 50, 1, -1)
|
||||
return MANUAL_SUICIDE
|
||||
|
||||
/obj/item/choice_beacon/liquids
|
||||
name = "Free Liquid Pump Kit"
|
||||
desc = "Kit containing a free liquid pump from SPAAAACE."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "gangtool-blue"
|
||||
item_state = "radio"
|
||||
|
||||
// LIQUIDS TM REMOVE THIS
|
||||
/obj/item/choice_beacon/liquids/generate_display_names()
|
||||
return list("Liquid Pump" = /obj/structure/liquid_pump)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
resistance_flags = FLAMMABLE
|
||||
var/mopping = 0
|
||||
var/mopcount = 0
|
||||
var/mopcap = 15
|
||||
var/mopcap = 45
|
||||
var/mopspeed = 15
|
||||
force_string = "robust... against germs"
|
||||
var/insertable = TRUE
|
||||
@@ -22,6 +22,7 @@
|
||||
/obj/item/mop/Initialize(mapload)
|
||||
. = ..()
|
||||
create_reagents(mopcap, REFILLABLE)
|
||||
AddComponent(/datum/component/liquids_interaction, TYPE_PROC_REF(/obj/item/mop, attack_on_liquids_turf))
|
||||
|
||||
|
||||
/obj/item/mop/proc/clean(turf/A)
|
||||
@@ -46,6 +47,11 @@
|
||||
return
|
||||
|
||||
if(T)
|
||||
// Disable normal cleaning if there are liquids.
|
||||
if(T.liquids)
|
||||
to_chat(user, span_warning("It would be quite difficult to clean this with a pool of liquids on top!"))
|
||||
return
|
||||
|
||||
user.visible_message("[user] begins to clean \the [T] with [src].", span_notice("You begin to clean \the [T] with [src]..."))
|
||||
|
||||
var/realspeed = mopspeed
|
||||
@@ -73,6 +79,33 @@
|
||||
to_chat(user, span_warning("You are unable to fit your [name] into the [J.name]."))
|
||||
return
|
||||
|
||||
/obj/item/mop/proc/attack_on_liquids_turf(obj/item/mop/the_mop, turf/target, mob/user, obj/effect/abstract/liquid_turf/liquids)
|
||||
if(!user.Adjacent(target))
|
||||
return FALSE
|
||||
var/free_space = mopcap - reagents.total_volume
|
||||
var/speed_mult = 1
|
||||
var/datum/liquid_group/targeted_group = target?.liquids?.liquid_group
|
||||
while(!QDELETED(targeted_group))
|
||||
if(speed_mult >= 0.2)
|
||||
speed_mult -= 0.05
|
||||
if(free_space <= 0)
|
||||
to_chat(user, span_warning("You cant absorb any more liquid with \the [src]!"))
|
||||
return TRUE
|
||||
if(!do_after(user, src.mopspeed * speed_mult, target = target))
|
||||
break
|
||||
if(the_mop.reagents.total_volume == the_mop.mopcap)
|
||||
to_chat(user, span_warning("You cant absorb any more liquid with \the [src]!"))
|
||||
break
|
||||
if(targeted_group?.reagents_per_turf)
|
||||
targeted_group?.trans_to_seperate_group(the_mop.reagents, min(targeted_group?.reagents_per_turf, 5))
|
||||
to_chat(user, span_notice("You soak up some liquids with \the [src]."))
|
||||
else if(!QDELETED(target?.liquids?.liquid_group))
|
||||
targeted_group = target.liquids.liquid_group
|
||||
else
|
||||
break
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
return TRUE
|
||||
|
||||
/obj/item/mop/cyborg
|
||||
insertable = FALSE
|
||||
|
||||
|
||||
@@ -39,6 +39,30 @@
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/structure/mop_bucket/attackby_secondary(obj/item/weapon, mob/user, params)
|
||||
if(istype(weapon, /obj/item/mop))
|
||||
if(!weapon.reagents.total_volume)
|
||||
if(weapon.reagents.total_volume >= weapon.reagents.maximum_volume)
|
||||
balloon_alert(user, "mop is already soaked!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
if(!reagents.total_volume < 1)
|
||||
balloon_alert(user, "mop bucket is empty!")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
reagents.trans_to(weapon, weapon.reagents.maximum_volume, transfered_by = user)
|
||||
balloon_alert(user, "wet mop")
|
||||
playsound(src, 'sound/effects/slosh.ogg', 25, vary = TRUE)
|
||||
else
|
||||
var/obj/item/mop/attacked_mop = weapon
|
||||
to_chat(user, "You completly wring out the [attacked_mop.name] into the waste bucket of the cart.")
|
||||
attacked_mop.reagents.remove_all(attacked_mop.mopcap)
|
||||
|
||||
if(istype(weapon, /obj/item/reagent_containers) || istype(weapon, /obj/item/mop))
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN // skip attack animations when refilling cart
|
||||
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
|
||||
|
||||
/obj/structure/mopbucket/update_overlays()
|
||||
. = ..()
|
||||
if(reagents.total_volume > 0)
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
/// Places a turf on top - for map loading
|
||||
/turf/proc/load_on_top(turf/added_layer, flags)
|
||||
var/area/our_area = get_area(src)
|
||||
flags = our_area.PlaceOnTopReact(list(baseturfs), added_layer, flags)
|
||||
flags = our_area.place_on_topReact(list(baseturfs), added_layer, flags)
|
||||
|
||||
if(flags & CHANGETURF_SKIP) // We haven't been initialized
|
||||
if(flags_1 & INITIALIZED_1)
|
||||
stack_trace("CHANGETURF_SKIP was used in a PlaceOnTop call for a turf that's initialized. This is a mistake. [src]([type])")
|
||||
stack_trace("CHANGETURF_SKIP was used in a place_on_top call for a turf that's initialized. This is a mistake. [src]([type])")
|
||||
assemble_baseturfs()
|
||||
|
||||
var/turf/new_turf
|
||||
|
||||
@@ -82,6 +82,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
|
||||
var/old_lighting_corner_NW = lighting_corner_NW
|
||||
var/old_directional_opacity = directional_opacity
|
||||
var/old_dynamic_lumcount = dynamic_lumcount
|
||||
|
||||
var/old_rcd_memory = rcd_memory
|
||||
var/old_explosion_throw_details = explosion_throw_details
|
||||
var/old_opacity = opacity
|
||||
@@ -206,6 +207,14 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
|
||||
//don't
|
||||
if(!SSair.initialized)
|
||||
return ..()
|
||||
var/obj/effect/abstract/liquid_turf/old_liquids = liquids
|
||||
var/datum/liquid_group/old_group = liquids?.liquid_group
|
||||
var/evaporating = FALSE
|
||||
if(old_group)
|
||||
old_group.remove_from_group(liquids.my_turf)
|
||||
if(SSliquids.evaporation_queue[src])
|
||||
evaporating = TRUE
|
||||
SSliquids.evaporation_queue -= src
|
||||
if ((flags & CHANGETURF_INHERIT_AIR) && ispath(path, /turf/open))
|
||||
var/datum/gas_mixture/stashed_air = new()
|
||||
stashed_air.copy_from(air)
|
||||
@@ -223,9 +232,17 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
|
||||
QDEL_NULL(newTurf.air)
|
||||
newTurf.air = stashed_air
|
||||
update_air_ref(planetary_atmos ? 1 : 2)
|
||||
if(old_liquids)
|
||||
old_liquids.my_turf = newTurf
|
||||
newTurf.liquids = old_liquids
|
||||
old_group.add_to_group(newTurf)
|
||||
if(evaporating)
|
||||
SSliquids.evaporation_queue[newTurf] = TRUE
|
||||
else
|
||||
if(turf_fire)
|
||||
qdel(turf_fire)
|
||||
if(old_liquids)
|
||||
qdel(old_liquids)
|
||||
if(ispath(path, /turf/closed) || ispath(path, /turf/cordon))
|
||||
flags |= CHANGETURF_RECALC_ADJACENT
|
||||
update_air_ref(-1)
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
* This replaces the current turf if it is plating and is passed plating, is tile and is passed tile.
|
||||
* It places the new turf on top of itself if it is plating and is passed a tile.
|
||||
* It also replaces the turf if it is tile and is passed plating, essentially destroying the over turf.
|
||||
* Flags argument is passed directly to ChangeTurf or PlaceOnTop
|
||||
* Flags argument is passed directly to ChangeTurf or place_on_top
|
||||
*/
|
||||
/turf/open/proc/replace_floor(turf/open/new_floor_path, flags)
|
||||
if (!overfloor_placed && initial(new_floor_path.overfloor_placed))
|
||||
|
||||
@@ -215,6 +215,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
|
||||
|
||||
if(length(vis_contents))
|
||||
vis_contents.Cut()
|
||||
SEND_SIGNAL(src, COMSIG_TURF_DESTROY)
|
||||
|
||||
/// WARNING WARNING
|
||||
/// Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS
|
||||
|
||||
@@ -132,7 +132,9 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
|
||||
/client/proc/admin_away,
|
||||
/client/proc/centcom_podlauncher,/*Open a window to launch a Supplypod and configure it or it's contents*/
|
||||
/client/proc/load_json_admin_event,
|
||||
/client/proc/event_role_manager
|
||||
/client/proc/event_role_manager,
|
||||
/client/proc/spawn_liquid,
|
||||
/client/proc/remove_liquid
|
||||
))
|
||||
GLOBAL_PROTECT(admin_verbs_fun)
|
||||
GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/podspawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character, /datum/admins/proc/beaker_panel))
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
if(!air)
|
||||
return
|
||||
|
||||
if(liquids && liquids.liquid_group && !liquids.fire_state)
|
||||
liquids.liquid_group.ignite_turf(src)
|
||||
|
||||
if (air.get_moles(GAS_O2) < 0.5 || air.get_moles(GAS_HYPERNOB) > REACTION_OPPRESSION_THRESHOLD)
|
||||
return
|
||||
|
||||
|
||||
@@ -3292,3 +3292,11 @@
|
||||
small_item = TRUE
|
||||
contains = list(/obj/item/wallframe/telescreen/preset)
|
||||
crate_name = "telescreen crate"
|
||||
|
||||
// LIQUIDS TM REMOVE THIS
|
||||
/datum/supply_pack/service/janitor/pump
|
||||
name = "Liquids Pump Crate"
|
||||
desc = "A crate containing a portable liquid pump, for stations that lack proper liquid infrastructure."
|
||||
cost = 2000
|
||||
crate_name = "liquid pump crate"
|
||||
contains = list(/obj/structure/liquid_pump)
|
||||
|
||||
@@ -48,3 +48,5 @@
|
||||
ears = /obj/item/radio/headset/headset_srv
|
||||
uniform = /obj/item/clothing/under/rank/civilian/janitor
|
||||
uniform_skirt = /obj/item/clothing/under/rank/civilian/janitor/skirt
|
||||
// LIQUIDS TM REMOVE THIS
|
||||
backpack_contents = list(/obj/item/choice_beacon/liquids)
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
* - y_upper: The maximum y coordinate to load
|
||||
* - z_lower: The minimum z coordinate to load
|
||||
* - z_upper: The maximum z coordinate to load
|
||||
* - place_on_top: Whether to use /turf/proc/PlaceOnTop rather than /turf/proc/ChangeTurf
|
||||
* - place_on_top: Whether to use /turf/proc/place_on_top rather than /turf/proc/ChangeTurf
|
||||
* - new_z: If true, a new z level will be created for the map
|
||||
*/
|
||||
/proc/load_map(
|
||||
|
||||
@@ -345,6 +345,10 @@
|
||||
T = get_turf(src)
|
||||
var/list/temp_blood_DNA
|
||||
if(small_drip)
|
||||
if(!QDELETED(T.liquids)) //just add it to our liquids
|
||||
var/list/blood_drop = list(get_blood_id() = 0.1)
|
||||
T.add_liquid_list(blood_drop, FALSE, 300)
|
||||
return
|
||||
// Only a certain number of drips (or one large splatter) can be on a given turf.
|
||||
var/obj/effect/decal/cleanable/blood/drip/drop = locate() in T
|
||||
if(drop)
|
||||
|
||||
@@ -113,6 +113,21 @@
|
||||
breath = loc_as_obj.handle_internal_lifeform(src, BREATH_VOLUME)
|
||||
|
||||
else if(isturf(loc)) //Breathe from loc as turf
|
||||
var/turf/our_turf = loc
|
||||
if(our_turf.liquids && !HAS_TRAIT(src, TRAIT_NOBREATH) && ((body_position == LYING_DOWN && our_turf.liquids.liquid_state >= LIQUID_STATE_WAIST) || (body_position == STANDING_UP && our_turf.liquids.liquid_state >= LIQUID_STATE_FULLTILE)))
|
||||
//Officially trying to breathe underwater
|
||||
if(HAS_TRAIT(src, TRAIT_WATER_BREATHING))
|
||||
failed_last_breath = FALSE
|
||||
clear_alert("not_enough_oxy")
|
||||
return FALSE
|
||||
adjustOxyLoss(3)
|
||||
failed_last_breath = TRUE
|
||||
if(oxyloss <= OXYGEN_DAMAGE_CHOKING_THRESHOLD && stat == CONSCIOUS)
|
||||
to_chat(src, span_userdanger("You hold in your breath!"))
|
||||
else
|
||||
//Try and drink water
|
||||
our_turf.liquids.liquid_group.transfer_to_atom(src, CHOKE_REAGENTS_INGEST_ON_BREATH_AMOUNT)
|
||||
visible_message(span_warning("[src] chokes on water!"), span_userdanger("You're choking on water!"))
|
||||
var/breath_ratio = 0
|
||||
if(environment)
|
||||
breath_ratio = BREATH_VOLUME/environment.return_volume()
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/proc/ZImpactDamage(turf/T, levels)
|
||||
SEND_SIGNAL(T, COMSIG_TURF_MOB_FALL, src)
|
||||
visible_message(span_danger("[src] crashes into [T] with a sickening noise!"))
|
||||
adjustBruteLoss((levels * 5) ** 1.5)
|
||||
Knockdown(levels * 50)
|
||||
@@ -633,6 +634,21 @@
|
||||
cure_fakedeath()
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_POST_FULLY_HEAL)
|
||||
|
||||
/mob/living/proc/do_strange_reagent_revival()
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C = src
|
||||
for(var/organ in C.internal_organs)
|
||||
var/obj/item/organ/O = organ
|
||||
O.setOrganDamage(0)
|
||||
adjustBruteLoss(-100)
|
||||
adjustFireLoss(-100)
|
||||
adjustOxyLoss(-200, 0)
|
||||
adjustToxLoss(-200, 0, TRUE)
|
||||
updatehealth()
|
||||
if(revive())
|
||||
emote("gasp")
|
||||
log_combat(src, src, "revived", src)
|
||||
|
||||
//proc called by revive(), to check if we can actually ressuscitate the mob (we don't want to revive him and have him instantly die again)
|
||||
/mob/living/proc/can_be_revived()
|
||||
. = 1
|
||||
|
||||
@@ -742,10 +742,10 @@
|
||||
return TRUE
|
||||
|
||||
/// Like add_reagent but you can enter a list. Format it like this: list(/datum/reagent/toxin = 10, "beer" = 15)
|
||||
/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null)
|
||||
/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null, _no_react = FALSE)
|
||||
for(var/r_id in list_reagents)
|
||||
var/amt = list_reagents[r_id]
|
||||
add_reagent(r_id, amt, data)
|
||||
add_reagent(r_id, amt, data, no_react = _no_react)
|
||||
|
||||
/// Remove a specific reagent
|
||||
/datum/reagents/proc/remove_reagent(reagent, amount, safety)//Added a safety check for the trans_id_to
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#define REM REAGENTS_EFFECT_MULTIPLIER
|
||||
|
||||
GLOBAL_VAR_INIT(global_evaporation_rate, 1)
|
||||
|
||||
GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
|
||||
|
||||
/proc/build_name2reagent()
|
||||
@@ -62,8 +64,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
|
||||
var/addiction_name = null
|
||||
/// What biotypes can process this? We'll assume by default that it affects organics (and undead, for plasmemes)
|
||||
var/compatible_biotypes = ALL_NON_ROBOTIC
|
||||
/// How flammable is this material?
|
||||
var/accelerant_quality = 0
|
||||
|
||||
/// You fucked up and this is now triggering its overdose effects, purge that shit quick.
|
||||
var/overdosed = 0
|
||||
///if false stops metab in liverless mobs
|
||||
@@ -76,8 +77,23 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
|
||||
var/harmful = FALSE
|
||||
/// The default reagent container for the reagent. Currently only used for crafting icon/displays.
|
||||
var/obj/item/reagent_containers/default_container = /obj/item/reagent_containers/glass/bottle
|
||||
|
||||
/// Are we from a material? We might wanna know that for special stuff. Like metalgen. Is replaced with a ref of the material on New()
|
||||
|
||||
///Whether it will evaporate if left untouched on a liquids simulated puddle
|
||||
var/evaporates = TRUE
|
||||
/// How flammable is this material? For liquid spills and molotov cocktails
|
||||
var/accelerant_quality = 0
|
||||
///Whether a fire from this requires oxygen in the atmosphere
|
||||
var/fire_needs_oxygen = TRUE
|
||||
///The opacity of the chems used to determine the alpha of liquid turfs
|
||||
var/opacity = 175
|
||||
///The rate of evaporation in units per call
|
||||
var/evaporation_rate = 1
|
||||
///The rate of evaporation for the entire GROUP per call, for special things like drying agent
|
||||
var/group_evaporation_rate = 0
|
||||
/// do we have a turf exposure (used to prevent liquids doing un-needed processes)
|
||||
var/turf_exposure = FALSE
|
||||
/// are we slippery?
|
||||
var/slippery = TRUE
|
||||
|
||||
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
|
||||
. = ..()
|
||||
@@ -149,6 +165,9 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
|
||||
/datum/reagent/proc/on_ex_act(severity)
|
||||
return
|
||||
|
||||
/datum/reagent/proc/evaporate(turf/exposed_turf, reac_volume)
|
||||
return
|
||||
|
||||
/// Called if the reagent has passed the overdose threshold and is set to be triggering overdose effects
|
||||
/datum/reagent/proc/overdose_process(mob/living/M)
|
||||
return
|
||||
|
||||
@@ -935,20 +935,7 @@
|
||||
M.do_jitter_animation(10)
|
||||
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob/living/carbon, do_jitter_animation), 10), 40) //jitter immediately, then again after 4 and 8 seconds
|
||||
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob/living/carbon, do_jitter_animation), 10), 80)
|
||||
sleep(10 SECONDS) //so the ghost has time to re-enter
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/C = M
|
||||
for(var/organ in C.internal_organs)
|
||||
var/obj/item/organ/O = organ
|
||||
O.setOrganDamage(0)
|
||||
M.adjustBruteLoss(-100)
|
||||
M.adjustFireLoss(-100)
|
||||
M.adjustOxyLoss(-200, 0)
|
||||
M.adjustToxLoss(-200, 0, TRUE)
|
||||
M.updatehealth()
|
||||
if(M.revive())
|
||||
M.emote("gasp")
|
||||
log_combat(M, M, "revived", src)
|
||||
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob/living, do_strange_reagent_revival)), 10 SECONDS)
|
||||
..()
|
||||
|
||||
/datum/reagent/medicine/strange_reagent/on_mob_life(mob/living/carbon/M)
|
||||
|
||||
@@ -141,8 +141,9 @@
|
||||
/datum/reagent/water
|
||||
name = "Water"
|
||||
description = "An ubiquitous chemical substance that is composed of hydrogen and oxygen."
|
||||
color = "#609bdf77" // rgb: 96, 155, 223, 77 (alpha)
|
||||
color = "#00B8FF" // rgb: 170, 170, 170, 77 (alpha)
|
||||
taste_description = "water"
|
||||
evaporation_rate = 4 // water goes fast
|
||||
glass_icon_state = "glass_clear"
|
||||
glass_name = "glass of water"
|
||||
glass_desc = "The father of all refreshments."
|
||||
@@ -1126,7 +1127,7 @@
|
||||
glass_icon_state = "dr_gibb_glass"
|
||||
glass_name = "glass of Dr. Gibb"
|
||||
glass_desc = "Dr. Gibb. Not as dangerous as the glass_name might imply."
|
||||
accelerant_quality = 10
|
||||
accelerant_quality = 15
|
||||
compatible_biotypes = ALL_BIOTYPES
|
||||
|
||||
/datum/reagent/fuel/reaction_mob(mob/living/M, methods=TOUCH, reac_volume, show_message = TRUE, permeability = 1)//Splashing people with welding fuel to make them easy to ignite!
|
||||
@@ -1447,6 +1448,7 @@
|
||||
color = "#C8A5DC"
|
||||
taste_description = "oil"
|
||||
compatible_biotypes = ALL_BIOTYPES
|
||||
accelerant_quality = 8
|
||||
|
||||
/datum/reagent/oil/on_mob_life(mob/living/carbon/M)
|
||||
M.adjustFireLoss(-2*REM, FALSE, FALSE, BODYPART_ROBOTIC)
|
||||
@@ -1628,6 +1630,8 @@
|
||||
reagent_state = LIQUID
|
||||
color = "#A70FFF"
|
||||
taste_description = "dryness"
|
||||
group_evaporation_rate = 16
|
||||
evaporation_rate = 0 //will never evaporate on it's own
|
||||
|
||||
/datum/reagent/drying_agent/reaction_turf(turf/open/T, reac_volume)
|
||||
if(istype(T))
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
taste_description = "burning"
|
||||
accelerant_quality = 20
|
||||
compatible_biotypes = ALL_BIOTYPES
|
||||
evaporation_rate = 100
|
||||
|
||||
/datum/reagent/clf3/on_mob_life(mob/living/carbon/M)
|
||||
M.adjust_fire_stacks(2)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
color = "#CF3600" // rgb: 207, 54, 0
|
||||
taste_description = "bitterness"
|
||||
taste_mult = 1.2
|
||||
evaporation_rate = 3 //6x faster than normal chems
|
||||
var/toxpwr = 1.5
|
||||
var/silent_toxin = FALSE //won't produce a pain message when processed by liver/Life(seconds_per_tick = SSMOBS_DT, times_fired) if there isn't another non-silent toxin present.
|
||||
|
||||
@@ -59,7 +60,7 @@
|
||||
taste_mult = 1.5
|
||||
color = "#8228A0"
|
||||
toxpwr = 3
|
||||
accelerant_quality = 10
|
||||
accelerant_quality = 50 //OWWW
|
||||
compatible_biotypes = ALL_BIOTYPES
|
||||
|
||||
/datum/reagent/toxin/plasma/on_mob_life(mob/living/carbon/C)
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
var/list/list_reagents = null
|
||||
var/spawned_disease = null
|
||||
var/disease_amount = 20
|
||||
var/spillable = FALSE
|
||||
|
||||
/obj/item/reagent_containers/Initialize(mapload, vol)
|
||||
. = ..()
|
||||
@@ -25,6 +24,37 @@
|
||||
|
||||
add_initial_reagents()
|
||||
|
||||
AddComponent(/datum/component/liquids_interaction, TYPE_PROC_REF(/obj/item/reagent_containers, attack_on_liquids_turf))
|
||||
|
||||
/obj/item/reagent_containers/proc/attack_on_liquids_turf(obj/item/reagent_containers/my_beaker, turf/T, mob/living/user, obj/effect/abstract/liquid_turf/liquids)
|
||||
if(!user.Adjacent(T))
|
||||
return FALSE
|
||||
if(!my_beaker.is_open_container())
|
||||
return FALSE
|
||||
if(!user.Adjacent(T))
|
||||
return FALSE
|
||||
if(user.combat_mode)
|
||||
return FALSE
|
||||
if(liquids.fire_state) //Use an extinguisher first
|
||||
to_chat(user, "<span class='warning'>You can't scoop up anything while it's on fire!</span>")
|
||||
return TRUE
|
||||
if(liquids.liquid_group.expected_turf_height == 1)
|
||||
to_chat(user, "<span class='warning'>The puddle is too shallow to scoop anything up!</span>")
|
||||
return TRUE
|
||||
var/free_space = my_beaker.reagents.maximum_volume - my_beaker.reagents.total_volume
|
||||
if(free_space <= 0)
|
||||
to_chat(user, "<span class='warning'>You can't fit any more liquids inside [my_beaker]!</span>")
|
||||
return TRUE
|
||||
var/desired_transfer = my_beaker.amount_per_transfer_from_this
|
||||
if(desired_transfer > free_space)
|
||||
desired_transfer = free_space
|
||||
if(desired_transfer > liquids.liquid_group.reagents_per_turf)
|
||||
desired_transfer = liquids.liquid_group.reagents_per_turf
|
||||
liquids.liquid_group.trans_to_seperate_group(my_beaker.reagents, desired_transfer, liquids)
|
||||
to_chat(user, "<span class='notice'>You scoop up around [round(desired_transfer)] units of liquids with [my_beaker].</span>")
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
return TRUE
|
||||
|
||||
/obj/item/reagent_containers/proc/add_initial_reagents()
|
||||
if(list_reagents)
|
||||
reagents.add_reagent_list(list_reagents)
|
||||
@@ -118,17 +148,34 @@
|
||||
return
|
||||
|
||||
else
|
||||
if(isturf(target) && reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]")
|
||||
log_game("[key_name(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [ADMIN_VERBOSEJMP(target)].")
|
||||
if(isturf(target))
|
||||
var/turf/T = target
|
||||
if(istype(T, /turf/open))
|
||||
T.add_liquid_from_reagents(reagents, FALSE, reagents.chem_temp)
|
||||
if(reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]")
|
||||
log_game("[key_name(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [ADMIN_VERBOSEJMP(target)].")
|
||||
else
|
||||
reagents.reaction(target, TOUCH)
|
||||
var/turf/targets_loc = target.loc
|
||||
if(istype(targets_loc, /turf/open) && !target.density)
|
||||
targets_loc.add_liquid_from_reagents(reagents)
|
||||
else
|
||||
targets_loc = get_step_towards(targets_loc, thrownby)
|
||||
targets_loc.add_liquid_from_reagents(reagents) //not perfect but i can't figure out how to move something to the nearest visible turf from throw_target
|
||||
visible_message(span_notice("[src] spills its contents all over [target]."))
|
||||
reagents.reaction(target, TOUCH)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
|
||||
if(!isturf(target)) // it all ends up on the floor because gravity exists
|
||||
reagents.reaction(get_turf(target), TOUCH)
|
||||
playsound(target, 'sound/effects/slosh.ogg', 25, TRUE)
|
||||
var/image/splash_animation = image('icons/effects/effects.dmi', target, "splash")
|
||||
if(isturf(target))
|
||||
splash_animation = image('icons/effects/effects.dmi', target, "splash_floor")
|
||||
splash_animation.color = mix_color_from_reagents(reagents.reagent_list)
|
||||
flick_overlay_global(splash_animation, GLOB.clients, 1.0 SECONDS)
|
||||
|
||||
reagents.clear_reagents()
|
||||
|
||||
/obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M)
|
||||
|
||||
@@ -460,7 +460,7 @@
|
||||
base_icon_state = "coffee_cup"
|
||||
possible_transfer_amounts = list(10)
|
||||
volume = 30
|
||||
spillable = TRUE
|
||||
reagent_flags = OPENCONTAINER
|
||||
|
||||
/obj/item/reagent_containers/glass/coffee_cup/update_icon_state()
|
||||
icon_state = reagents.total_volume ? base_icon_state : "[base_icon_state]_e"
|
||||
@@ -715,7 +715,7 @@
|
||||
fill_icon_thresholds = list(0, 20, 40, 60, 80, 100)
|
||||
possible_transfer_amounts = list(5, 10)
|
||||
amount_per_transfer_from_this = 5
|
||||
spillable = FALSE
|
||||
reagent_flags = OPENCONTAINER_NOSPILL
|
||||
///variable to tell if the bottle can be refilled
|
||||
var/cap_on = TRUE
|
||||
obj_flags = UNIQUE_RENAME | UNIQUE_REDESC
|
||||
|
||||
@@ -278,6 +278,24 @@
|
||||
ITEM_SLOT_DEX_STORAGE
|
||||
)
|
||||
|
||||
/obj/item/reagent_containers/glass/bucket/attackby_secondary(obj/item/weapon, mob/user, params)
|
||||
. = ..()
|
||||
if(istype(weapon, /obj/item/mop))
|
||||
if(reagents.total_volume == volume)
|
||||
to_chat(user, "The [src.name] can't hold anymore liquids")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
|
||||
var/obj/item/mop/attacked_mop = weapon
|
||||
|
||||
if(attacked_mop.reagents.total_volume < 0.1)
|
||||
to_chat(user, span_warning("Your [attacked_mop.name] is already dry!"))
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
|
||||
to_chat(user, "You wring out the [attacked_mop.name] into the [src.name].")
|
||||
attacked_mop.reagents.trans_to(src, attacked_mop.mopcap * 0.25)
|
||||
attacked_mop.reagents.remove_all(attacked_mop.mopcap)
|
||||
return SECONDARY_ATTACK_CONTINUE_CHAIN
|
||||
|
||||
/obj/item/reagent_containers/glass/bucket/wooden
|
||||
name = "wooden bucket"
|
||||
icon_state = "woodbucket"
|
||||
|
||||
BIN
goon/icons/turfs/outdoors.dmi
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 928 KiB After Width: | Height: | Size: 843 KiB |
@@ -236,6 +236,7 @@
|
||||
#include "code\__DEFINES\{yogs_defines}\is_helpers.dm"
|
||||
#include "code\__DEFINES\{yogs_defines}\jungle.dm"
|
||||
#include "code\__DEFINES\{yogs_defines}\layers.dm"
|
||||
#include "code\__DEFINES\{yogs_defines}\liquids.dm"
|
||||
#include "code\__DEFINES\{yogs_defines}\logging.dm"
|
||||
#include "code\__DEFINES\{yogs_defines}\mapping.dm"
|
||||
#include "code\__DEFINES\{yogs_defines}\maps.dm"
|
||||
@@ -4429,6 +4430,19 @@
|
||||
#include "yogstation\code\modules\jungleland\kinetic_javelin.dm"
|
||||
#include "yogstation\code\modules\language\darkspeak.dm"
|
||||
#include "yogstation\code\modules\language\japanese.dm"
|
||||
#include "yogstation\code\modules\liquids\drains.dm"
|
||||
#include "yogstation\code\modules\liquids\height_floors.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_controller.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_effect.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_groups.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_height.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_interaction.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_ocean.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_plumbers.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_pump.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_status_effect.dm"
|
||||
#include "yogstation\code\modules\liquids\liquid_turf.dm"
|
||||
#include "yogstation\code\modules\liquids\tools.dm"
|
||||
#include "yogstation\code\modules\language\language_holder.dm"
|
||||
#include "yogstation\code\modules\language\voxpidgin.dm"
|
||||
#include "yogstation\code\modules\mentor\follow.dm"
|
||||
|
||||
80
yogstation/code/modules/liquids/drains.dm
Normal file
@@ -0,0 +1,80 @@
|
||||
//Structure as this doesn't need any power to work
|
||||
/obj/structure/drain
|
||||
name = "drain"
|
||||
icon = 'yogstation/icons/obj/structures/drains.dmi'
|
||||
icon_state = "drain"
|
||||
desc = "Drainage inlet embedded in the floor to prevent flooding."
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
density = FALSE
|
||||
plane = FLOOR_PLANE
|
||||
layer = GAS_SCRUBBER_LAYER
|
||||
anchored = TRUE
|
||||
var/processing = FALSE
|
||||
var/drain_flat = 5
|
||||
var/drain_percent = 0.1
|
||||
var/welded = FALSE
|
||||
var/turf/my_turf //need to keep track of it for the signal, if in any bizarre cases something would be moving the drain
|
||||
|
||||
/obj/structure/drain/update_icon()
|
||||
. = ..()
|
||||
if(welded)
|
||||
icon_state = "[initial(icon_state)]_welded"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]"
|
||||
|
||||
/obj/structure/drain/welder_act(mob/living/user, obj/item/I)
|
||||
..()
|
||||
if(!I.tool_start_check(user, amount=0))
|
||||
return TRUE
|
||||
|
||||
playsound(src, 'sound/items/welder2.ogg', 50, TRUE)
|
||||
to_chat(user, span_notice("You start [welded ? "unwelding" : "welding"] [src]..."))
|
||||
if(I.use_tool(src, user, 20))
|
||||
to_chat(user, span_notice("You [welded ? "unweld" : "weld"] [src]."))
|
||||
welded = !welded
|
||||
update_icon()
|
||||
if(welded)
|
||||
if(processing)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
processing = FALSE
|
||||
else if (my_turf.liquids)
|
||||
START_PROCESSING(SSobj, src)
|
||||
processing = TRUE
|
||||
return TRUE
|
||||
|
||||
/obj/structure/drain/process()
|
||||
if(!my_turf.liquids)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
processing = FALSE
|
||||
return
|
||||
my_turf.liquids.liquid_group.remove_any(my_turf.liquids, drain_flat + (drain_percent * my_turf.liquids.liquid_group.total_reagent_volume))
|
||||
|
||||
/obj/structure/drain/Initialize()
|
||||
. = ..()
|
||||
if(!isturf(loc))
|
||||
stack_trace("Drain structure initialized not on a turf")
|
||||
my_turf = loc
|
||||
RegisterSignal(my_turf, COMSIG_TURF_LIQUIDS_CREATION, PROC_REF(liquids_signal))
|
||||
if(my_turf.liquids)
|
||||
START_PROCESSING(SSobj, src)
|
||||
processing = TRUE
|
||||
|
||||
/obj/structure/drain/proc/liquids_signal()
|
||||
SIGNAL_HANDLER
|
||||
if(processing || welded)
|
||||
return
|
||||
START_PROCESSING(SSobj, src)
|
||||
processing = TRUE
|
||||
|
||||
/obj/structure/drain/Destroy()
|
||||
if(processing)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
UnregisterSignal(my_turf, COMSIG_TURF_LIQUIDS_CREATION)
|
||||
my_turf = null
|
||||
return ..()
|
||||
|
||||
/obj/structure/drain/big
|
||||
desc = "Drainage inlet embedded in the floor to prevent flooding. This one seems large."
|
||||
icon_state = "bigdrain"
|
||||
drain_percent = 0.3
|
||||
drain_flat = 15
|
||||
57
yogstation/code/modules/liquids/height_floors.dm
Normal file
@@ -0,0 +1,57 @@
|
||||
/obj/item/stack/tile/elevated
|
||||
name = "elevated floor tile"
|
||||
singular_name = "elevated floor tile"
|
||||
turf_type = /turf/open/floor/elevated
|
||||
merge_type = /obj/item/stack/tile/elevated
|
||||
icon = 'yogstation/icons/obj/items/tiles.dmi'
|
||||
icon_state = "elevated"
|
||||
|
||||
/obj/item/stack/tile/lowered
|
||||
name = "lowered floor tile"
|
||||
singular_name = "lowered floor tile"
|
||||
turf_type = /turf/open/floor/lowered
|
||||
merge_type = /obj/item/stack/tile/lowered
|
||||
icon = 'yogstation/icons/obj/items/tiles.dmi'
|
||||
icon_state = "lowered"
|
||||
|
||||
/obj/item/stack/tile/lowered/iron
|
||||
name = "lowered floor tile"
|
||||
singular_name = "lowered floor tile"
|
||||
turf_type = /turf/open/floor/lowered
|
||||
merge_type = /obj/item/stack/tile/lowered
|
||||
icon = 'yogstation/icons/obj/items/tiles.dmi'
|
||||
icon_state = "lowered"
|
||||
|
||||
/turf/open/floor/iron/pool/rust_heretic_act()
|
||||
return
|
||||
|
||||
/turf/open/floor/elevated
|
||||
name = "elevated floor"
|
||||
floor_tile = /obj/item/stack/tile/elevated
|
||||
icon = 'yogstation/icons/turf/floors/elevated_iron.dmi'
|
||||
icon_state = "elevated_plasteel-0"
|
||||
base_icon_state = "elevated_plasteel-0"
|
||||
smoothing_flags = SMOOTH_CORNERS
|
||||
smoothing_groups = SMOOTH_GROUP_ELEVATED_PLASTEEL
|
||||
canSmoothWith = SMOOTH_GROUP_WALLS + SMOOTH_GROUP_ELEVATED_PLASTEEL
|
||||
liquid_height = 30
|
||||
turf_height = 30
|
||||
|
||||
/turf/open/floor/elevated/rust_heretic_act()
|
||||
return
|
||||
|
||||
/turf/open/floor/lowered
|
||||
name = "lowered floor"
|
||||
floor_tile = /obj/item/stack/tile/lowered
|
||||
icon = 'yogstation/icons/turf/floors/lowered_iron.dmi'
|
||||
icon_state = "lowered_plasteel-0"
|
||||
base_icon_state = "lowered_plasteel-0"
|
||||
smoothing_flags = SMOOTH_CORNERS
|
||||
smoothing_groups = SMOOTH_GROUP_LOWERED_PLASTEEL
|
||||
canSmoothWith = SMOOTH_GROUP_WALLS + SMOOTH_GROUP_LOWERED_PLASTEEL
|
||||
liquid_height = -30
|
||||
turf_height = -30
|
||||
|
||||
|
||||
/turf/open/floor/lowered/rust_heretic_act()
|
||||
return
|
||||
233
yogstation/code/modules/liquids/liquid_controller.dm
Normal file
@@ -0,0 +1,233 @@
|
||||
SUBSYSTEM_DEF(liquids)
|
||||
name = "Liquid Turfs"
|
||||
wait = 0.5 SECONDS
|
||||
flags = SS_KEEP_TIMING | SS_NO_INIT
|
||||
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||
var/list/active_groups = list()
|
||||
|
||||
var/list/evaporation_queue = list()
|
||||
var/evaporation_counter = 0 //Only process evaporation on intervals
|
||||
|
||||
var/list/temperature_queue = list()
|
||||
|
||||
var/list/active_ocean_turfs = list()
|
||||
var/list/ocean_turfs = list()
|
||||
var/list/currentrun_active_ocean_turfs = list()
|
||||
var/list/unvalidated_oceans = list()
|
||||
var/ocean_counter = 0
|
||||
|
||||
var/run_type = SSLIQUIDS_RUN_TYPE_GROUPS
|
||||
|
||||
///debug variable to toggle evaporation from running
|
||||
var/debug_evaporation = FALSE
|
||||
|
||||
var/list/burning_turfs = list()
|
||||
var/fire_counter = 0
|
||||
|
||||
var/member_counter = 0
|
||||
|
||||
var/list/arrayed_groups = list()
|
||||
|
||||
///list of groups to work on for cached edges
|
||||
var/list/cached_edge_work_queue = list()
|
||||
///list of groups we are going to work on in group process
|
||||
var/list/group_process_work_queue = list()
|
||||
///list of all work queue for turf processing
|
||||
var/list/active_turf_group_queue = list()
|
||||
|
||||
|
||||
/datum/controller/subsystem/liquids/stat_entry(msg)
|
||||
msg += "AG:[length(active_groups)]|BT:[length(burning_turfs)]|EQ:[length(evaporation_queue)]|AO:[length(active_ocean_turfs)]|UO:[length(unvalidated_oceans)]"
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/liquids/fire(resumed)
|
||||
if(!length(active_groups) && !length(evaporation_queue) && !length(active_ocean_turfs) && !length(burning_turfs) && !length(unvalidated_oceans))
|
||||
return
|
||||
|
||||
listclearnulls(active_groups)
|
||||
|
||||
if(length(unvalidated_oceans))
|
||||
for(var/turf/open/floor/plating/ocean/unvalidated_turf in unvalidated_oceans)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
unvalidated_turf.assume_self()
|
||||
|
||||
if(length(arrayed_groups))
|
||||
listclearnulls(arrayed_groups)
|
||||
for(var/datum/liquid_group/liquid_group as anything in arrayed_groups)
|
||||
if(QDELETED(liquid_group))
|
||||
arrayed_groups -= liquid_group
|
||||
continue
|
||||
while(!MC_TICK_CHECK && length(liquid_group?.splitting_array)) // three at a time until we either finish or over-run, this should be done before anything else
|
||||
liquid_group.work_on_split_queue()
|
||||
liquid_group.cleanse_members()
|
||||
|
||||
if(!length(temperature_queue))
|
||||
for(var/datum/liquid_group/liquid_group as anything in active_groups)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(QDELETED(liquid_group))
|
||||
temperature_queue -= active_groups
|
||||
continue
|
||||
var/list/turfs = liquid_group.fetch_temperature_queue()
|
||||
temperature_queue += turfs
|
||||
|
||||
if(run_type == SSLIQUIDS_RUN_TYPE_GROUPS)
|
||||
if(!length(group_process_work_queue))
|
||||
group_process_work_queue |= active_groups
|
||||
listclearnulls(group_process_work_queue)
|
||||
if(length(group_process_work_queue))
|
||||
var/populate_evaporation = FALSE
|
||||
if(!length(evaporation_queue))
|
||||
populate_evaporation = TRUE
|
||||
for(var/datum/liquid_group/liquid_group as anything in group_process_work_queue)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(QDELETED(liquid_group))
|
||||
group_process_work_queue -= liquid_group
|
||||
continue
|
||||
liquid_group.process_group(TRUE)
|
||||
if(populate_evaporation && (liquid_group.expected_turf_height < LIQUID_ANKLES_LEVEL_HEIGHT) && liquid_group.evaporates)
|
||||
for(var/turf/listed_turf as anything in liquid_group.members)
|
||||
if(QDELETED(listed_turf))
|
||||
continue
|
||||
evaporation_queue |= listed_turf
|
||||
group_process_work_queue -= liquid_group
|
||||
|
||||
|
||||
run_type = SSLIQUIDS_RUN_TYPE_TEMPERATURE
|
||||
|
||||
if(run_type == SSLIQUIDS_RUN_TYPE_TEMPERATURE)
|
||||
listclearnulls(temperature_queue)
|
||||
if(length(temperature_queue))
|
||||
for(var/turf/open/temperature_turf as anything in temperature_queue)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
temperature_queue -= temperature_turf
|
||||
if(QDELETED(temperature_turf.liquids))
|
||||
continue
|
||||
if(QDELETED(temperature_turf.liquids.liquid_group))
|
||||
QDEL_NULL(temperature_turf.liquids)
|
||||
continue
|
||||
temperature_turf.liquids.liquid_group.act_on_queue(temperature_turf)
|
||||
run_type = SSLIQUIDS_RUN_TYPE_EVAPORATION
|
||||
|
||||
if(run_type == SSLIQUIDS_RUN_TYPE_EVAPORATION && !debug_evaporation)
|
||||
listclearnulls(evaporation_queue)
|
||||
evaporation_counter++
|
||||
if(evaporation_counter >= REQUIRED_EVAPORATION_PROCESSES)
|
||||
evaporation_counter = 0
|
||||
for(var/datum/liquid_group/liquid_group as anything in active_groups)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(QDELETED(liquid_group))
|
||||
active_groups -= liquid_group
|
||||
continue
|
||||
liquid_group.check_dead()
|
||||
if(!length(liquid_group?.splitting_array))
|
||||
liquid_group.process_turf_disperse()
|
||||
for(var/turf/liquid_turf as anything in evaporation_queue)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(!prob(EVAPORATION_CHANCE) || QDELETED(liquid_turf))
|
||||
evaporation_queue -= liquid_turf
|
||||
continue
|
||||
liquid_turf?.liquids?.process_evaporation()
|
||||
run_type = SSLIQUIDS_RUN_TYPE_FIRE
|
||||
|
||||
if(run_type == SSLIQUIDS_RUN_TYPE_FIRE)
|
||||
fire_counter++
|
||||
for(var/datum/liquid_group/liquid_group as anything in active_groups)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(length(liquid_group?.burning_members))
|
||||
for(var/turf/burning_turf as anything in liquid_group.burning_members)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(!istype(burning_turf) || QDELING(burning_turf))
|
||||
liquid_group.burning_members -= burning_turf
|
||||
continue
|
||||
liquid_group.process_spread(burning_turf)
|
||||
|
||||
if(fire_counter > REQUIRED_FIRE_PROCESSES)
|
||||
for(var/datum/liquid_group/liquid_group as anything in active_groups)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(QDELETED(liquid_group))
|
||||
active_groups -= liquid_group
|
||||
continue
|
||||
if(length(liquid_group.burning_members))
|
||||
liquid_group.process_fire()
|
||||
fire_counter = 0
|
||||
run_type = SSLIQUIDS_RUN_TYPE_OCEAN
|
||||
|
||||
if(!length(currentrun_active_ocean_turfs))
|
||||
currentrun_active_ocean_turfs = active_ocean_turfs
|
||||
|
||||
if(run_type == SSLIQUIDS_RUN_TYPE_OCEAN)
|
||||
listclearnulls(currentrun_active_ocean_turfs)
|
||||
ocean_counter++
|
||||
if(ocean_counter >= REQUIRED_OCEAN_PROCESSES)
|
||||
for(var/turf/open/floor/plating/ocean/active_ocean in currentrun_active_ocean_turfs)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
active_ocean.process_turf()
|
||||
ocean_counter = 0
|
||||
run_type = SSLIQUIDS_RUN_TYPE_TURFS
|
||||
|
||||
if(run_type == SSLIQUIDS_RUN_TYPE_TURFS)
|
||||
member_counter++
|
||||
if(!length(active_turf_group_queue))
|
||||
active_turf_group_queue += active_groups
|
||||
listclearnulls(active_turf_group_queue)
|
||||
|
||||
if(member_counter > REQUIRED_MEMBER_PROCESSES)
|
||||
for(var/datum/liquid_group/liquid_group as anything in active_turf_group_queue)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(QDELETED(liquid_group))
|
||||
active_turf_group_queue -= liquid_group
|
||||
continue
|
||||
liquid_group.build_turf_reagent()
|
||||
active_turf_group_queue -= liquid_group
|
||||
if(!liquid_group.exposure)
|
||||
continue
|
||||
for(var/turf/member as anything in liquid_group.members)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(!istype(member) || QDELING(member))
|
||||
liquid_group.members -= member
|
||||
continue
|
||||
liquid_group.process_member(member)
|
||||
member_counter = 0
|
||||
run_type = SSLIQUIDS_RUN_TYPE_CACHED_EDGES
|
||||
|
||||
if(run_type == SSLIQUIDS_RUN_TYPE_CACHED_EDGES)
|
||||
if(!length(cached_edge_work_queue))
|
||||
cached_edge_work_queue |= active_groups
|
||||
listclearnulls(cached_edge_work_queue)
|
||||
|
||||
if(length(cached_edge_work_queue))
|
||||
for(var/datum/liquid_group/liquid_group as anything in cached_edge_work_queue)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
if(QDELETED(liquid_group))
|
||||
cached_edge_work_queue -= liquid_group
|
||||
continue
|
||||
|
||||
liquid_group.build_turf_reagent()
|
||||
if(liquid_group.reagents_per_turf > LIQUID_HEIGHT_DIVISOR)
|
||||
liquid_group.process_cached_edges()
|
||||
cached_edge_work_queue -= liquid_group
|
||||
|
||||
|
||||
run_type = SSLIQUIDS_RUN_TYPE_GROUPS
|
||||
|
||||
|
||||
/client/proc/toggle_liquid_debug()
|
||||
set category = "Debug"
|
||||
set name = "Liquid Groups Color Debug"
|
||||
set desc = "Liquid Groups Color Debug."
|
||||
if(!holder)
|
||||
return
|
||||
GLOB.liquid_debug_colors = !GLOB.liquid_debug_colors
|
||||
312
yogstation/code/modules/liquids/liquid_effect.dm
Normal file
@@ -0,0 +1,312 @@
|
||||
/obj/effect/abstract/liquid_turf
|
||||
name = "liquid"
|
||||
icon = 'yogstation/icons/obj/effects/liquid.dmi'
|
||||
icon_state = "water-0"
|
||||
base_icon_state = "water"
|
||||
anchored = TRUE
|
||||
plane = FLOOR_PLANE
|
||||
color = "#DDF"
|
||||
alpha = 175
|
||||
//For being on fire
|
||||
light_power = 1
|
||||
light_color = LIGHT_COLOR_FIRE
|
||||
|
||||
smoothing_flags = SMOOTH_BITMASK | SMOOTH_OBJ
|
||||
smoothing_groups = SMOOTH_GROUP_WATER
|
||||
canSmoothWith = SMOOTH_GROUP_WATER + SMOOTH_GROUP_WINDOW_FULLTILE + SMOOTH_GROUP_WALLS
|
||||
|
||||
mouse_opacity = FALSE
|
||||
|
||||
var/datum/liquid_group/liquid_group
|
||||
var/turf/my_turf
|
||||
|
||||
var/fire_state = LIQUID_FIRE_STATE_NONE
|
||||
var/liquid_state = LIQUID_STATE_PUDDLE
|
||||
var/no_effects = FALSE
|
||||
|
||||
|
||||
var/static/obj/effect/abstract/fire/small_fire/small_fire
|
||||
var/static/obj/effect/abstract/fire/medium_fire/medium_fire
|
||||
var/static/obj/effect/abstract/fire/big_fire/big_fire
|
||||
|
||||
var/mutable_appearance/displayed_content
|
||||
/// State-specific message chunks for examine_turf()
|
||||
var/static/list/liquid_state_messages = list(
|
||||
"[LIQUID_STATE_PUDDLE]" = "a puddle of $",
|
||||
"[LIQUID_STATE_ANKLES]" = "$ going [span_warning("up to your ankles")]",
|
||||
"[LIQUID_STATE_WAIST]" = "$ going [span_warning("up to your waist")]",
|
||||
"[LIQUID_STATE_SHOULDERS]" = "$ going [span_warning("up to your shoulders")]",
|
||||
"[LIQUID_STATE_FULLTILE]" = "$ going [span_danger("over your head")]",
|
||||
)
|
||||
|
||||
var/temporary_split_key
|
||||
|
||||
|
||||
/obj/effect/abstract/liquid_turf/proc/process_evaporation()
|
||||
if(liquid_group.expected_turf_height > LIQUID_ANKLES_LEVEL_HEIGHT)
|
||||
SSliquids.evaporation_queue -= my_turf
|
||||
return
|
||||
|
||||
//See if any of our reagents evaporates
|
||||
var/any_change = FALSE
|
||||
var/datum/reagent/R //Faster declaration
|
||||
for(var/reagent_type in liquid_group.reagents.reagent_list)
|
||||
R = reagent_type
|
||||
//We evaporate. bye bye
|
||||
if(initial(R.evaporates))
|
||||
var/remove_amount = min((initial(R.evaporation_rate) * GLOB.global_evaporation_rate), R.volume, (liquid_group.reagents_per_turf / length(liquid_group.reagents.reagent_list)))
|
||||
liquid_group.remove_specific(src, remove_amount, R, TRUE)
|
||||
any_change = TRUE
|
||||
R.evaporate(src.loc, remove_amount)
|
||||
if(initial(R.group_evaporation_rate))
|
||||
var/remove_amount = min((initial(R.group_evaporation_rate) * GLOB.global_evaporation_rate), liquid_group.total_reagent_volume, (liquid_group.reagents_per_turf / length(liquid_group.reagents.reagent_list)))
|
||||
liquid_group.remove_any(src, remove_amount)
|
||||
any_change = TRUE
|
||||
R.evaporate(src.loc, remove_amount)
|
||||
if(!any_change)
|
||||
SSliquids.evaporation_queue -= my_turf
|
||||
return
|
||||
|
||||
/obj/effect/abstract/liquid_turf/forceMove(atom/destination, no_tp=FALSE, harderforce = FALSE)
|
||||
if(harderforce)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/abstract/liquid_turf/proc/set_new_liquid_state(new_state)
|
||||
if(no_effects)
|
||||
return
|
||||
liquid_state = new_state
|
||||
|
||||
var/number = new_state - 1
|
||||
if(number != 0)
|
||||
icon_state = null
|
||||
base_icon_state = null
|
||||
update_appearance()
|
||||
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
base_icon_state = initial(base_icon_state)
|
||||
QUEUE_SMOOTH(src)
|
||||
QUEUE_SMOOTH_NEIGHBORS(src)
|
||||
|
||||
/obj/effect/abstract/liquid_turf/update_overlays()
|
||||
. = ..()
|
||||
var/number = liquid_state - 1
|
||||
if(number != 0)
|
||||
. += mutable_appearance('yogstation/icons/obj/effects/liquid_overlays.dmi', "stage[number]_bottom", offset_spokesman = my_turf, plane = ABOVE_GAME_PLANE, layer = ABOVE_MOB_LAYER)
|
||||
. += mutable_appearance('yogstation/icons/obj/effects/liquid_overlays.dmi', "stage[number]_top", offset_spokesman = my_turf, plane =GAME_PLANE, layer = GATEWAY_UNDERLAY_LAYER)
|
||||
|
||||
/obj/effect/abstract/liquid_turf/proc/set_fire_effect()
|
||||
if(displayed_content)
|
||||
vis_contents -= displayed_content
|
||||
|
||||
if(!liquid_group)
|
||||
return
|
||||
|
||||
switch(liquid_group.group_fire_state)
|
||||
if(LIQUID_FIRE_STATE_SMALL)
|
||||
displayed_content = small_fire
|
||||
if(LIQUID_FIRE_STATE_MILD)
|
||||
displayed_content = small_fire
|
||||
if(LIQUID_FIRE_STATE_MEDIUM)
|
||||
displayed_content = medium_fire
|
||||
if(LIQUID_FIRE_STATE_HUGE)
|
||||
displayed_content = big_fire
|
||||
if(LIQUID_FIRE_STATE_INFERNO)
|
||||
displayed_content = big_fire
|
||||
else
|
||||
displayed_content = null
|
||||
|
||||
if(displayed_content)
|
||||
vis_contents |= displayed_content
|
||||
|
||||
//Takes a flat of our reagents and returns it, possibly qdeling our liquids
|
||||
/obj/effect/abstract/liquid_turf/proc/take_reagents_flat(flat_amount)
|
||||
liquid_group.remove_any(src, flat_amount)
|
||||
|
||||
/obj/effect/abstract/liquid_turf/proc/movable_entered(datum/source, atom/movable/AM)
|
||||
SIGNAL_HANDLER
|
||||
if(!liquid_group)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
var/turf/T = source
|
||||
if(isobserver(AM))
|
||||
return //ghosts, camera eyes, etc. don't make water splashy splashy
|
||||
if(liquid_group.group_overlay_state >= LIQUID_STATE_ANKLES)
|
||||
if(prob(30))
|
||||
var/sound_to_play = pick(list(
|
||||
'yogstation/sound/effects/water_wade1.ogg',
|
||||
'yogstation/sound/effects/water_wade2.ogg',
|
||||
'yogstation/sound/effects/water_wade3.ogg',
|
||||
'yogstation/sound/effects/water_wade4.ogg'
|
||||
))
|
||||
playsound(T, sound_to_play, 50, 0)
|
||||
if(iscarbon(AM))
|
||||
var/mob/living/carbon/C = AM
|
||||
C.apply_status_effect(/datum/status_effect/water_affected)
|
||||
if(isliving(AM))
|
||||
var/mob/living/carbon/human/stepped_human = AM
|
||||
liquid_group.expose_atom(stepped_human, 1, TOUCH)
|
||||
else if (isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(liquid_group.slippery)
|
||||
if(prob(7) && !(L.movement_type & FLYING) && L.body_position == STANDING_UP)
|
||||
L.slip(30, T, NO_SLIP_WHEN_WALKING, 0, TRUE)
|
||||
|
||||
if(fire_state)
|
||||
AM.fire_act((T20C+50) + (50*fire_state), 125)
|
||||
|
||||
/obj/effect/abstract/liquid_turf/proc/mob_fall(datum/source, mob/M)
|
||||
SIGNAL_HANDLER
|
||||
var/turf/T = source
|
||||
if(liquid_group.group_overlay_state >= LIQUID_STATE_ANKLES && T.has_gravity(T))
|
||||
playsound(T, 'yogstation/sound/effects/splash.ogg', 50, 0)
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/C = M
|
||||
if(C.wear_mask && C.wear_mask.flags_cover & MASKCOVERSMOUTH)
|
||||
to_chat(C, span_userdanger("You fall in the water!"))
|
||||
else
|
||||
liquid_group.transfer_to_atom(src, CHOKE_REAGENTS_INGEST_ON_FALL_AMOUNT, C)
|
||||
C.adjustOxyLoss(5)
|
||||
//C.emote("cough")
|
||||
INVOKE_ASYNC(C, TYPE_PROC_REF(/mob, emote), "cough")
|
||||
to_chat(C, span_userdanger("You fall in and swallow some water!"))
|
||||
else
|
||||
to_chat(M, span_userdanger("You fall in the water!"))
|
||||
|
||||
/obj/effect/abstract/liquid_turf/Initialize(mapload, datum/liquid_group/group_to_add)
|
||||
. = ..()
|
||||
if(!small_fire)
|
||||
small_fire = new
|
||||
if(!medium_fire)
|
||||
medium_fire = new
|
||||
if(!big_fire)
|
||||
big_fire = new
|
||||
|
||||
if(!my_turf)
|
||||
my_turf = loc
|
||||
|
||||
if(!my_turf.liquids)
|
||||
my_turf.liquids = src
|
||||
|
||||
if(group_to_add)
|
||||
group_to_add.add_to_group(my_turf)
|
||||
set_new_liquid_state(liquid_group.group_overlay_state)
|
||||
|
||||
if(!liquid_group && !group_to_add)
|
||||
liquid_group = new(1, src)
|
||||
|
||||
if(!SSliquids)
|
||||
CRASH("Liquid Turf created with the liquids sybsystem not yet initialized!")
|
||||
my_turf = loc
|
||||
RegisterSignal(my_turf, COMSIG_ATOM_ENTERED, PROC_REF(movable_entered))
|
||||
RegisterSignal(my_turf, COMSIG_TURF_MOB_FALL, PROC_REF(mob_fall))
|
||||
RegisterSignal(my_turf, COMSIG_ATOM_EXAMINE, PROC_REF(examine_turf))
|
||||
|
||||
SEND_SIGNAL(my_turf, COMSIG_TURF_LIQUIDS_CREATION, src)
|
||||
|
||||
if(z)
|
||||
QUEUE_SMOOTH(src)
|
||||
QUEUE_SMOOTH_NEIGHBORS(src)
|
||||
|
||||
|
||||
/obj/effect/abstract/liquid_turf/Destroy(force)
|
||||
UnregisterSignal(my_turf, list(COMSIG_ATOM_ENTERED, COMSIG_TURF_MOB_FALL, COMSIG_ATOM_EXAMINE))
|
||||
if(liquid_group)
|
||||
liquid_group.remove_from_group(my_turf)
|
||||
if(my_turf in SSliquids.evaporation_queue)
|
||||
SSliquids.evaporation_queue -= my_turf
|
||||
if(my_turf in SSliquids.burning_turfs)
|
||||
SSliquids.burning_turfs -= my_turf
|
||||
my_turf.liquids = null
|
||||
my_turf = null
|
||||
QUEUE_SMOOTH_NEIGHBORS(src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/abstract/liquid_turf/proc/ChangeToNewTurf(turf/NewT)
|
||||
if(NewT.liquids)
|
||||
stack_trace("Liquids tried to change to a new turf, that already had liquids on it!")
|
||||
|
||||
UnregisterSignal(my_turf, list(COMSIG_ATOM_ENTERED, COMSIG_TURF_MOB_FALL))
|
||||
if(SSliquids.evaporation_queue[my_turf])
|
||||
SSliquids.evaporation_queue -= my_turf
|
||||
SSliquids.evaporation_queue[NewT] = TRUE
|
||||
my_turf.liquids = null
|
||||
my_turf = NewT
|
||||
liquid_group.move_liquid_group(src)
|
||||
NewT.liquids = src
|
||||
loc = NewT
|
||||
RegisterSignal(my_turf, COMSIG_ATOM_ENTERED, PROC_REF(movable_entered))
|
||||
RegisterSignal(my_turf, COMSIG_TURF_MOB_FALL, PROC_REF(mob_fall))
|
||||
|
||||
/**
|
||||
* Handles COMSIG_ATOM_EXAMINE for the turf.
|
||||
*
|
||||
* Adds reagent info to examine text.
|
||||
* Arguments:
|
||||
* * source - the turf we're peekin at
|
||||
* * examiner - the user
|
||||
* * examine_text - the examine list
|
||||
* */
|
||||
/obj/effect/abstract/liquid_turf/proc/examine_turf(turf/source, mob/examiner, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!liquid_group)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// This should always have reagents if this effect object exists, but as a sanity check...
|
||||
if(!length(liquid_group.reagents.reagent_list))
|
||||
return
|
||||
|
||||
var/liquid_state_template = liquid_state_messages["[liquid_group.group_overlay_state]"]
|
||||
|
||||
examine_list += "<hr>"
|
||||
|
||||
if(examiner.can_see_reagents())
|
||||
examine_list += "<hr>"
|
||||
|
||||
if(length(liquid_group.reagents.reagent_list) == 1)
|
||||
// Single reagent text.
|
||||
var/datum/reagent/reagent_type = liquid_group.reagents.reagent_list[1]
|
||||
var/reagent_name = initial(reagent_type.name)
|
||||
var/volume = round(reagent_type.volume / length(liquid_group.members), 0.01)
|
||||
|
||||
examine_list += span_notice("There is [replacetext(liquid_state_template, "$", "[volume] units of [reagent_name]")] here.")
|
||||
else
|
||||
// Show each individual reagent
|
||||
examine_list += "There is [replacetext(liquid_state_template, "$", "the following")] here:"
|
||||
|
||||
for(var/datum/reagent/reagent_type as anything in liquid_group.reagents.reagent_list)
|
||||
var/reagent_name = initial(reagent_type.name)
|
||||
var/volume = round(reagent_type.volume / length(liquid_group.members), 0.01)
|
||||
examine_list += "• [volume] units of [reagent_name]"
|
||||
|
||||
examine_list += span_notice("The solution has a temperature of [liquid_group.group_temperature]K.")
|
||||
examine_list += "<hr>"
|
||||
return
|
||||
|
||||
// Otherwise, just show the total volume
|
||||
examine_list += span_notice("There is [replacetext(liquid_state_template, "$", "liquid")] here.")
|
||||
|
||||
/obj/effect/temp_visual/liquid_splash
|
||||
icon = 'yogstation/icons/obj/effects/splash.dmi'
|
||||
icon_state = "splash"
|
||||
layer = FLY_LAYER
|
||||
randomdir = FALSE
|
||||
|
||||
/obj/effect/abstract/fire
|
||||
icon = 'yogstation/icons/obj/effects/liquid.dmi'
|
||||
plane = FLOOR_PLANE
|
||||
layer = BELOW_MOB_LAYER
|
||||
mouse_opacity = FALSE
|
||||
appearance_flags = RESET_COLOR | RESET_ALPHA
|
||||
|
||||
/obj/effect/abstract/fire/small_fire
|
||||
icon_state = "fire_small"
|
||||
|
||||
/obj/effect/abstract/fire/medium_fire
|
||||
icon_state = "fire_medium"
|
||||
|
||||
/obj/effect/abstract/fire/big_fire
|
||||
icon_state = "fire_big"
|
||||
1028
yogstation/code/modules/liquids/liquid_groups.dm
Normal file
45
yogstation/code/modules/liquids/liquid_height.dm
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Liquid Height element; for dynamically applying liquid blockages.
|
||||
*
|
||||
* Used for reinforced tables, sandbags, and the likes.
|
||||
*/
|
||||
/datum/element/liquids_height
|
||||
element_flags = ELEMENT_BESPOKE
|
||||
argument_hash_start_idx = 2
|
||||
|
||||
///Height applied by this element
|
||||
var/height_applied
|
||||
|
||||
/datum/element/liquids_height/Attach(datum/target, height_applied)
|
||||
. = ..()
|
||||
if(!ismovable(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
src.height_applied = height_applied
|
||||
|
||||
RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_target_move))
|
||||
var/atom/movable/movable_target = target
|
||||
if(isturf(movable_target.loc))
|
||||
var/turf/turf_loc = movable_target.loc
|
||||
turf_loc.turf_height += height_applied
|
||||
turf_loc.reasses_liquids()
|
||||
|
||||
/datum/element/liquids_height/Detach(atom/movable/target)
|
||||
. = ..()
|
||||
UnregisterSignal(target, list(COMSIG_MOVABLE_MOVED))
|
||||
var/atom/movable/movable_target = target
|
||||
if(isturf(movable_target.loc))
|
||||
var/turf/turf_loc = movable_target.loc
|
||||
turf_loc.turf_height -= height_applied
|
||||
turf_loc.reasses_liquids()
|
||||
|
||||
/datum/element/liquids_height/proc/on_target_move(atom/movable/source, atom/OldLoc, Dir, Forced = FALSE)
|
||||
SIGNAL_HANDLER
|
||||
if(isturf(OldLoc))
|
||||
var/turf/old_turf = OldLoc
|
||||
old_turf.turf_height += height_applied
|
||||
old_turf.reasses_liquids()
|
||||
if(isturf(source.loc))
|
||||
var/turf/new_turf = source.loc
|
||||
new_turf.turf_height -= height_applied
|
||||
new_turf.reasses_liquids()
|
||||
28
yogstation/code/modules/liquids/liquid_interaction.dm
Normal file
@@ -0,0 +1,28 @@
|
||||
///This element allows for items to interact with liquids on turfs.
|
||||
/datum/component/liquids_interaction
|
||||
///Callback interaction called when the turf has some liquids on it
|
||||
var/datum/callback/interaction_callback
|
||||
|
||||
/datum/component/liquids_interaction/Initialize(on_interaction_callback)
|
||||
. = ..()
|
||||
|
||||
if(!istype(parent, /obj/item))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
interaction_callback = CALLBACK(parent, on_interaction_callback)
|
||||
|
||||
/datum/component/liquids_interaction/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(AfterAttack)) //The only signal allowing item -> turf interaction
|
||||
|
||||
/datum/component/liquids_interaction/UnregisterFromParent()
|
||||
UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK)
|
||||
|
||||
/datum/component/liquids_interaction/proc/AfterAttack(datum/source, atom/victim, mob/caster, proximity_flag, click_parameters)
|
||||
SIGNAL_HANDLER
|
||||
var/turf/turf_target = victim
|
||||
|
||||
if(!isturf(turf_target) || !turf_target.liquids)
|
||||
return NONE
|
||||
|
||||
if(interaction_callback.Invoke(parent, victim, caster, turf_target.liquids))
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
332
yogstation/code/modules/liquids/liquid_ocean.dm
Normal file
@@ -0,0 +1,332 @@
|
||||
GLOBAL_LIST_INIT(initalized_ocean_areas, list())
|
||||
/area/ocean
|
||||
name = "Ocean"
|
||||
|
||||
icon = 'yogstation/icons/obj/effects/liquid.dmi'
|
||||
base_icon_state = "ocean"
|
||||
icon_state = "ocean"
|
||||
alpha = 120
|
||||
|
||||
requires_power = TRUE
|
||||
always_unpowered = TRUE
|
||||
|
||||
power_light = FALSE
|
||||
power_equip = FALSE
|
||||
power_environ = FALSE
|
||||
|
||||
outdoors = TRUE
|
||||
ambience_index = AMBIENCE_SPACE
|
||||
|
||||
flags_1 = CAN_BE_DIRTY_1
|
||||
sound_environment = SOUND_AREA_SPACE
|
||||
|
||||
/area/ocean/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.initalized_ocean_areas += src
|
||||
|
||||
/area/ocean/dark
|
||||
base_lighting_alpha = 0
|
||||
|
||||
/area/ruin/ocean
|
||||
has_gravity = TRUE
|
||||
|
||||
/area/ruin/ocean/listening_outpost
|
||||
unique = TRUE
|
||||
|
||||
/area/ruin/ocean/bunker
|
||||
unique = TRUE
|
||||
|
||||
/area/ruin/ocean/bioweapon_research
|
||||
unique = TRUE
|
||||
|
||||
/area/ruin/ocean/mining_site
|
||||
unique = TRUE
|
||||
|
||||
/area/ocean/near_station_powered
|
||||
requires_power = FALSE
|
||||
|
||||
/turf/open/openspace/ocean
|
||||
name = "ocean"
|
||||
planetary_atmos = TRUE
|
||||
baseturfs = /turf/open/openspace/ocean
|
||||
var/replacement_turf = /turf/open/floor/plating/ocean
|
||||
|
||||
/turf/open/openspace/ocean/Initialize()
|
||||
. = ..()
|
||||
ChangeTurf(replacement_turf, null, CHANGETURF_IGNORE_AIR)
|
||||
|
||||
/turf/open/floor/plating
|
||||
///do we still call parent but dont want other stuff?
|
||||
var/overwrites_attack_by = FALSE
|
||||
|
||||
/turf/open/floor/plating/ocean
|
||||
plane = FLOOR_PLANE
|
||||
layer = TURF_LAYER
|
||||
force_no_gravity = FALSE
|
||||
gender = PLURAL
|
||||
name = "ocean sand"
|
||||
baseturfs = /turf/open/floor/plating/ocean
|
||||
icon = 'yogstation/icons/turf/floors/seafloor.dmi'
|
||||
icon_state = "seafloor"
|
||||
base_icon_state = "seafloor"
|
||||
footstep = FOOTSTEP_SAND
|
||||
barefootstep = FOOTSTEP_SAND
|
||||
clawfootstep = FOOTSTEP_SAND
|
||||
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
|
||||
planetary_atmos = TRUE
|
||||
initial_gas_mix = OCEAN_DEFAULT_ATMOS
|
||||
|
||||
upgradable = FALSE
|
||||
attachment_holes = FALSE
|
||||
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
|
||||
overwrites_attack_by = TRUE
|
||||
|
||||
var/static/obj/effect/abstract/ocean_overlay/static_overlay
|
||||
var/static/list/ocean_reagents = list(/datum/reagent/water = 10)
|
||||
var/ocean_temp = T20C
|
||||
var/list/ocean_turfs = list()
|
||||
var/list/open_turfs = list()
|
||||
|
||||
///are we captured, this is easier than having to run checks on turfs for vents
|
||||
var/captured = FALSE
|
||||
|
||||
var/rand_variants = 0
|
||||
var/rand_chance = 30
|
||||
|
||||
/// Itemstack to drop when dug by a shovel
|
||||
var/obj/item/stack/dig_result = /obj/item/stack/ore/glass
|
||||
/// Whether the turf has been dug or not
|
||||
var/dug = FALSE
|
||||
|
||||
/// do we build a catwalk or plating with rods
|
||||
var/catwalk = FALSE
|
||||
|
||||
/turf/open/floor/plating/ocean/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_ATOM_ENTERED, PROC_REF(movable_entered))
|
||||
RegisterSignal(src, COMSIG_TURF_MOB_FALL, PROC_REF(mob_fall))
|
||||
if(!static_overlay)
|
||||
static_overlay = new(null, ocean_reagents)
|
||||
|
||||
vis_contents += static_overlay
|
||||
light_color = static_overlay.color
|
||||
SSliquids.unvalidated_oceans |= src
|
||||
SSliquids.ocean_turfs |= src
|
||||
|
||||
if(rand_variants && prob(rand_chance))
|
||||
var/random = rand(1,rand_variants)
|
||||
icon_state = "[base_icon_state][random]"
|
||||
base_icon_state = "[base_icon_state][random]"
|
||||
|
||||
|
||||
/turf/open/floor/plating/ocean/Destroy()
|
||||
. = ..()
|
||||
UnregisterSignal(src, list(COMSIG_ATOM_ENTERED, COMSIG_TURF_MOB_FALL))
|
||||
SSliquids.active_ocean_turfs -= src
|
||||
SSliquids.ocean_turfs -= src
|
||||
for(var/turf/open/floor/plating/ocean/listed_ocean as anything in ocean_turfs)
|
||||
listed_ocean.rebuild_adjacent()
|
||||
|
||||
/turf/open/floor/plating/ocean/attackby(obj/item/C, mob/user, params)
|
||||
if(..())
|
||||
return
|
||||
if(istype(C, /obj/item/stack/rods))
|
||||
var/obj/item/stack/rods/R = C
|
||||
if (R.get_amount() < 2)
|
||||
to_chat(user, span_warning("You need two rods to make a [catwalk ? "catwalk" : "plating"]!"))
|
||||
return
|
||||
else
|
||||
to_chat(user, span_notice("You begin constructing a [catwalk ? "catwalk" : "plating"]..."))
|
||||
if(do_after(user, 30, target = src))
|
||||
if (R.get_amount() >= 2 && !catwalk)
|
||||
place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE)
|
||||
R.use(2)
|
||||
to_chat(user, span_notice("You reinforce the [src]."))
|
||||
else if(R.get_amount() >= 2 && catwalk)
|
||||
new /obj/structure/lattice/catwalk(src)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE)
|
||||
R.use(2)
|
||||
to_chat(user, span_notice("You build a catwalk over the [src]."))
|
||||
|
||||
/// Drops itemstack when dug and changes icon
|
||||
/turf/open/floor/plating/ocean/proc/getDug()
|
||||
dug = TRUE
|
||||
new dig_result(src, 5)
|
||||
|
||||
/// If the user can dig the turf
|
||||
/turf/open/floor/plating/ocean/proc/can_dig(mob/user)
|
||||
if(!dug)
|
||||
return TRUE
|
||||
if(user)
|
||||
to_chat(user, span_warning("Looks like someone has dug here already!"))
|
||||
|
||||
|
||||
/turf/open/floor/plating/ocean/proc/assume_self()
|
||||
if(!atmos_adjacent_turfs)
|
||||
immediate_calculate_adjacent_turfs()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/turf/directional_turf = get_step(src, direction)
|
||||
if(istype(directional_turf, /turf/open/floor/plating/ocean))
|
||||
ocean_turfs |= directional_turf
|
||||
else
|
||||
if(isclosedturf(directional_turf))
|
||||
RegisterSignal(directional_turf, COMSIG_TURF_DESTROY, PROC_REF(add_turf_direction), TRUE)
|
||||
continue
|
||||
else if(!(directional_turf in atmos_adjacent_turfs))
|
||||
var/obj/machinery/door/found_door = locate(/obj/machinery/door) in directional_turf
|
||||
if(found_door)
|
||||
RegisterSignal(found_door, COMSIG_ATOM_DOOR_OPEN, TYPE_PROC_REF(/turf/open/floor/plating/ocean, door_opened))
|
||||
RegisterSignal(directional_turf, COMSIG_TURF_UPDATE_AIR, PROC_REF(add_turf_direction_non_closed), TRUE)
|
||||
continue
|
||||
else
|
||||
open_turfs.Add(direction)
|
||||
|
||||
if(open_turfs.len)
|
||||
SSliquids.active_ocean_turfs |= src
|
||||
SSliquids.unvalidated_oceans -= src
|
||||
|
||||
/turf/open/floor/plating/ocean/proc/door_opened(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/machinery/door/found_door = source
|
||||
var/turf/turf = get_turf(found_door)
|
||||
|
||||
if(turf.can_atmos_pass())
|
||||
turf.add_liquid_list(ocean_reagents, FALSE, ocean_temp)
|
||||
|
||||
/turf/open/floor/plating/ocean/proc/process_turf()
|
||||
for(var/direction in open_turfs)
|
||||
var/turf/directional_turf = get_step(src, direction)
|
||||
if(isspaceturf(directional_turf) || istype(directional_turf, /turf/open/floor/plating/ocean))
|
||||
RegisterSignal(directional_turf, COMSIG_TURF_DESTROY, PROC_REF(add_turf_direction), TRUE)
|
||||
open_turfs -= direction
|
||||
if(!open_turfs.len)
|
||||
SSliquids.active_ocean_turfs -= src
|
||||
return
|
||||
else if(!(directional_turf in atmos_adjacent_turfs))
|
||||
RegisterSignal(directional_turf, COMSIG_TURF_UPDATE_AIR, PROC_REF(add_turf_direction_non_closed), TRUE)
|
||||
open_turfs -= direction
|
||||
if(!open_turfs.len)
|
||||
SSliquids.active_ocean_turfs -= src
|
||||
return
|
||||
|
||||
directional_turf.add_liquid_list(ocean_reagents, FALSE, ocean_temp)
|
||||
|
||||
/turf/open/floor/plating/ocean/proc/rebuild_adjacent()
|
||||
ocean_turfs = list()
|
||||
open_turfs = list()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/turf/directional_turf = get_step(src, direction)
|
||||
if(istype(directional_turf, /turf/open/floor/plating/ocean))
|
||||
ocean_turfs |= directional_turf
|
||||
else
|
||||
open_turfs.Add(direction)
|
||||
|
||||
if(open_turfs.len)
|
||||
SSliquids.active_ocean_turfs |= src
|
||||
else if(src in SSliquids.active_ocean_turfs)
|
||||
SSliquids.active_ocean_turfs -= src
|
||||
|
||||
/turf/open/floor/plating/ocean/attackby(obj/item/C, mob/user, params)
|
||||
. = ..()
|
||||
|
||||
if(C.tool_behaviour == TOOL_SHOVEL || C.tool_behaviour == TOOL_MINING)
|
||||
if(!can_dig(user))
|
||||
return TRUE
|
||||
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
|
||||
balloon_alert(user, "digging...")
|
||||
|
||||
if(C.use_tool(src, user, 40, volume=50))
|
||||
if(!can_dig(user))
|
||||
return TRUE
|
||||
getDug()
|
||||
SSblackbox.record_feedback("tally", "pick_used_mining", 1, C.type)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/abstract/ocean_overlay
|
||||
icon = 'yogstation/icons/obj/effects/liquid.dmi'
|
||||
icon_state = "ocean"
|
||||
base_icon_state = "ocean"
|
||||
plane = AREA_PLANE //Same as weather, etc.
|
||||
layer = ABOVE_MOB_LAYER
|
||||
vis_flags = NONE
|
||||
mouse_opacity = FALSE
|
||||
alpha = 120
|
||||
|
||||
/obj/effect/abstract/ocean_overlay/Initialize(mapload, list/ocean_contents)
|
||||
. = ..()
|
||||
var/datum/reagents/fake_reagents = new
|
||||
fake_reagents.add_reagent_list(ocean_contents)
|
||||
color = mix_color_from_reagents(fake_reagents.reagent_list)
|
||||
qdel(fake_reagents)
|
||||
if(istype(loc, /area/ocean))
|
||||
var/area/area_loc = loc
|
||||
area_loc.base_lighting_color = color
|
||||
|
||||
/obj/effect/abstract/ocean_overlay/proc/mix_colors(list/ocean_contents)
|
||||
var/datum/reagents/fake_reagents = new
|
||||
fake_reagents.add_reagent_list(ocean_contents)
|
||||
color = mix_color_from_reagents(fake_reagents.reagent_list)
|
||||
qdel(fake_reagents)
|
||||
if(istype(loc, /area/ocean))
|
||||
var/area/area_loc = loc
|
||||
area_loc.base_lighting_color = color
|
||||
|
||||
/turf/open/floor/plating/ocean/proc/mob_fall(datum/source, mob/M)
|
||||
SIGNAL_HANDLER
|
||||
var/turf/T = source
|
||||
playsound(T, 'yogstation/sound/effects/splash.ogg', 50, 0)
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/C = M
|
||||
to_chat(C, span_userdanger("You fall in the water!"))
|
||||
|
||||
/turf/open/floor/plating/ocean/proc/movable_entered(datum/source, atom/movable/AM)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/turf/T = source
|
||||
if(isobserver(AM))
|
||||
return //ghosts, camera eyes, etc. don't make water splashy splashy
|
||||
if(prob(30))
|
||||
var/sound_to_play = pick(list(
|
||||
'yogstation/sound/effects/water_wade1.ogg',
|
||||
'yogstation/sound/effects/water_wade2.ogg',
|
||||
'yogstation/sound/effects/water_wade3.ogg',
|
||||
'yogstation/sound/effects/water_wade4.ogg'
|
||||
))
|
||||
playsound(T, sound_to_play, 50, 0)
|
||||
if(isliving(AM))
|
||||
var/mob/living/arrived = AM
|
||||
if(!arrived.has_status_effect(/datum/status_effect/ocean_affected))
|
||||
arrived.apply_status_effect(/datum/status_effect/ocean_affected)
|
||||
|
||||
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WASH)
|
||||
|
||||
/turf/open/floor/plating/ocean/proc/add_turf_direction(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
var/turf/direction_turf = source
|
||||
|
||||
if(istype(direction_turf, /turf/open/floor/plating/ocean))
|
||||
return
|
||||
|
||||
open_turfs.Add(get_dir(src, direction_turf))
|
||||
|
||||
if(!(src in SSliquids.active_ocean_turfs))
|
||||
SSliquids.active_ocean_turfs |= src
|
||||
|
||||
/turf/open/floor/plating/ocean/proc/add_turf_direction_non_closed(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
var/turf/direction_turf = source
|
||||
|
||||
if(!(direction_turf in atmos_adjacent_turfs))
|
||||
return
|
||||
|
||||
open_turfs.Add(get_dir(src, direction_turf))
|
||||
|
||||
if(!(src in SSliquids.active_ocean_turfs))
|
||||
SSliquids.active_ocean_turfs |= src
|
||||
336
yogstation/code/modules/liquids/liquid_plumbers.dm
Normal file
@@ -0,0 +1,336 @@
|
||||
/**
|
||||
* Base class for underfloor plumbing machines that mess with floor liquids.
|
||||
*/
|
||||
/obj/machinery/plumbing/floor_pump
|
||||
icon = 'yogstation/icons/obj/structures/drains.dmi'
|
||||
base_icon_state = "active_input"
|
||||
icon_state = "active_input"
|
||||
anchored = FALSE
|
||||
density = FALSE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 1000
|
||||
//buffer = 300
|
||||
//category="Distribution"
|
||||
//reagent_flags = NO_REACT
|
||||
|
||||
/// Pump is turned on by engineer, etc.
|
||||
var/turned_on = FALSE
|
||||
/// Only pump to this liquid level height. 0 means pump the most possible.
|
||||
var/height_regulator = 0
|
||||
|
||||
/// The default duct layer for mapping
|
||||
var/duct_layer = 0
|
||||
|
||||
/// Base amount to drain
|
||||
var/drain_flat = 20
|
||||
/// Additional ratio of liquid volume to drain
|
||||
var/drain_percent = 1
|
||||
|
||||
/// Currently pumping.
|
||||
var/is_pumping = FALSE
|
||||
/// Floor tile is placed down
|
||||
var/tile_placed = FALSE
|
||||
|
||||
var/processes = 0
|
||||
var/processes_required = 25
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/Initialize(mapload, bolt, layer)
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_OBJ_HIDE, PROC_REF(on_hide))
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/examine(mob/user)
|
||||
. = ..()
|
||||
. += span_notice("It's currently turned [turned_on ? "ON" : "OFF"].")
|
||||
. += span_notice("Its height regulator [height_regulator ? "points at [height_regulator]" : "is disabled"]. Click while unanchored to change.")
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/update_appearance(updates)
|
||||
. = ..()
|
||||
layer = tile_placed ? GAS_SCRUBBER_LAYER : BELOW_OBJ_LAYER
|
||||
plane = tile_placed ? FLOOR_PLANE : GAME_PLANE
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/update_icon_state()
|
||||
. = ..()
|
||||
if(panel_open)
|
||||
icon_state = "[base_icon_state]-open"
|
||||
else if(is_pumping)
|
||||
icon_state = "[base_icon_state]-pumping"
|
||||
else if(is_operational() && turned_on)
|
||||
icon_state = "[base_icon_state]-idle"
|
||||
else
|
||||
icon_state = base_icon_state
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/default_unfasten_wrench(mob/user, obj/item/I, time = 20)
|
||||
. = ..()
|
||||
if(. == SUCCESSFUL_UNFASTEN)
|
||||
turned_on = FALSE
|
||||
update_icon_state()
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/attack_hand(mob/user)
|
||||
if(!anchored)
|
||||
set_regulator(user)
|
||||
return
|
||||
balloon_alert(user, "turned [turned_on ? "off" : "on"]")
|
||||
turned_on = !turned_on
|
||||
update_icon_state()
|
||||
|
||||
/**
|
||||
* Change regulator level -- ie. what liquid depth we are OK with, like a thermostat.
|
||||
*/
|
||||
/obj/machinery/plumbing/floor_pump/proc/set_regulator(mob/living/user)
|
||||
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
var/new_height = tgui_input_number(user,
|
||||
"At what water level should the pump stop pumping from 0 to [LIQUID_HEIGHT_CONSIDER_FULL_TILE]? 0 disables.",
|
||||
"[src]",
|
||||
default = height_regulator,
|
||||
min_value = 0,
|
||||
max_value = LIQUID_HEIGHT_CONSIDER_FULL_TILE)
|
||||
if(QDELETED(src) || new_height == null)
|
||||
return
|
||||
height_regulator = new_height
|
||||
|
||||
/**
|
||||
* Handle COMSIG_OBJ_HIDE to toggle whether we're on the floor
|
||||
*/
|
||||
/obj/machinery/plumbing/floor_pump/proc/on_hide(atom/movable/AM, should_hide)
|
||||
tile_placed = should_hide
|
||||
update_appearance()
|
||||
|
||||
/**
|
||||
* Can the pump actually run at all?
|
||||
*/
|
||||
/obj/machinery/plumbing/floor_pump/proc/can_run()
|
||||
return is_operational() \
|
||||
&& turned_on \
|
||||
&& anchored \
|
||||
&& !panel_open \
|
||||
&& isturf(loc) \
|
||||
&& are_reagents_ready()
|
||||
|
||||
/**
|
||||
* Is the internal reagents container able to give or take liquid as appropriate?
|
||||
*/
|
||||
/obj/machinery/plumbing/floor_pump/proc/are_reagents_ready()
|
||||
CRASH("are_reagents_ready() must be overriden.")
|
||||
|
||||
/**
|
||||
* Should we actually be pumping this tile right now?
|
||||
* Arguments:
|
||||
* * affected_turf - the turf to check.
|
||||
*/
|
||||
/obj/machinery/plumbing/floor_pump/proc/should_pump(turf/affected_turf)
|
||||
return isturf(affected_turf) \
|
||||
&& should_regulator_permit(affected_turf)
|
||||
|
||||
/**
|
||||
* Should the liquid height regulator allow water to be pumped here?
|
||||
*/
|
||||
/obj/machinery/plumbing/floor_pump/proc/should_regulator_permit(turf/affected_turf)
|
||||
CRASH("should_regulator_permit() must be overriden.")
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/process(seconds_per_tick)
|
||||
var/was_pumping = is_pumping
|
||||
|
||||
if(!can_run())
|
||||
is_pumping = FALSE
|
||||
if(was_pumping)
|
||||
update_icon_state()
|
||||
return
|
||||
|
||||
// Determine what tiles should be pumped. We grab from a 3x3 area,
|
||||
// but overall try to pump the same volume regardless of number of affected tiles
|
||||
var/turf/local_turf = get_turf(src)
|
||||
var/list/turf/candidate_turfs = local_turf.get_atmos_adjacent_turfs(alldir = TRUE)
|
||||
candidate_turfs += local_turf
|
||||
|
||||
var/list/turf/affected_turfs = list()
|
||||
|
||||
for(var/turf/candidate as anything in candidate_turfs)
|
||||
if(should_pump(candidate))
|
||||
affected_turfs += candidate
|
||||
|
||||
// Update state
|
||||
is_pumping = length(affected_turfs) > 0
|
||||
if(is_pumping != was_pumping)
|
||||
update_icon_state()
|
||||
if(!is_pumping)
|
||||
return
|
||||
|
||||
// note that the length was verified to be > 0 directly above and is a local var.
|
||||
var/multiplier = 1 / length(affected_turfs)
|
||||
|
||||
// We're good, actually pump.
|
||||
for(var/turf/affected_turf as anything in affected_turfs)
|
||||
pump_turf(affected_turf, seconds_per_tick, multiplier)
|
||||
|
||||
/**
|
||||
* Pump out the liquids on a turf.
|
||||
*
|
||||
* Arguments:
|
||||
* * affected_turf - the turf to pump liquids out of.
|
||||
* * seconds_per_tick - machine process delta time
|
||||
* * multiplier - Multiplier to apply to final volume we want to pump.
|
||||
*/
|
||||
/obj/machinery/plumbing/floor_pump/proc/pump_turf(turf/affected_turf, seconds_per_tick, multiplier)
|
||||
CRASH("pump_turf() must be overriden.")
|
||||
|
||||
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/input
|
||||
name = "liquid input pump"
|
||||
desc = "Pump used to siphon liquids from a location into the plumbing pipenet."
|
||||
icon_state = "active_input"
|
||||
base_icon_state = "active_input"
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/input/Initialize(mapload, bolt, layer)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/plumbing/simple_supply, bolt, layer || duct_layer)
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/input/are_reagents_ready()
|
||||
return reagents.total_volume < reagents.maximum_volume
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/input/should_regulator_permit(turf/affected_turf)
|
||||
return affected_turf.liquids && affected_turf.liquids.liquid_group.expected_turf_height > height_regulator
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/input/pump_turf(turf/affected_turf, seconds_per_tick, multiplier)
|
||||
if(processes < processes_required)
|
||||
processes++
|
||||
return
|
||||
processes = 0
|
||||
if(!affected_turf.liquids || !affected_turf.liquids.liquid_group || reagents.total_volume)
|
||||
return
|
||||
var/target_value = seconds_per_tick * (drain_flat + (affected_turf.liquids.liquid_group.total_reagent_volume * drain_percent)) * multiplier
|
||||
//Free space handling
|
||||
var/free_space = reagents.maximum_volume - reagents.total_volume
|
||||
if(target_value > free_space)
|
||||
target_value = free_space
|
||||
|
||||
var/datum/liquid_group/targeted_group = affected_turf.liquids.liquid_group
|
||||
if(!targeted_group.reagents_per_turf)
|
||||
return
|
||||
var/turfs_to_pull = round(target_value / targeted_group.reagents_per_turf,1)
|
||||
|
||||
var/list/removed_turfs = targeted_group.return_connected_liquids_in_range(affected_turf.liquids, turfs_to_pull)
|
||||
targeted_group.trans_to_seperate_group(reagents, target_value, merge = TRUE)
|
||||
for(var/turf/listed_turf in removed_turfs)
|
||||
var/datum/liquid_group/listed_group = listed_turf.liquids.liquid_group
|
||||
targeted_group.remove_from_group(listed_turf)
|
||||
qdel(listed_turf.liquids)
|
||||
for(var/dir in GLOB.cardinals)
|
||||
var/turf/open/direction_turf = get_step(listed_turf, dir)
|
||||
if(!isopenturf(direction_turf) || !direction_turf.liquids)
|
||||
continue
|
||||
if(!listed_group)
|
||||
continue
|
||||
listed_group.check_edges(direction_turf)
|
||||
|
||||
///recalculate the values here because processing
|
||||
targeted_group.total_reagent_volume = targeted_group.reagents.total_volume
|
||||
targeted_group.reagents_per_turf = targeted_group.total_reagent_volume / length(targeted_group.members)
|
||||
|
||||
if(!removed_turfs.len)
|
||||
return
|
||||
while(removed_turfs.len)
|
||||
var/turf/picked_turf = pick(removed_turfs)
|
||||
var/list/output = targeted_group.try_split(picked_turf, TRUE)
|
||||
removed_turfs -= picked_turf
|
||||
for(var/turf/outputted_turf in output)
|
||||
if(outputted_turf in removed_turfs)
|
||||
removed_turfs -= outputted_turf
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/input/on
|
||||
icon_state = "active_input-mapping"
|
||||
anchored = TRUE
|
||||
turned_on = TRUE
|
||||
|
||||
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/plumbing/floor_pump/input/on, 0)
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/input/on/waste
|
||||
icon_state = "active_input-mapping2"
|
||||
duct_layer = SECOND_DUCT_LAYER
|
||||
|
||||
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/plumbing/floor_pump/input/on/waste, 0)
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output
|
||||
name = "liquid output pump"
|
||||
desc = "Pump used to dump liquids out from a plumbing pipenet into a location."
|
||||
icon_state = "active_output"
|
||||
base_icon_state = "active_output"
|
||||
|
||||
/// Is the turf too full to pump more?
|
||||
var/over_volume = FALSE
|
||||
/// Max liquid volume on the turf before we stop pumping.
|
||||
var/max_ext_volume = LIQUID_HEIGHT_CONSIDER_FULL_TILE
|
||||
|
||||
/// Is the turf too high-pressured to pump more?
|
||||
var/over_pressure = FALSE
|
||||
/// Max pressure on the turf before we stop pumping.
|
||||
var/max_ext_kpa = WARNING_HIGH_PRESSURE
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output/Initialize(mapload, bolt, layer)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/plumbing/simple_demand, bolt, layer || duct_layer)
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output/examine(mob/user)
|
||||
. = ..()
|
||||
if(over_pressure)
|
||||
. += span_warning("The gas regulator light is blinking.")
|
||||
if(over_volume)
|
||||
. += span_warning("The liquid volume regulator light is blinking.")
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output/are_reagents_ready()
|
||||
return reagents.total_volume > 0
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output/should_regulator_permit(turf/affected_turf)
|
||||
// 0 means keep pumping forever.
|
||||
return !height_regulator || affected_turf.liquids.liquid_group.expected_turf_height < height_regulator
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output/process()
|
||||
over_pressure = FALSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output/should_pump(turf/affected_turf)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
if(affected_turf.liquids?.liquid_group.expected_turf_height >= max_ext_volume)
|
||||
return FALSE
|
||||
var/turf/open/open_turf = affected_turf
|
||||
var/datum/gas_mixture/gas_mix = open_turf?.return_air()
|
||||
if(gas_mix?.return_pressure() > max_ext_kpa)
|
||||
over_pressure = TRUE
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output/pump_turf(turf/affected_turf, seconds_per_tick, multiplier)
|
||||
var/target_value = seconds_per_tick * (drain_flat + (reagents.total_volume * drain_percent)) * multiplier
|
||||
if(target_value > reagents.total_volume)
|
||||
target_value = reagents.total_volume
|
||||
|
||||
var/datum/reagents/tempr = new(10000)
|
||||
reagents.trans_to(tempr, target_value, no_react = TRUE)
|
||||
affected_turf.add_liquid_from_reagents(tempr)
|
||||
qdel(tempr)
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output/on
|
||||
icon_state = "active_output-mapping"
|
||||
anchored = TRUE
|
||||
turned_on = TRUE
|
||||
|
||||
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/plumbing/floor_pump/output/on, 0)
|
||||
|
||||
/obj/machinery/plumbing/floor_pump/output/on/supply
|
||||
icon_state = "active_output-mapping2"
|
||||
duct_layer = FOURTH_DUCT_LAYER
|
||||
|
||||
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/plumbing/floor_pump/output/on/supply, 0)
|
||||
|
||||
// Helpers for maps
|
||||
/obj/machinery/duct/supply
|
||||
duct_color = COLOR_CYAN
|
||||
duct_layer = FOURTH_DUCT_LAYER
|
||||
|
||||
/obj/machinery/duct/waste
|
||||
duct_color = COLOR_BROWN
|
||||
duct_layer = SECOND_DUCT_LAYER
|
||||
99
yogstation/code/modules/liquids/liquid_pump.dm
Normal file
@@ -0,0 +1,99 @@
|
||||
//Right now it's a structure that works off of magic, as it'd require an internal power source for what its supposed to do
|
||||
/obj/structure/liquid_pump
|
||||
name = "portable liquid pump"
|
||||
desc = "An industrial grade pump, capable of either siphoning or spewing liquids. Needs to be anchored first to work. Has a limited capacity internal storage."
|
||||
icon = 'yogstation/icons/obj/structures/liquid_pump.dmi'
|
||||
icon_state = "liquid_pump"
|
||||
density = TRUE
|
||||
max_integrity = 500
|
||||
anchored = FALSE
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
/// How many reagents at maximum can it hold
|
||||
var/max_volume = 10000
|
||||
/// Whether spewing reagents out, instead of siphoning them
|
||||
var/spewing_mode = FALSE
|
||||
/// Whether its turned on and processing
|
||||
var/turned_on = FALSE
|
||||
/// How fast does the pump work, in percentages relative to the volume we're working with
|
||||
var/pump_speed_percentage = 0.4
|
||||
/// How fast does the pump work, in flat values. Flat values on top of percentages to help processing
|
||||
var/pump_speed_flat = 20
|
||||
|
||||
/obj/structure/liquid_pump/wrench_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
default_unfasten_wrench(user, I, 40)
|
||||
if(!anchored && turned_on)
|
||||
toggle_working()
|
||||
return TRUE
|
||||
|
||||
/obj/structure/liquid_pump/attack_hand(mob/user)
|
||||
if(!anchored)
|
||||
to_chat(user, span_warning("[src] needs to be anchored first!"))
|
||||
return
|
||||
to_chat(user, span_notice("You turn [src] [turned_on ? "off" : "on"]."))
|
||||
toggle_working()
|
||||
|
||||
/obj/structure/liquid_pump/AltClick(mob/living/user)
|
||||
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
to_chat(user, span_notice("You flick [src]'s spewing mode [spewing_mode ? "off" : "on"]."))
|
||||
spewing_mode = !spewing_mode
|
||||
update_icon()
|
||||
|
||||
/obj/structure/liquid_pump/examine(mob/user)
|
||||
. = ..()
|
||||
. += span_notice("It's anchor bolts are [anchored ? "down and secured" : "up"].")
|
||||
. += span_notice("It's currently [turned_on ? "ON" : "OFF"].")
|
||||
. += span_notice("It's mode currently is set to [spewing_mode ? "SPEWING" : "SIPHONING"]. (Alt-click to switch)")
|
||||
. += span_notice("The pressure gauge shows [reagents.total_volume]/[reagents.maximum_volume].")
|
||||
|
||||
/obj/structure/liquid_pump/process()
|
||||
if(!isturf(loc))
|
||||
return
|
||||
var/turf/T = loc
|
||||
if(spewing_mode)
|
||||
if(!reagents.total_volume)
|
||||
return
|
||||
var/datum/reagents/tempr = new(10000)
|
||||
reagents.trans_to(tempr, (reagents.total_volume * pump_speed_percentage) + pump_speed_flat, no_react = TRUE)
|
||||
T.add_liquid_from_reagents(tempr)
|
||||
qdel(tempr)
|
||||
else
|
||||
if(!T.liquids)
|
||||
return
|
||||
var/free_space = reagents.maximum_volume - reagents.total_volume
|
||||
if(!free_space)
|
||||
return
|
||||
var/target_siphon_amt = (T.liquids.liquid_group.total_reagent_volume * pump_speed_percentage) + pump_speed_flat
|
||||
if(target_siphon_amt > free_space)
|
||||
target_siphon_amt = free_space
|
||||
T.liquids.liquid_group.transfer_to_atom(T.liquids, target_siphon_amt, src)
|
||||
return
|
||||
|
||||
/obj/structure/liquid_pump/update_icon()
|
||||
. = ..()
|
||||
if(turned_on)
|
||||
if(spewing_mode)
|
||||
icon_state = "[initial(icon_state)]_spewing"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]_siphoning"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]"
|
||||
|
||||
/obj/structure/liquid_pump/proc/toggle_working()
|
||||
if(turned_on)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
else
|
||||
START_PROCESSING(SSobj, src)
|
||||
turned_on = !turned_on
|
||||
update_icon()
|
||||
|
||||
/obj/structure/liquid_pump/Initialize()
|
||||
. = ..()
|
||||
create_reagents(max_volume)
|
||||
|
||||
/obj/structure/liquid_pump/Destroy()
|
||||
if(turned_on)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
qdel(reagents)
|
||||
return ..()
|
||||
46
yogstation/code/modules/liquids/liquid_status_effect.dm
Normal file
@@ -0,0 +1,46 @@
|
||||
/datum/status_effect/water_affected
|
||||
id = "wateraffected"
|
||||
alert_type = null
|
||||
duration = -1
|
||||
|
||||
/datum/status_effect/water_affected/on_apply()
|
||||
//We should be inside a liquid turf if this is applied
|
||||
calculate_water_slow()
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/water_affected/proc/calculate_water_slow()
|
||||
//Factor in swimming skill here?
|
||||
var/turf/T = get_turf(owner)
|
||||
var/slowdown_amount = T.liquids.liquid_group.group_overlay_state * 0.5
|
||||
owner.add_movespeed_modifier(MOVESPEED_ID_LIQUID, multiplicative_slowdown = slowdown_amount)
|
||||
|
||||
/datum/status_effect/water_affected/tick()
|
||||
var/turf/owner_turf = get_turf(owner)
|
||||
if(QDELETED(owner_turf) || QDELETED(owner_turf.liquids) || owner_turf.liquids.liquid_group.group_overlay_state == LIQUID_STATE_PUDDLE)
|
||||
qdel(src)
|
||||
return
|
||||
calculate_water_slow()
|
||||
//Make the reagents touch the person
|
||||
|
||||
var/fraction = SUBMERGEMENT_PERCENT(owner, owner_turf.liquids)
|
||||
owner_turf.liquids.liquid_group.expose_members_turf(owner_turf.liquids)
|
||||
owner_turf.liquids.liquid_group.transfer_to_atom(owner_turf.liquids, ((SUBMERGEMENT_REAGENTS_TOUCH_AMOUNT * fraction / 20)), owner)
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/water_affected/on_remove()
|
||||
owner.remove_movespeed_modifier(MOVESPEED_ID_LIQUID)
|
||||
|
||||
/datum/status_effect/ocean_affected
|
||||
alert_type = null
|
||||
duration = -1
|
||||
|
||||
/datum/status_effect/ocean_affected/tick()
|
||||
var/turf/ocean_turf = get_turf(owner)
|
||||
if(!istype(ocean_turf, /turf/open/floor/plating/ocean))
|
||||
qdel(src)
|
||||
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/arrived = owner
|
||||
if(is_species(owner, /datum/species/ipc) && !(arrived.wear_suit?.clothing_flags & STOPSPRESSUREDAMAGE))
|
||||
arrived.adjustFireLoss(5)
|
||||
58
yogstation/code/modules/liquids/liquid_turf.dm
Normal file
@@ -0,0 +1,58 @@
|
||||
/turf
|
||||
var/obj/effect/abstract/liquid_turf/liquids
|
||||
var/liquid_height = 0
|
||||
var/turf_height = 0
|
||||
|
||||
/turf/proc/reasses_liquids()
|
||||
if(!liquids)
|
||||
return
|
||||
if(!liquids.liquid_group)
|
||||
liquids.liquid_group = new(1, liquids)
|
||||
|
||||
/turf/proc/liquid_update_turf()
|
||||
if(!liquids)
|
||||
return
|
||||
//Check atmos adjacency to cut off any disconnected groups
|
||||
if(liquids.liquid_group)
|
||||
var/assoc_atmos_turfs = list()
|
||||
for(var/tur in get_atmos_adjacent_turfs())
|
||||
assoc_atmos_turfs[tur] = TRUE
|
||||
//Check any cardinals that may have a matching group
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/turf/T = get_step(src, direction)
|
||||
if(!T.liquids)
|
||||
return
|
||||
|
||||
/turf/proc/add_liquid_from_reagents(datum/reagents/giver, no_react = FALSE, chem_temp)
|
||||
var/list/compiled_list = list()
|
||||
for(var/r in giver.reagent_list)
|
||||
var/datum/reagent/R = r
|
||||
if(!(R.type in GLOB.liquid_blacklist))
|
||||
compiled_list[R.type] = R.volume
|
||||
if(!compiled_list.len) //No reagents to add, don't bother going further
|
||||
return
|
||||
if(!liquids)
|
||||
liquids = new(src)
|
||||
liquids.liquid_group.add_reagents(liquids, compiled_list, chem_temp)
|
||||
|
||||
//More efficient than add_liquid for multiples
|
||||
/turf/proc/add_liquid_list(reagent_list, no_react = FALSE, chem_temp)
|
||||
if(liquids && !liquids.liquid_group)
|
||||
qdel(liquids)
|
||||
return
|
||||
|
||||
if(!liquids)
|
||||
liquids = new(src)
|
||||
liquids.liquid_group.add_reagents(liquids, reagent_list, chem_temp)
|
||||
//Expose turf
|
||||
liquids.liquid_group.expose_members_turf(liquids)
|
||||
|
||||
/turf/proc/add_liquid(reagent, amount, no_react = FALSE, chem_temp = 300)
|
||||
if(reagent in GLOB.liquid_blacklist)
|
||||
return
|
||||
if(!liquids)
|
||||
liquids = new(src)
|
||||
|
||||
liquids.liquid_group.add_reagent(liquids, reagent, amount, chem_temp)
|
||||
//Expose turf
|
||||
liquids.liquid_group.expose_members_turf(liquids)
|
||||
75
yogstation/code/modules/liquids/tools.dm
Normal file
@@ -0,0 +1,75 @@
|
||||
/client/proc/spawn_liquid()
|
||||
set category = "Misc.Unused"
|
||||
set name = "Spawn Liquid"
|
||||
set desc = "Spawns an amount of chosen liquid at your current location."
|
||||
|
||||
var/choice
|
||||
var/valid_id
|
||||
while(!valid_id)
|
||||
choice = stripped_input(usr, "Enter the ID of the reagent you want to add.", "Search reagents")
|
||||
if(isnull(choice)) //Get me out of here!
|
||||
break
|
||||
if (!ispath(text2path(choice)))
|
||||
choice = pick_closest_path(choice, make_types_fancy(subtypesof(/datum/reagent)))
|
||||
if (ispath(choice))
|
||||
valid_id = TRUE
|
||||
else
|
||||
valid_id = TRUE
|
||||
if(!valid_id)
|
||||
to_chat(usr, span_warning("A reagent with that ID doesn't exist!"))
|
||||
if(!choice)
|
||||
return
|
||||
var/volume = input(usr, "Volume:", "Choose volume") as num
|
||||
if(!volume)
|
||||
return
|
||||
if(volume >= 100000)
|
||||
to_chat(usr, span_warning("Please limit the volume to below 100000 units!"))
|
||||
return
|
||||
var/turf/epicenter = get_turf(mob)
|
||||
epicenter.add_liquid(choice, volume, FALSE, 300)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] spawned liquid at [epicenter.loc] ([choice] - [volume]).")
|
||||
log_admin("[key_name(usr)] spawned liquid at [epicenter.loc] ([choice] - [volume]).")
|
||||
|
||||
/client/proc/remove_liquid()
|
||||
set name = "Remove Liquids"
|
||||
set category = "Misc.Unused"
|
||||
set desc = "Removes liquids in a specified radius."
|
||||
var/turf/epicenter = get_turf(mob)
|
||||
|
||||
var/range = input(usr, "Enter range:", "Range selection", 2) as num
|
||||
|
||||
for(var/obj/effect/abstract/liquid_turf/liquid in range(range, epicenter))
|
||||
if(QDELETED(liquid))
|
||||
continue
|
||||
if(!liquid)
|
||||
continue
|
||||
if(!liquid.liquid_group)
|
||||
continue
|
||||
liquid.liquid_group.remove_any(liquid, liquid.liquid_group.reagents_per_turf)
|
||||
qdel(liquid)
|
||||
|
||||
message_admins("[key_name_admin(usr)] removed liquids with range [range] in [epicenter.loc.name]")
|
||||
log_game("[key_name_admin(usr)] removed liquids with range [range] in [epicenter.loc.name]")
|
||||
|
||||
|
||||
|
||||
/client/proc/change_ocean()
|
||||
set category = "Admin.Fun"
|
||||
set name = "Change Ocean Liquid"
|
||||
set desc = "Changes the reagent of the ocean."
|
||||
|
||||
|
||||
var/choice = tgui_input_list(usr, "Choose a reagent", "Ocean Reagent", subtypesof(/datum/reagent))
|
||||
if(!choice)
|
||||
return
|
||||
var/datum/reagent/chosen_reagent = choice
|
||||
var/rebuilt = FALSE
|
||||
for(var/turf/open/floor/plating/ocean/listed_ocean as anything in SSliquids.ocean_turfs)
|
||||
if(!rebuilt)
|
||||
listed_ocean.ocean_reagents = list()
|
||||
listed_ocean.ocean_reagents[chosen_reagent] = 10
|
||||
listed_ocean.static_overlay.mix_colors(listed_ocean.ocean_reagents)
|
||||
for(var/area/ocean/ocean_types in GLOB.initalized_ocean_areas)
|
||||
ocean_types.base_lighting_color = listed_ocean.static_overlay.color
|
||||
ocean_types.update_base_lighting()
|
||||
rebuilt = TRUE
|
||||
BIN
yogstation/icons/obj/effects/liquid.dmi
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
yogstation/icons/obj/effects/liquid_overlays.dmi
Normal file
|
After Width: | Height: | Size: 803 B |
BIN
yogstation/icons/obj/effects/splash.dmi
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
yogstation/icons/obj/items/tiles.dmi
Normal file
|
After Width: | Height: | Size: 502 B |
BIN
yogstation/icons/obj/structures/drains.dmi
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
yogstation/icons/obj/structures/liquid_pump.dmi
Normal file
|
After Width: | Height: | Size: 929 B |
BIN
yogstation/icons/turf/floors/elevated_iron.dmi
Normal file
|
After Width: | Height: | Size: 417 B |
BIN
yogstation/icons/turf/floors/lowered_iron.dmi
Normal file
|
After Width: | Height: | Size: 352 B |
BIN
yogstation/icons/turf/floors/seafloor.dmi
Normal file
|
After Width: | Height: | Size: 2.5 KiB |