diff --git a/code/_helpers/unsorted_vr.dm b/code/_helpers/unsorted_vr.dm index e9b5f86f0b..d7650deb8f 100644 --- a/code/_helpers/unsorted_vr.dm +++ b/code/_helpers/unsorted_vr.dm @@ -7,4 +7,35 @@ return var/atom/A for(A=O, A && !isturf(A.loc), A=A.loc); // semicolon is for the empty statement - return A \ No newline at end of file + return A + +/proc/get_safe_ventcrawl_target(var/obj/machinery/atmospherics/unary/vent_pump/start_vent) + if(!start_vent.network || !start_vent.network.normal_members.len) + return + var/list/vent_list = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/vent in start_vent.network.normal_members) + if(vent == start_vent) + continue + if(vent.welded) + continue + if(istype(get_area(vent), /area/crew_quarters/sleep)) //No going to dorms + continue + vent_list += vent + if(!vent_list.len) + return + return pick(vent_list) + +/proc/split_into_3(var/total) + if(!total || !isnum(total)) + return + + var/part1 = rand(0,total) + var/part2 = rand(0,total) + var/part3 = total-(part1+part2) + + if(part3<0) + part1 = total-part1 + part2 = total-part2 + part3 = -part3 + + return list(part1, part2, part3) \ No newline at end of file diff --git a/code/game/objects/effects/spider_vr.dm b/code/game/objects/effects/spider_vr.dm deleted file mode 100644 index d40f08aa9f..0000000000 --- a/code/game/objects/effects/spider_vr.dm +++ /dev/null @@ -1,13 +0,0 @@ -/obj/effect/spider/spiderling/grub - name = "grub larva" - desc = "It never stays still for long." - //M.icon = 'grub_vr.dmi' - icon_state = "spiderling" - -obj/effect/spider/spiderling/grub/process() - if(amount_grown >= 100) - var/spawn_type = /mob/living/simple_animal/retaliate/solargrub - new spawn_type(src.loc, src) - qdel(src) - else - ..() \ No newline at end of file diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 94c0a7999f..e9d25346f2 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -171,6 +171,13 @@ entry_vent = null else if(entry_vent) if(get_dist(src, entry_vent) <= 1) + //VOREStation Edit Start + var/obj/machinery/atmospherics/unary/vent_pump/exit_vent = get_safe_ventcrawl_target(entry_vent) + if(!exit_vent) + return + if(1) //To maintain indentation level + //VOREStation Edit End + /* //VOREStation Removal Start - prevent spiders in dorms if(entry_vent.network && entry_vent.network.normal_members.len) var/list/vents = list() for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in entry_vent.network.normal_members) @@ -179,6 +186,7 @@ entry_vent = null return var/obj/machinery/atmospherics/unary/vent_pump/exit_vent = pick(vents) + */ //VOREStation Removal End /*if(prob(50)) src.visible_message("[src] scrambles into the ventillation ducts!")*/ diff --git a/code/modules/events/grubinfestation_vr.dm b/code/modules/events/grubinfestation_vr.dm index a7898e11e6..6ef35901b0 100644 --- a/code/modules/events/grubinfestation_vr.dm +++ b/code/modules/events/grubinfestation_vr.dm @@ -14,13 +14,15 @@ /datum/event/grub_infestation/start() var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world) + for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines) + if(istype(get_area(temp_vent), /area/crew_quarters/sleep)) + continue if(!temp_vent.welded && temp_vent.network && temp_vent.loc.z in using_map.station_levels) if(temp_vent.network.normal_members.len > 50) vents += temp_vent while((spawncount >= 1) && vents.len) var/obj/vent = pick(vents) - new /obj/effect/spider/spiderling/grub(vent.loc) + new /mob/living/simple_animal/solargrub_larva(get_turf(vent)) vents -= vent spawncount-- diff --git a/code/modules/mob/living/simple_animal/vore/solargrub.dm b/code/modules/mob/living/simple_animal/vore/solargrub.dm index 69cd1d3abc..0d23c781f2 100644 --- a/code/modules/mob/living/simple_animal/vore/solargrub.dm +++ b/code/modules/mob/living/simple_animal/vore/solargrub.dm @@ -80,6 +80,10 @@ List of things solar grubs should be able to do: if(attached) if(prob(2)) src.visible_message("\The [src] begins to sink power from the net.") + if(prob(5)) + var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread() + sparks.set_up(5, 0, get_turf(src)) + sparks.start() anchored = 1 PN = attached.powernet PN.draw_power(150000) @@ -114,4 +118,11 @@ List of things solar grubs should be able to do: /mob/living/simple_animal/retaliate/solargrub/death() src.anchored = 0 + set_light(0) ..() + +/mob/living/simple_animal/retaliate/solargrub/handle_light() + . = ..() + if(. == 0 && !is_dead()) + set_light(2.5, 1, COLOR_YELLOW) + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/vore/solargrub_larva.dm b/code/modules/mob/living/simple_animal/vore/solargrub_larva.dm new file mode 100644 index 0000000000..b412be2a4b --- /dev/null +++ b/code/modules/mob/living/simple_animal/vore/solargrub_larva.dm @@ -0,0 +1,253 @@ +var/global/list/grub_machine_overlays = list() + +/mob/living/simple_animal/solargrub_larva + name = "solargrub larva" + desc = "A tiny wormy thing that can grow to massive sizes under the right conditions." + icon = 'icons/mob/vore.dmi' + icon_state = "grublarva" + icon_living = "grublarva" + icon_dead = "grublarva-dead" + + health = 5 + maxHealth = 5 + + faction = "grubs" + + response_help = "pats" + response_disarm = "nudges" + response_harm = "stomps on" + + mob_size = MOB_MINISCULE + pass_flags = PASSTABLE + can_pull_size = ITEMSIZE_TINY + can_pull_mobs = MOB_PULL_NONE + density = 0 + + stop_when_pulled = 0 + + var/static/list/ignored_machine_types = list( + /obj/machinery/atmospherics/unary/vent_pump, + /obj/machinery/atmospherics/unary/vent_scrubber, + /obj/machinery/door/firedoor + ) + + var/obj/machinery/atmospherics/unary/vent_pump/target_vent + + var/datum/effect/effect/system/spark_spread/sparks + var/image/machine_effect + + var/obj/machinery/abstract_grub_machine/powermachine + var/power_drained = 0 + var/forced_out = 0 + +/mob/living/simple_animal/solargrub_larva/New() + ..() + powermachine = new(src) + sparks = new(src) + sparks.set_up() + sparks.attach(src) + verbs += /mob/living/proc/ventcrawl + +/mob/living/simple_animal/solargrub_larva/death() + powermachine.draining = 0 + set_light(0) + return ..() + +/mob/living/simple_animal/solargrub_larva/Destroy() + qdel_null(powermachine) + qdel_null(sparks) + qdel_null(machine_effect) + target_vent = null + return ..() + +/mob/living/simple_animal/solargrub_larva/Life() + . = ..() + + if(machine_effect && !istype(loc, /obj/machinery)) + qdel_null(machine_effect) + + if(!. || ai_inactive) + return + + if(power_drained >= 7 MEGAWATTS && prob(5)) + expand_grub() + return + + if(istype(loc, /obj/machinery)) + if(machine_effect && air_master.current_cycle%30) + for(var/mob/M in player_list) + M << machine_effect + if(prob(10)) + sparks.start() + return + + if(stance == STANCE_IDLE) + if(forced_out) + forced_out = Clamp(0, forced_out--, forced_out) + return + + if(target_vent) + if(Adjacent(target_vent)) + spawn() + do_ventcrawl(target_vent) + target_vent = null + else + target_vent = null + stop_automated_movement = 0 + walk(src, 0) + return + + if(prob(20)) + var/list/possible_machines = list() + for(var/obj/machinery/M in orange(1,src)) + if(!Adjacent(M)) + continue + if(istype(M, /obj/machinery/power/apc) || istype(M, /obj/machinery/power/smes)) //APCs and SMES units don't actually use power, but it's too thematic to ignore them + possible_machines += M + continue + if(is_type_in_list(M, ignored_machine_types)) + continue + if(!M.idle_power_usage && !M.active_power_usage) //If it can't use power at all, ignore it + continue + possible_machines += M + if(possible_machines.len) + enter_machine(pick(possible_machines)) + return + + if(prob(10)) + var/list/vents = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/vent in view(7,src)) + if(vent.welded) + continue + vents += vent + if(vents.len) + var/picked = pick(vents) + target_vent = picked + WanderTowards(get_turf(picked)) + return + +/mob/living/simple_animal/solargrub_larva/proc/enter_machine(var/obj/machinery/M) + if(!istype(M)) + return + forceMove(M) + powermachine.draining = 2 + visible_message("\The [src] finds an opening and crawls inside \the [M].") + if(!(M.type in grub_machine_overlays)) + generate_machine_effect(M) + machine_effect = image(grub_machine_overlays[M.type], M) //Can't do this the reasonable way with an overlay, + for(var/mob/L in player_list) //because nearly every machine updates its icon by removing all overlays first + L << machine_effect + +/mob/living/simple_animal/solargrub_larva/proc/generate_machine_effect(var/obj/machinery/M) + var/icon/I = new /icon(M.icon, M.icon_state) + I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) + I.Blend(new /icon('icons/effects/alert.dmi', "_red"),ICON_MULTIPLY) + grub_machine_overlays[M.type] = I + +/mob/living/simple_animal/solargrub_larva/proc/eject_from_machine(var/obj/machinery/M) + if(!M) + if(istype(loc, /obj/machinery)) + M = loc + else + return + forceMove(get_turf(M)) + sparks.start() + if(machine_effect) + qdel_null(machine_effect) + forced_out += rand(5,15) + powermachine.draining = 1 + +/mob/living/simple_animal/solargrub_larva/proc/do_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent) + if(!vent) + return + var/obj/machinery/atmospherics/unary/vent_pump/end_vent = get_safe_ventcrawl_target(vent) + if(!end_vent) + return + forceMove(vent) + playsound(vent, 'sound/machines/ventcrawl.ogg', 50, 1, -3) + vent.visible_message("\The [src] wiggles into \the [vent]!") + var/redirect_attempts = 3 + while(redirect_attempts) + var/travel_time = round(get_dist(get_turf(src), get_turf(end_vent)) / 2) + sleep(travel_time) + if(end_vent.welded) + end_vent = get_safe_ventcrawl_target(vent) + if(!end_vent) + forceMove(get_turf(vent)) + return + redirect_attempts-- + continue + break + playsound(end_vent, 'sound/machines/ventcrawl.ogg', 50, 1, -3) + forceMove(get_turf(end_vent)) + +/mob/living/simple_animal/solargrub_larva/proc/expand_grub() + eject_from_machine() + visible_message("\The [src] suddenly balloons in size!") + new /mob/living/simple_animal/retaliate/solargrub(get_turf(src)) +// var/mob/living/simple_animal/retaliate/solargrub/grub = new(get_turf(src)) +// grub.power_drained = power_drained //TODO + qdel(src) + +/mob/living/simple_animal/solargrub_larva/handle_light() + . = ..() + if(. == 0 && !is_dead()) + set_light(1.5, 1, COLOR_YELLOW) + return 1 + + +/obj/machinery/abstract_grub_machine + var/total_active_power_usage = 45 KILOWATTS + var/list/active_power_usages = list(15 KILOWATTS, 15 KILOWATTS, 15 KILOWATTS) + var/total_idle_power_usage = 3 KILOWATTS + var/list/idle_power_usages = list(1 KILOWATTS, 1 KILOWATTS, 1 KILOWATTS) + var/draining = 1 + var/mob/living/simple_animal/solargrub_larva/grub + +/obj/machinery/abstract_grub_machine/New() + ..() + shuffle_power_usages() + grub = loc + if(!istype(grub)) + grub = null + qdel(src) + +/obj/machinery/abstract_grub_machine/Destroy() + grub = null + return ..() + +/obj/machinery/abstract_grub_machine/process() + if(!draining) + return + var/area/A = get_area(src) + if(!A) + return + var/list/power_list + switch(draining) + if(1) + power_list = idle_power_usages + if(2) + power_list = active_power_usages + for(var/i = 1 to power_list.len) + if(A.powered(i)) + use_power(power_list[i], i) + grub.power_drained += power_list[i] + if(prob(5)) + shuffle_power_usages() + +/obj/machinery/abstract_grub_machine/proc/shuffle_power_usages() + total_active_power_usage = rand(30 KILOWATTS, 60 KILOWATTS) + total_idle_power_usage = rand(1 KILOWATTS, 5 KILOWATTS) + active_power_usages = split_into_3(total_active_power_usage) + idle_power_usages = split_into_3(total_idle_power_usage) + + +/obj/item/device/multitool/afterattack(obj/O, mob/user, proximity) + if(proximity) + if(istype(O, /obj/machinery)) + var/mob/living/simple_animal/solargrub_larva/grub = locate() in O + if(grub) + grub.eject_from_machine(O) + to_chat(user, "You disturb a grub nesting in \the [O]!") + return + return ..() \ No newline at end of file diff --git a/icons/mob/vore.dmi b/icons/mob/vore.dmi index e34a68f2e8..0a6958c1b7 100644 Binary files a/icons/mob/vore.dmi and b/icons/mob/vore.dmi differ diff --git a/vorestation.dme b/vorestation.dme index 8ecbda2e26..d38356c3e6 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -811,7 +811,6 @@ #include "code\game\objects\effects\misc.dm" #include "code\game\objects\effects\overlays.dm" #include "code\game\objects\effects\portals.dm" -#include "code\game\objects\effects\spider_vr.dm" #include "code\game\objects\effects\spiders.dm" #include "code\game\objects\effects\step_triggers.dm" #include "code\game\objects\effects\zone_divider.dm" @@ -2027,6 +2026,7 @@ #include "code\modules\mob\living\simple_animal\vore\panther.dm" #include "code\modules\mob\living\simple_animal\vore\snake.dm" #include "code\modules\mob\living\simple_animal\vore\solargrub.dm" +#include "code\modules\mob\living\simple_animal\vore\solargrub_larva.dm" #include "code\modules\mob\living\simple_animal\vore\wah.dm" #include "code\modules\mob\living\simple_animal\vore\wolf.dm" #include "code\modules\mob\living\simple_animal\vore\zz_vore_overrides.dm"