/datum/component/wet_floor dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS can_transfer = TRUE var/highest_strength = TURF_DRY var/lube_flags = NONE //why do we have this? var/list/time_left_list //In deciseconds. var/static/mutable_appearance/permafrost_overlay = mutable_appearance('icons/effects/water.dmi', "ice_floor") var/static/mutable_appearance/ice_overlay = mutable_appearance('icons/turf/overlays.dmi', "snowfloor") var/static/mutable_appearance/water_overlay = mutable_appearance('icons/effects/water.dmi', "wet_floor_static") var/static/mutable_appearance/generic_turf_overlay = mutable_appearance('icons/effects/water.dmi', "wet_static") var/current_overlay var/permanent = FALSE var/last_process = 0 /// Should we display an overlay for this component? Useful mainly for turfs /// that already look wets or just don't need the visuals for any other reason. var/should_display_overlay = TRUE /datum/component/wet_floor/InheritComponent(datum/newcomp, orig, strength, duration_minimum, duration_add, duration_maximum, _permanent, _should_display_overlay) if(!newcomp) //We are getting passed the arguments of a would-be new component, but not a new component add_wet(arglist(args.Copy(3))) else //We are being passed in a full blown component var/datum/component/wet_floor/WF = newcomp //Lets make an assumption if(WF.gc()) //See if it's even valid, still. Also does LAZYLEN and stuff for us. CRASH("Wet floor component tried to inherit another, but the other was able to garbage collect while being inherited! What a waste of time!") for(var/i in WF.time_left_list) add_wet(text2num(i), WF.time_left_list[i]) /datum/component/wet_floor/Initialize(strength, duration_minimum, duration_add, duration_maximum, _permanent = FALSE, _should_display_overlay = TRUE) if(!isopenturf(parent)) return COMPONENT_INCOMPATIBLE should_display_overlay = _should_display_overlay add_wet(strength, duration_minimum, duration_add, duration_maximum, _permanent, _should_display_overlay) permanent = _permanent if(!permanent) START_PROCESSING(SSwet_floors, src) addtimer(CALLBACK(src, PROC_REF(gc), TRUE), 1) //GC after initialization. last_process = world.time /datum/component/wet_floor/RegisterWithParent() RegisterSignal(parent, COMSIG_TURF_IS_WET, PROC_REF(is_wet)) RegisterSignal(parent, COMSIG_TURF_MAKE_DRY, PROC_REF(dry)) /datum/component/wet_floor/UnregisterFromParent() UnregisterSignal(parent, list(COMSIG_TURF_IS_WET, COMSIG_TURF_MAKE_DRY)) /datum/component/wet_floor/Destroy() STOP_PROCESSING(SSwet_floors, src) var/turf/T = parent qdel(T.GetComponent(/datum/component/slippery)) if(istype(T)) //If this is false there is so many things wrong with it. T.cut_overlay(current_overlay) else stack_trace("Warning: Wet floor component wasn't on a turf when being destroyed! This is really bad!") return ..() /datum/component/wet_floor/proc/update_overlay() if(!should_display_overlay) if(!current_overlay) return var/turf/parent_turf = parent parent_turf.cut_overlay(current_overlay) current_overlay = null return var/intended if(!isfloorturf(parent)) intended = generic_turf_overlay else switch(highest_strength) if(TURF_WET_PERMAFROST) intended = permafrost_overlay if(TURF_WET_ICE) intended = ice_overlay else intended = water_overlay if(current_overlay != intended) var/turf/parent_turf = parent parent_turf.cut_overlay(current_overlay) parent_turf.add_overlay(intended) current_overlay = intended /datum/component/wet_floor/proc/AfterSlip(mob/living/slipped) if(highest_strength != TURF_WET_LUBE) return slipped.set_confusion_if_lower(8 SECONDS) /datum/component/wet_floor/proc/update_flags() var/intensity lube_flags = SLIPPERY_TURF switch(highest_strength) if(TURF_WET_WATER) intensity = 60 lube_flags |= NO_SLIP_WHEN_WALKING if(TURF_WET_LUBE) intensity = 80 lube_flags |= SLIDE | GALOSHES_DONT_HELP if(TURF_WET_ICE) intensity = 120 lube_flags |= SLIDE | GALOSHES_DONT_HELP if(TURF_WET_PERMAFROST) intensity = 120 lube_flags |= SLIDE_ICE | GALOSHES_DONT_HELP if(TURF_WET_SUPERLUBE) intensity = 120 lube_flags |= SLIDE | GALOSHES_DONT_HELP | SLIP_WHEN_CRAWLING else qdel(parent.GetComponent(/datum/component/slippery)) return parent.LoadComponent(/datum/component/slippery, intensity, lube_flags, CALLBACK(src, PROC_REF(AfterSlip))) /datum/component/wet_floor/proc/dry(datum/source, strength = TURF_WET_WATER, immediate = FALSE, duration_decrease = INFINITY) SIGNAL_HANDLER for(var/i in time_left_list) if(text2num(i) <= strength) time_left_list[i] = max(0, time_left_list[i] - duration_decrease) if(immediate) check() /datum/component/wet_floor/proc/max_time_left() . = 0 for(var/i in time_left_list) . = max(., time_left_list[i]) /datum/component/wet_floor/process() var/turf/open/T = parent var/diff = world.time - last_process var/decrease = 0 var/t = T.GetTemperature() switch(t) if(-INFINITY to T0C) add_wet(TURF_WET_ICE, max_time_left()) //Water freezes into ice! if(T0C to T0C + 100) decrease = ((T.air.return_temperature() - T0C) / SSwet_floors.temperature_coeff) * (diff / SSwet_floors.time_ratio) if(T0C + 100 to INFINITY) decrease = INFINITY decrease = max(0, decrease) if((is_wet() & TURF_WET_ICE) && t > T0C) //Ice melts into water! for(var/obj/O in T.contents) O.unfreeze() add_wet(TURF_WET_WATER, max_time_left()) dry(null, TURF_WET_ICE) dry(null, ALL, FALSE, decrease) check() last_process = world.time /datum/component/wet_floor/proc/update_strength() highest_strength = 0 //Not bitflag. for(var/i in time_left_list) highest_strength = max(highest_strength, text2num(i)) /datum/component/wet_floor/proc/is_wet() SIGNAL_HANDLER . = 0 for(var/i in time_left_list) . |= text2num(i) /datum/component/wet_floor/PreTransfer() var/turf/O = parent O.cut_overlay(current_overlay) //That turf is no longer slippery, we're out of here //Slippery components don't transfer due to callbacks qdel(O.GetComponent(/datum/component/slippery)) /datum/component/wet_floor/PostTransfer() if(!isopenturf(parent)) return COMPONENT_INCOMPATIBLE var/turf/T = parent T.add_overlay(current_overlay) //Make sure to add/update any slippery component on the new turf (update_flags calls LoadComponent) update_flags() //NB it's possible we get deleted after this, due to inherit /datum/component/wet_floor/proc/add_wet(type, duration_minimum = 0, duration_add = 0, duration_maximum = MAXIMUM_WET_TIME, _permanent = FALSE, _should_display_overlay = TRUE) var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST, TURF_WET_SUPERLUBE) if(duration_minimum <= 0 || !type) return FALSE if(type in allowed_types) return _do_add_wet(type, duration_minimum, duration_add, duration_maximum) else . = NONE for(var/i in allowed_types) if(!(type & i)) continue . |= _do_add_wet(i, duration_minimum, duration_add, duration_maximum) if(_permanent) permanent = TRUE STOP_PROCESSING(SSwet_floors, src) should_display_overlay = _should_display_overlay /datum/component/wet_floor/proc/_do_add_wet(type, duration_minimum, duration_add, duration_maximum) var/time = 0 if(LAZYACCESS(time_left_list, "[type]")) time = clamp(LAZYACCESS(time_left_list, "[type]") + duration_add, duration_minimum, duration_maximum) else time = min(duration_minimum, duration_maximum) LAZYSET(time_left_list, "[type]", time) check(TRUE) return TRUE /datum/component/wet_floor/proc/gc(on_init = FALSE) if(!LAZYLEN(time_left_list)) if(on_init) var/turf/T = parent stack_trace("Warning: Wet floor component gc'd right after initialization! What a waste of time and CPU! Type = [T? T.type : "ERROR - NO PARENT"], Location = [istype(T)? AREACOORD(T) : "ERROR - INVALID PARENT"].") qdel(src) return TRUE return FALSE /datum/component/wet_floor/proc/check(force_update = FALSE) var/changed = FALSE for(var/i in time_left_list) if(time_left_list[i] <= 0) time_left_list -= i changed = TRUE if(changed || force_update) update_strength() update_overlay() update_flags() gc()