diff --git a/code/game/machinery/atmoalter/area_atmos_computer.dm b/code/game/machinery/atmoalter/area_atmos_computer.dm index 1c538eaf01c..81ce3e496bf 100644 --- a/code/game/machinery/atmoalter/area_atmos_computer.dm +++ b/code/game/machinery/atmoalter/area_atmos_computer.dm @@ -15,7 +15,10 @@ var/zone = "This computer is working on a wireless range, the range is currently limited to " /obj/machinery/computer/area_atmos/Initialize() - . = ..() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/computer/area_atmos/LateInitialize() scanscrubbers() /obj/machinery/computer/area_atmos/attack_ai(var/mob/user as mob) diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm index acf80965aef..3d53c9eea90 100644 --- a/code/game/objects/items/devices/communicator/communicator.dm +++ b/code/game/objects/items/devices/communicator/communicator.dm @@ -268,12 +268,15 @@ var/global/list/obj/item/communicator/all_communicators = list() // Parameters: None // Description: Gives ghosts an exonet address based on their key and ghost name. /mob/observer/dead/Initialize() - . = ..() + ..() + return INITIALIZE_HINT_LATELOAD + +/mob/observer/dead/LateInitialize() exonet = new(src) if(client) - exonet.make_address("communicator-[src.client]-[src.client.prefs.real_name]") + exonet.make_address("communicator-[client]-[client.prefs.real_name]") else - exonet.make_address("communicator-[key]-[src.real_name]") + exonet.make_address("communicator-[key]-[real_name]") // Proc: Destroy() // Parameters: None diff --git a/code/game/objects/structures/ghost_pods/ghost_pods_vr.dm b/code/game/objects/structures/ghost_pods/ghost_pods_vr.dm index 2a97db74738..03c84221264 100644 --- a/code/game/objects/structures/ghost_pods/ghost_pods_vr.dm +++ b/code/game/objects/structures/ghost_pods/ghost_pods_vr.dm @@ -55,4 +55,7 @@ /obj/structure/ghost_pod/ghost_activated/Initialize(var/mapload) . = ..() if(!mapload) - ghostpod_startup(spawn_active) + return INITIALIZE_HINT_LATELOAD + +/obj/structure/ghost_pod/LateInitialize() + ghostpod_startup(spawn_active) diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 35b92822b42..c226796cfdb 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -19,25 +19,34 @@ var/special_temperature //Used for turf HE-Pipe interaction var/climbable = FALSE //Adds proc to wall if set to TRUE on its initialization, defined here since not all walls are subtypes of wall - var/icon_edge = 'icons/turf/outdoors_edge.dmi' //VOREStation Addition - Allows for alternative edge icon files + var/icon_edge = 'icons/turf/outdoors_edge.dmi' //Allows for alternative edge icon files + var/wet_cleanup_timer // This is not great. /turf/simulated/proc/wet_floor(var/wet_val = 1) if(wet > 2) //Can't mop up ice return - spawn(0) - wet = wet_val - if(wet_overlay) - cut_overlay(wet_overlay) - wet_overlay = image('icons/effects/water.dmi', icon_state = "wet_floor") - add_overlay(wet_overlay) - sleep(800) - if(wet == 2) - sleep(3200) - wet = 0 - if(wet_overlay) - cut_overlay(wet_overlay) - wet_overlay = null + wet = wet_val + if(wet_overlay) + cut_overlay(wet_overlay) + wet_overlay = image('icons/effects/water.dmi', icon_state = "wet_floor") + add_overlay(wet_overlay) + if(wet_cleanup_timer) + deltimer(wet_cleanup_timer) + wet_cleanup_timer = null + if(wet == 2) + wet_cleanup_timer = addtimer(CALLBACK(src, PROC_REF(wet_floor_finish)), 160 SECONDS, TIMER_STOPPABLE) + else + wet_cleanup_timer = addtimer(CALLBACK(src, PROC_REF(wet_floor_finish)), 40 SECONDS, TIMER_STOPPABLE) + +/turf/simulated/proc/wet_floor_finish() + wet = 0 + if(wet_cleanup_timer) + deltimer(wet_cleanup_timer) + wet_cleanup_timer = null + if(wet_overlay) + cut_overlay(wet_overlay) + wet_overlay = null /turf/simulated/proc/freeze_floor() if(!wet) // Water is required for it to freeze. @@ -66,7 +75,7 @@ levelupdate() if(climbable) verbs += /turf/simulated/proc/climb_wall - if(is_outdoors()) //VOREStation edit - quick fix for a planetary lighting issue + if(is_outdoors()) SSplanets.addTurf(src) /turf/simulated/examine(mob/user) @@ -92,8 +101,9 @@ /turf/simulated/Entered(atom/A, atom/OL) if (isliving(A)) + var/dirtslip = FALSE var/mob/living/M = A - if(M.lying || M.flying) //VOREStation Edit + if(M.lying || M.flying || M.is_incorporeal()) return ..() if(M.dirties_floor()) @@ -102,13 +112,17 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M + dirtslip = H.species.dirtslip + if(H.species.mudking) + dirt = min(dirt+2, 101) + update_dirt() // Tracking blood var/list/bloodDNA = null var/bloodcolor="" if(H.shoes) var/obj/item/clothing/shoes/S = H.shoes if(istype(S)) - S.handle_movement(src,(H.m_intent == I_RUN ? 1 : 0)) + S.handle_movement(src,(H.m_intent == I_RUN ? 1 : 0), H) // handle_movement now needs to know who is moving, for inshoe steppies if(S.track_blood && S.blood_DNA) bloodDNA = S.blood_DNA bloodcolor=S.blood_color @@ -127,15 +141,21 @@ bloodDNA = null - if(src.wet) - + if(src.wet || (dirtslip && (dirt > 50 || outdoors == 1))) if(M.buckled || (src.wet == 1 && M.m_intent == I_WALK)) return var/slip_dist = 1 var/slip_stun = 6 var/floor_type = "wet" - + if(dirtslip) + slip_stun = 10 + if(dirt > 50) + floor_type = "dirty" + else if(outdoors) + floor_type = "uneven" + if(src.wet == 0 && M.m_intent == I_WALK) + return switch(src.wet) if(2) // Lube floor_type = "slippery" @@ -144,20 +164,32 @@ if(3) // Ice floor_type = "icy" slip_stun = 4 - slip_dist = 2 + slip_dist = rand(1,3) if(M.slip("the [floor_type] floor", slip_stun)) - for(var/i = 1 to slip_dist) - if(isbelly(M.loc)) //VOREEdit, Stop the slip if we're in a belly. Inspired by a chompedit, cleaned it up with isbelly instead of a variable since the var was resetting too fast. - return - step(M, M.dir) - sleep(1) + addtimer(CALLBACK(src, PROC_REF(handle_slipping), M, slip_dist, dirtslip), 0) else M.inertia_dir = 0 else M.inertia_dir = 0 ..() +/turf/simulated/proc/handle_slipping(var/mob/living/M, var/slip_dist, var/dirtslip) + PRIVATE_PROC(TRUE) + if(!M || !slip_dist) + return + if(isbelly(M.loc)) // Stop the slip if we're in a belly. + return + if(!step(M, M.dir) && !dirtslip) + return // done sliding, failed to move + // check tile for next slip + if(!dirtslip) + var/turf/simulated/ground = get_turf(M) + if(!istype(ground,/turf/simulated)) + return // stop sliding as it is impossible to be on wet terrain? + if(ground.wet != 2) + return // done sliding, not lubed + addtimer(CALLBACK(src, PROC_REF(handle_slipping), M, --slip_dist, dirtslip), 1) //returns 1 if made bloody, returns 0 otherwise /turf/simulated/add_blood(mob/living/carbon/human/M as mob) diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index eec0bede4bb..a13648fd9f1 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -109,6 +109,10 @@ /turf/simulated/floor/can_engrave() return (!flooring || flooring.can_engrave) +/turf/simulated/floor/proc/cause_slip(var/mob/living/M) + PROTECTED_PROC(TRUE) + return + /turf/simulated/floor/rcd_values(mob/living/user, obj/item/rcd/the_rcd, passed_mode) switch(passed_mode) if(RCD_FLOORWALL) diff --git a/code/game/turfs/simulated/outdoors/snow.dm b/code/game/turfs/simulated/outdoors/snow.dm index e6d9484429f..c1f499c50b7 100644 --- a/code/game/turfs/simulated/outdoors/snow.dm +++ b/code/game/turfs/simulated/outdoors/snow.dm @@ -4,10 +4,6 @@ edge_blending_priority = 6 movement_cost = 2 initial_flooring = /decl/flooring/snow - turf_layers = list( - /turf/simulated/floor/outdoors/rocks, - /turf/simulated/floor/outdoors/dirt - ) var/list/crossed_dirs = list() @@ -41,6 +37,8 @@ ..() /turf/simulated/floor/outdoors/snow/attack_hand(mob/user as mob) + if(!Adjacent(user)) + return visible_message("[user] starts scooping up some snow.", "You start scooping up some snow.") if(do_after(user, 1 SECOND)) var/obj/S = new /obj/item/stack/material/snow(user.loc) @@ -66,12 +64,15 @@ desc = "Dark rock that has been smoothened to be perfectly even. It's coated in a layer of slippey ice" /turf/simulated/floor/outdoors/ice/Entered(var/mob/living/M) - sleep(1 * world.tick_lag) if(isliving(M)) - if(M.stunned == 0) - to_chat(M, span_warning("You slide across the ice!")) - M.SetStunned(1) - step(M,M.dir) + if((M.weakened && prob(10)) || (M.m_intent == "walk" && prob(95))) + return ..() + addtimer(CALLBACK(src,TYPE_PROC_REF(/turf/simulated/floor/outdoors/ice,cause_slip),M), 1 * world.tick_lag, TIMER_DELETE_ME) +/turf/simulated/floor/outdoors/ice/cause_slip(var/mob/living/M) + if(M.weakened == 0) + to_chat(M, span_warning("You slide across the ice!")) + M.SetWeakened(3) + step(M,M.dir) // Ice that is used for, say, areas floating on water or similar. /turf/simulated/floor/outdoors/shelfice diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index e5a560a9134..b7ea704d841 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -7,7 +7,10 @@ return /turf/space/transit/Initialize() - . = ..() + ..() + return INITIALIZE_HINT_LATELOAD + +/turf/space/transit/LateInitialize() toggle_transit(reverse_dir[pushdirection]) //------------------------ @@ -28,4 +31,4 @@ icon_state = "arrow-west" pushdirection = WEST -//------------------------ \ No newline at end of file +//------------------------ diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index a474c4b24ff..356c48cde15 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -15,9 +15,13 @@ var/airlock_wire = null var/datum/wires/connected = null var/datum/radio_frequency/radio_connection + var/deadman = FALSE /obj/item/assembly/signaler/Initialize() - . = ..() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/item/assembly/signaler/LateInitialize() set_frequency(frequency) /obj/item/assembly/signaler/activate() diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 821dde398ed..fad68249051 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -32,8 +32,11 @@ /obj/effect/landmark/corpse/Initialize() ..() + return INITIALIZE_HINT_LATELOAD + +/obj/effect/landmark/corpse/LateInitialize() createCorpse() - return INITIALIZE_HINT_QDEL + qdel(src) /obj/effect/landmark/corpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it. var/mob/living/carbon/human/M = new /mob/living/carbon/human (src.loc) diff --git a/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm b/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm index 2e02cc4a02a..6fbcf5e0bd0 100644 --- a/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm +++ b/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm @@ -112,6 +112,8 @@ var/kin_type var/energy_light = 0.25 var/energy_dark = 0.75 + var/phase_gentle = TRUE + var/doing_phase = FALSE /datum/species/shadekin/New() ..() diff --git a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm index 1054e4fec76..1cda374a2ab 100644 --- a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm +++ b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm @@ -93,6 +93,7 @@ /mob/living/carbon/human/proc/phase_in(var/turf/T) if(ability_flags & AB_PHASE_SHIFTED) + // var/datum/species/shadekin/SK = species // pre-change forceMove(T) @@ -104,48 +105,77 @@ if(pulledby) pulledby.stop_pulling() stop_pulling() + canmove = FALSE // change - canmove = FALSE ability_flags &= ~AB_PHASE_SHIFTED ability_flags |= AB_PHASE_SHIFTING - mouse_opacity = 1 + throwpass = FALSE name = get_visible_name() for(var/obj/belly/B as anything in vore_organs) B.escapable = initial(B.escapable) - //cut_overlays() invisibility = initial(invisibility) see_invisible = initial(see_invisible) + see_invisible_default = initial(see_invisible_default) incorporeal_move = initial(incorporeal_move) density = initial(density) force_max_speed = initial(force_max_speed) + can_pull_size = initial(can_pull_size) + can_pull_mobs = initial(can_pull_mobs) + hovering = initial(hovering) update_icon() //Cosmetics mostly var/obj/effect/temp_visual/shadekin/phase_in/phaseanim = new /obj/effect/temp_visual/shadekin/phase_in(src.loc) + phaseanim.pixel_y = (src.size_multiplier - 1) * 16 // Pixel shift for the animation placement + phaseanim.adjust_scale(src.size_multiplier, src.size_multiplier) phaseanim.dir = dir alpha = 0 - custom_emote(1,"phases in!") - sleep(5) //The duration of the TP animation - canmove = original_canmove - alpha = initial(alpha) - remove_modifiers_of_type(/datum/modifier/shadekin_phase_vision) + addtimer(CALLBACK(src,PROC_REF(custom_emote), 1, "phases in!"), 0, TIMER_DELETE_ME) + addtimer(CALLBACK(src,PROC_REF(phase_in_finish_phase),T,original_canmove),5, TIMER_DELETE_ME) - //Potential phase-in vore - if(can_be_drop_pred) //Toggleable in vore panel - var/list/potentials = living_mobs(0) - if(potentials.len) - var/mob/living/target = pick(potentials) - if(istype(target) && target.devourable && target.can_be_drop_prey && vore_selected) - target.forceMove(vore_selected) - to_chat(target,span_vwarning("\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!")) +/mob/living/carbon/human/proc/phase_in_finish_phase(var/turf/T,var/original_canmove) + PRIVATE_PROC(TRUE) + SHOULD_NOT_OVERRIDE(TRUE) + var/datum/species/shadekin/SK = species - ability_flags &= ~AB_PHASE_SHIFTING + canmove = original_canmove + alpha = initial(alpha) + remove_modifiers_of_type(/datum/modifier/shadekin_phase_vision) + remove_modifiers_of_type(/datum/modifier/shadekin_phase) - //Affect nearby lights - var/destroy_lights = 0 + //Potential phase-in vore + if(can_be_drop_pred || can_be_drop_prey) //Toggleable in vore panel + var/list/potentials = living_mobs(0) + if(potentials.len) + var/mob/living/target = pick(potentials) + if(can_be_drop_pred && istype(target) && target.devourable && target.can_be_drop_prey && vore_selected) + target.forceMove(vore_selected) + to_chat(target, span_vwarning("\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!")) + to_chat(src, span_vwarning("You phase around [target], [vore_selected.vore_verb]ing them into your [vore_selected.name]!")) + else if(can_be_drop_prey && istype(target) && devourable && target.can_be_drop_pred && target.vore_selected) + forceMove(target.vore_selected) + to_chat(target, span_vwarning("\The [src] phases into you, [target.vore_selected.vore_verb]ing them into your [target.vore_selected.name]!")) + to_chat(src, span_vwarning("You phase into [target], having them [target.vore_selected.vore_verb] you into their [target.vore_selected.name]!")) + ability_flags &= ~AB_PHASE_SHIFTING + + //Affect nearby lights + var/destroy_lights = 0 + + if(SK.get_shadekin_eyecolor(src) == RED_EYES) + destroy_lights = 80 + else if(SK.get_shadekin_eyecolor(src) == PURPLE_EYES) + destroy_lights = 25 + + if(SK.phase_gentle) // gentle case: No light destruction. Flicker in 4 tile radius once. + for(var/obj/machinery/light/L in machines) + if(L.z != z || get_dist(src,L) > 4) + continue + L.flicker(1) + src.Stun(1) + else for(var/obj/machinery/light/L in machines) if(L.z != z || get_dist(src,L) > 10) continue @@ -170,23 +200,53 @@ stop_pulling() canmove = FALSE + var/list/allowed_implants = list( + /obj/item/implant/sizecontrol, + /obj/item/implant/compliance, + ) + for(var/obj/item/organ/external/organ in organs) + for(var/obj/item/O in organ.implants) + if(is_type_in_list(O, allowed_implants)) + continue + if(O == nif) + nif.unimplant(src) + O.forceMove(drop_location()) + organ.implants -= O + if(!has_embedded_objects()) + clear_alert("embeddedobject") + // change ability_flags |= AB_PHASE_SHIFTED ability_flags |= AB_PHASE_SHIFTING - mouse_opacity = 0 + throwpass = TRUE custom_emote(1,"phases out!") name = get_visible_name() + if(l_hand) + unEquip(l_hand) + if(r_hand) + unEquip(r_hand) + if(back) + unEquip(back) + + can_pull_size = 0 + can_pull_mobs = MOB_PULL_NONE + hovering = TRUE + for(var/obj/belly/B as anything in vore_organs) B.escapable = FALSE var/obj/effect/temp_visual/shadekin/phase_out/phaseanim = new /obj/effect/temp_visual/shadekin/phase_out(src.loc) + phaseanim.pixel_y = (src.size_multiplier - 1) * 16 // Pixel shift for the animation placement + phaseanim.adjust_scale(src.size_multiplier, src.size_multiplier) phaseanim.dir = dir alpha = 0 add_modifier(/datum/modifier/shadekin_phase_vision) + add_modifier(/datum/modifier/shadekin_phase) sleep(5) - invisibility = INVISIBILITY_LEVEL_TWO - see_invisible = INVISIBILITY_LEVEL_TWO + invisibility = INVISIBILITY_SHADEKIN + see_invisible = INVISIBILITY_SHADEKIN + see_invisible_default = INVISIBILITY_SHADEKIN //cut_overlays() update_icon() alpha = 127 @@ -197,6 +257,10 @@ force_max_speed = TRUE ability_flags &= ~AB_PHASE_SHIFTING +/datum/modifier/shadekin_phase + name = "Shadekin Phasing" + evasion = 100 + /datum/modifier/shadekin_phase_vision name = "Shadekin Phase Vision" vision_flags = SEE_THRU @@ -335,3 +399,45 @@ holder.glow_color = initial(holder.glow_color) holder.set_light(0) my_kin = null + +/mob/living/carbon/human/proc/attack_dephase(var/turf/T = null, atom/dephaser) + var/datum/species/shadekin/SK = species + + // no assigned dephase-target, just use our own + if(!T) + T = get_turf(src) + + // make sure it's possible to be dephased (and we're in phase) + if(!istype(SK) || SK.doing_phase || !T.CanPass(src,T) || loc != T || !(ability_flags & AB_PHASE_SHIFTED) ) + return FALSE + + + log_admin("[key_name_admin(src)] was stunned out of phase at [T.x],[T.y],[T.z] by [dephaser.name], last touched by [dephaser.fingerprintslast].") + message_admins("[key_name_admin(src)] was stunned out of phase at [T.x],[T.y],[T.z] by [dephaser.name], last touched by [dephaser.fingerprintslast]. (JMP)", 1) + // start the dephase + phase_in(T) + shadekin_adjust_energy(-20) // loss of energy for the interception + // apply a little extra stun for good measure + src.Weaken(3) + +//toggle proc for toggling gentle/normal phasing +/mob/living/carbon/human/proc/phase_strength_toggle() + set name = "Toggle Phase Strength" + set desc = "Toggle strength of phase. Gentle but slower, or faster but destructive to lights." + set category = "Abilities.Shadekin" + + var/datum/species/shadekin/SK = species + if(!istype(SK)) + to_chat(src, span_warning("Only a shadekin can use that!")) + return FALSE + + if(SK.phase_gentle) + to_chat(src, span_notice("Phasing toggled to Normal. You may damage lights.")) + SK.phase_gentle = 0 + else + to_chat(src, span_notice("Phasing toggled to Gentle. You won't damage lights, but concentrating on that incurs a short stun.")) + SK.phase_gentle = 1 + +/datum/modifier/shadekin_phase_vision + name = "Shadekin Phase Vision" + vision_flags = SEE_THRU diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index e8bcb5c029b..61102a0dd9e 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -209,6 +209,7 @@ var/has_glowing_eyes = 0 // Whether the eyes are shown above all lighting var/water_movement = 0 // How much faster or slower the species is in water var/snow_movement = 0 // How much faster or slower the species is on snow + var/dirtslip = FALSE // If we slip over dirt or not. var/can_space_freemove = FALSE // Can we freely move in space? var/can_zero_g_move = FALSE // What about just in zero-g non-space? @@ -227,6 +228,8 @@ var/vanity_base_fit //when shapeshifting using vanity_copy_to, this allows you to have add something so they can go back to their original species fit + var/mudking = FALSE // If we dirty up tiles quicker + var/vore_belly_default_variant = "H" // Determines the organs that the species spawns with and diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm index 6d3c5069380..b8d1ff7b4b9 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm @@ -194,3 +194,9 @@ var_changes = list("bad_swimmer" = 1, "water_movement" = 4, "swim_mult" = 1.25) varchange_type = TRAIT_VARCHANGE_LESS_BETTER excludes = list(/datum/trait/positive/good_swimmer) + +/datum/trait/negative/slipperydirt + name = "Dirt Vulnerability" + desc = "Even the tiniest particles of dirt give you uneasy footing, even through several layers of footwear." + cost = -5 + var_changes = list("dirtslip" = TRUE) diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm index ccc43426a87..47dfae93d1b 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm @@ -1216,3 +1216,10 @@ else input += "s" return input + +/datum/trait/neutral/mudking + name = "Mudking" + desc = "Somehow you are so filthy that tiles get dirty four times as quick from you walking on them." + cost = 0 + var_changes = list("mudking" = TRUE) + custom_only = FALSE diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm index 9a5925c6784..ba347c8b59a 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer.dm @@ -62,10 +62,13 @@ true_name = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]" - if(!roundstart && antag) - request_player() + . = ..() - return ..() + if(!roundstart && antag) + return INITIALIZE_HINT_LATELOAD + +/mob/living/simple_mob/animal/borer/LateInitialize() + request_player() /mob/living/simple_mob/animal/borer/handle_special() if(host && !stat && !host.stat) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm index 552060e3138..dbf0a8125a7 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm @@ -5,6 +5,11 @@ if(!T.CanPass(src,T) || loc != T) to_chat(src,span_warning("You can't use that here!")) return FALSE + /* + if((get_area(src).flags & PHASE_SHIELDED)) + to_chat(src,span_warning("This area is preventing you from phasing!")) + return FALSE + */ //RS Port #658 Start if(!client?.holder && A.flag_check(AREA_BLOCK_PHASE_SHIFT)) to_chat(src,span_warning("You can't use that here!")) @@ -35,6 +40,7 @@ // change ability_flags &= ~AB_PHASE_SHIFTED + throwpass = FALSE mouse_opacity = 1 name = real_name for(var/obj/belly/B as anything in vore_organs) @@ -50,38 +56,27 @@ //Cosmetics mostly flick("tp_in",src) - custom_emote(1,"phases in!") - sleep(5) //The duration of the TP animation - canmove = original_canmove + addtimer(CALLBACK(src,PROC_REF(custom_emote), 1, "phases in!"), 0, TIMER_DELETE_ME) + addtimer(CALLBACK(src,PROC_REF(phase_in_finish_phase),T,original_canmove),5, TIMER_DELETE_ME) - //Potential phase-in vore - if(can_be_drop_pred) //Toggleable in vore panel - var/list/potentials = living_mobs(0) - if(potentials.len) - var/mob/living/target = pick(potentials) - if(istype(target) && target.devourable && target.can_be_drop_prey && vore_selected) - target.forceMove(vore_selected) - to_chat(target,span_vwarning("\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!")) +/mob/living/simple_mob/shadekin/proc/phase_in_finish_phase(var/turf/T,var/original_canmove) + PRIVATE_PROC(TRUE) + SHOULD_NOT_OVERRIDE(TRUE) + canmove = original_canmove - // Do this after the potential vore, so we get the belly - update_icon() + //Potential phase-in vore + if(can_be_drop_pred) //Toggleable in vore panel + var/list/potentials = living_mobs(0) + if(potentials.len) + var/mob/living/target = pick(potentials) + if(istype(target) && target.devourable && target.can_be_drop_prey && vore_selected) + target.forceMove(vore_selected) + to_chat(target,span_vwarning("\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!")) - //Affect nearby lights - var/destroy_lights = 0 - if(eye_state == RED_EYES) - destroy_lights = 80 - if(eye_state == PURPLE_EYES) - destroy_lights = 25 + // Do this after the potential vore, so we get the belly + update_icon() - for(var/obj/machinery/light/L in machines) - if(L.z != z || get_dist(src,L) > 10) - continue - - if(prob(destroy_lights)) - spawn(rand(5,25)) - L.broken() - else - L.flicker(10) + handle_phasein_flicker() /mob/living/simple_mob/shadekin/proc/phase_out(var/turf/T) if(!(ability_flags & AB_PHASE_SHIFTED)) @@ -100,6 +95,7 @@ // change ability_flags |= AB_PHASE_SHIFTED + throwpass = TRUE // CHOMPAdd mouse_opacity = 0 custom_emote(1,"phases out!") real_name = name @@ -110,16 +106,20 @@ cut_overlays() flick("tp_out",src) - sleep(5) - invisibility = INVISIBILITY_LEVEL_TWO - see_invisible = INVISIBILITY_LEVEL_TWO - update_icon() - alpha = 127 + addtimer(CALLBACK(src, PROC_REF(phase_invis_handling), original_canmove), 5, TIMER_DELETE_ME) - canmove = original_canmove - incorporeal_move = TRUE - density = FALSE - force_max_speed = TRUE +/mob/living/simple_mob/shadekin/proc/phase_invis_handling(var/original_canmove) + PRIVATE_PROC(TRUE) + SHOULD_NOT_OVERRIDE(TRUE) + invisibility = INVISIBILITY_LEVEL_TWO + see_invisible = INVISIBILITY_LEVEL_TWO + update_icon() + alpha = 127 + + canmove = original_canmove + incorporeal_move = TRUE + density = FALSE + force_max_speed = TRUE /mob/living/simple_mob/shadekin/UnarmedAttack() if(ability_flags & AB_PHASE_SHIFTED) @@ -161,3 +161,74 @@ visible_message(span_notice("\The [src] gently places a hand on \the [target]...")) face_atom(target) return TRUE + + +/* +/mob/living/simple_mob/shadekin/proc/dark_tunneling() + var/template_id = "dark_portal" + var/datum/map_template/shelter/template + + if(!template) + template = SSmapping.shelter_templates[template_id] + if(!template) + throw EXCEPTION("Shelter template ([template_id]) not found!") + return FALSE + + var/turf/deploy_location = get_turf(src) + var/status = template.check_deploy(deploy_location) + + switch(status) + //Not allowed due to /area technical reasons + if(SHELTER_DEPLOY_BAD_AREA) + to_chat(src, span_warning("A tunnel to the Dark will not function in this area.")) + + //Anchored objects or no space + if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS) + var/width = template.width + var/height = template.height + to_chat(src, span_warning("There is not enough open area for a tunnel to the Dark to form! You need to clear a [width]x[height] area!")) + + if(status != SHELTER_DEPLOY_ALLOWED) + return FALSE + + var/turf/T = deploy_location + var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() + smoke.attach(T) + smoke.set_up(10, 0, T) + smoke.start() + + src.visible_message(span_notice("[src] begins pulling dark energies around themselves.")) + if(do_after(src, 600)) //60 seconds + playsound(src, 'sound/effects/phasein.ogg', 100, 1) + src.visible_message(span_notice("[src] finishes pulling dark energies around themselves, creating a portal.")) + + log_and_message_admins("[key_name_admin(src)] created a tunnel to the dark at [get_area(T)]!") + template.annihilate_plants(deploy_location) + template.load(deploy_location, centered = TRUE) + template.update_lighting(deploy_location) + ability_flags &= AB_DARK_TUNNEL + return TRUE + else + return FALSE +*/ + +/* +/mob/living/simple_mob/shadekin/proc/dark_maw() + var/turf/T = get_turf(src) + if(!istype(T)) + to_chat(src, span_warning("You don't seem to be able to set a trap here!")) + return FALSE + else if(T.get_lumcount() >= 0.5) + to_chat(src, span_warning("There is too much light here for your trap to last!")) + return FALSE + + if(do_after(src, 10)) + if(ability_flags & AB_PHASE_SHIFTED) + new /obj/effect/abstract/dark_maw(loc, src, 1) + else + new /obj/effect/abstract/dark_maw(loc, src) + + return TRUE + else + return FALSE +*/ diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm index e407d22070a..e517511e04b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm @@ -78,6 +78,7 @@ var/list/shadekin_abilities var/check_for_observer = FALSE var/check_timer = 0 + var/phase_gentle = 0 /mob/living/simple_mob/shadekin/Initialize() //You spawned the prototype, and want a totally random one. @@ -249,8 +250,7 @@ cut_overlays() icon_state = "" flick("tp_out",src) - spawn(1 SECOND) - qdel(src) //Back from whence you came! + QDEL_IN(src, 1 SECOND) . = ..(FALSE, deathmessage) @@ -474,3 +474,27 @@ say_maybe_target = list("...mar?") say_got_target = list("MAR!!!") //reactions = list("Mar?" = "Marrr!", "Mar!" = "Marrr???", "Mar." = "Marrr.") + +//custom light flicker proc +/mob/living/simple_mob/shadekin/proc/handle_phasein_flicker() + if(phase_gentle) // gentle case: No light destruction. Flicker in 4 tile radius for 3s. Weaken for 3sec after + for(var/obj/machinery/light/L in machines) + if(L.z != z || get_dist(src,L) > 4) + continue + L.flicker(3) + src.Stun(3) + else //normal case. Flicker in 10 tile radius for 10s. chance to destroy light based on eye type. + var/destroy_lights = 0 + if(eye_state == RED_EYES) + destroy_lights = 80 + if(eye_state == PURPLE_EYES) + destroy_lights = 25 + + for(var/obj/machinery/light/L in machines) + if(L.z != z || get_dist(src,L) > 10) + continue + + if(prob(destroy_lights)) + addtimer(CALLBACK(L, TYPE_PROC_REF(/obj/machinery/light, broken)), rand(5,25), TIMER_DELETE_ME) + else + L.flicker(10) diff --git a/code/modules/resleeving/designer.dm b/code/modules/resleeving/designer.dm index 5494cf797dd..e89a5f917a0 100644 --- a/code/modules/resleeving/designer.dm +++ b/code/modules/resleeving/designer.dm @@ -494,7 +494,7 @@ var/action = 0 action = to_use.OnTopic(list2params(href_list), href_list, user) - if((action & TOPIC_UPDATE_PREVIEW || action & TOPIC_REFRESH_UPDATE_PREVIEW || action & TOPIC_HANDLED || action & TOPIC_REFRESH) && mannequin && active_br) // Outpost 21 edit - Handled and Refreshes also count for check! + if((action & TOPIC_UPDATE_PREVIEW || action & TOPIC_REFRESH_UPDATE_PREVIEW || action & TOPIC_HANDLED || action & TOPIC_REFRESH) && mannequin && active_br) // Handled and Refreshes also count for check! switch(params["target_href"]) if("rename") active_br.mydna.name = P.real_name