diff --git a/code/modules/events/abductor.dm b/code/modules/events/abductor.dm index ecf3f6047ef..f562e7b7954 100755 --- a/code/modules/events/abductor.dm +++ b/code/modules/events/abductor.dm @@ -1,7 +1,7 @@ /datum/round_event_control/abductor name = "Abductors" typepath = /datum/round_event/ghost_role/abductor - weight = 10 + weight = 0 //SKYRAT EDIT CHANGE max_occurrences = 1 min_players = 20 dynamic_should_hijack = TRUE diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index 9f194da7cee..e9c6691d853 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -3,7 +3,7 @@ typepath = /datum/round_event/ghost_role/alien_infestation //SKYRAT EDIT CHANGE BEGIN //weight = 5 - SKYRAT EDIT - ORIGINAL - weight = 2 + weight = 0 //SKYRAT EDIT CHANGE END min_players = 10 diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm index 0b642301460..929ff0ee606 100644 --- a/code/modules/events/blob.dm +++ b/code/modules/events/blob.dm @@ -2,10 +2,9 @@ name = "Blob" typepath = /datum/round_event/ghost_role/blob weight = 10 - max_occurrences = 1 + max_occurrences = 0 //SKYRAT EDIT CHANGE - // min_players = 20 // SKYRAT EDIT -- Original - min_players = 60 // SKYRAT EDIT CHANGE -- Requires 60 alive non-afk players for blob + min_players = 20 dynamic_should_hijack = TRUE diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm index 3abfa123fb5..880560e7bc0 100644 --- a/code/modules/events/pirates.dm +++ b/code/modules/events/pirates.dm @@ -1,8 +1,7 @@ /datum/round_event_control/pirates name = "Space Pirates" typepath = /datum/round_event/pirates - //weight = 8 //ORIGINAL - weight = 2 //SKYRAT EDIT CHANGE - EVENTS + weight = 8 max_occurrences = 1 min_players = 10 earliest_start = 30 MINUTES diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 1eacb5c7bcd..b1f88c983ad 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -1,8 +1,8 @@ +/* SKYRAT EDIT REMOVAL - MOVED TO MODULAR /datum/round_event_control/spacevine name = "Spacevine" typepath = /datum/round_event/spacevine - //weight = 15 //ORIGINAL - weight = 8 //SKYRAT EDIT CHANGE + weight = 15 max_occurrences = 3 min_players = 10 @@ -592,3 +592,4 @@ if(("vines" in M.faction) || ("plants" in M.faction)) return TRUE return FALSE +*/ diff --git a/code/modules/events/swarmer.dm b/code/modules/events/swarmer.dm index 2599cc92d79..7e597a9747e 100644 --- a/code/modules/events/swarmer.dm +++ b/code/modules/events/swarmer.dm @@ -2,7 +2,7 @@ name = "Spawn Swarmer Beacon" typepath = /datum/round_event/spawn_swarmer //weight = 10 //ORIGINAL - weight = 3 //SKYRAT EDIT CHANGE - EVENTS - same as the dynamic ruleset + weight = 0 //SKYRAT EDIT CHANGE - EVENTS - same as the dynamic ruleset max_occurrences = 1 //Only once okay fam min_players = 20 dynamic_should_hijack = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 93560e2e331..a6f177495cd 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -20,7 +20,7 @@ canSmoothWith = null smoothing_flags = NONE /// The amount of time it takes to create a venus human trap. - var/growth_time = 120 SECONDS + var/growth_time = 1 MINUTES //SKYRAT EDIT CHANGE var/growth_icon = 0 /// Used by countdown to check time, this is when the timer will complete and the venus trap will spawn. @@ -100,15 +100,16 @@ health_doll_icon = "venus_human_trap" mob_biotypes = MOB_ORGANIC | MOB_PLANT layer = SPACEVINE_MOB_LAYER - health = 50 - maxHealth = 50 + health = 40 //SKYRAT EDIT CHANGE + maxHealth = 40 //SKYRAT EDIT CHANGE ranged = TRUE harm_intent_damage = 5 obj_damage = 60 - melee_damage_lower = 25 - melee_damage_upper = 25 + melee_damage_lower = 20 //SKYRAT EDIT CHANGE - Original: 25 + melee_damage_upper = 20 //SKYRAT EDIT CHANGE - Original: 25 combat_mode = TRUE - del_on_death = TRUE + //del_on_death = TRUE //SKYRAT EDIT REMOVAL + flip_on_death = TRUE deathmessage = "collapses into bits of plant matter." attacked_sound = 'sound/creatures/venus_trap_hurt.ogg' deathsound = 'sound/creatures/venus_trap_death.ogg' @@ -130,6 +131,7 @@ /// Whether or not this plant is ghost possessable var/playable_plant = TRUE + /mob/living/simple_animal/hostile/venus_human_trap/Life(delta_time = SSMOBS_DT, times_fired) . = ..() pull_vines() @@ -224,3 +226,10 @@ */ /mob/living/simple_animal/hostile/venus_human_trap/proc/remove_vine(datum/beam/vine) vines -= vine + +//SKYRAT EDIT ADDITION +/mob/living/simple_animal/hostile/venus_human_trap/death(gibbed) + for(var/i in vines) + qdel(i) + return ..() +//SKYRAT EDIT END diff --git a/modular_skyrat/master_files/code/modules/events/spacevine.dm b/modular_skyrat/master_files/code/modules/events/spacevine.dm new file mode 100644 index 00000000000..23822cb1d8e --- /dev/null +++ b/modular_skyrat/master_files/code/modules/events/spacevine.dm @@ -0,0 +1,776 @@ +/datum/round_event_control/spacevine + name = "Spacevine" + typepath = /datum/round_event/spacevine + weight = 10 + max_occurrences = 3 + min_players = 10 + +/datum/round_event/spacevine + fakeable = FALSE + +/datum/round_event/spacevine/start() + var/list/turfs = list() //list of all the empty floor turfs in the hallway areas + + var/obj/structure/spacevine/SV = new() + + for(var/area/maintenance/A in world) + for(var/turf/F in A) + if(F.Enter(SV)) + turfs += F + + qdel(SV) + + if(turfs.len) //Pick a turf to spawn at if we can + var/turf/T = pick(turfs) + new /datum/spacevine_controller(T, list(pick(subtypesof(/datum/spacevine_mutation))), rand(10,100), rand(1,6), src) //spawn a controller at turf with randomized stats and a single random mutation + new /mob/living/simple_animal/hostile/venus_human_trap(T) + new /mob/living/simple_animal/hostile/venus_human_trap(T) + +/datum/spacevine_mutation + var/name = "" + var/severity = 1 + var/hue + var/quality + +/datum/spacevine_mutation/proc/add_mutation_to_vinepiece(obj/structure/spacevine/holder) + holder.mutations |= src + holder.add_atom_colour(hue, FIXED_COLOUR_PRIORITY) + +/datum/spacevine_mutation/proc/process_mutation(obj/structure/spacevine/holder) + return + +/datum/spacevine_mutation/proc/process_temperature(obj/structure/spacevine/holder, temp, volume) + return + +/datum/spacevine_mutation/proc/on_birth(obj/structure/spacevine/holder) + return + +/datum/spacevine_mutation/proc/on_grow(obj/structure/spacevine/holder) + return + +/datum/spacevine_mutation/proc/on_death(obj/structure/spacevine/holder) + return + +/datum/spacevine_mutation/proc/on_hit(obj/structure/spacevine/holder, mob/hitter, obj/item/I, expected_damage) + . = expected_damage + +/datum/spacevine_mutation/proc/on_cross(obj/structure/spacevine/holder, mob/crosser) + return + +/datum/spacevine_mutation/proc/on_chem(obj/structure/spacevine/holder, datum/reagent/R) + return + +/datum/spacevine_mutation/proc/on_eat(obj/structure/spacevine/holder, mob/living/eater) + return + +/datum/spacevine_mutation/proc/on_spread(obj/structure/spacevine/holder, turf/target) + return + +/datum/spacevine_mutation/proc/on_buckle(obj/structure/spacevine/holder, mob/living/buckled) + return + +/datum/spacevine_mutation/proc/on_explosion(severity, target, obj/structure/spacevine/holder) + return + +/datum/spacevine_mutation/aggressive_spread/proc/aggrospread_act(obj/structure/spacevine/S, mob/living/M) + return + +/datum/spacevine_mutation/light + name = "light" + hue = "#ffff00" + quality = POSITIVE + severity = 4 + +/datum/spacevine_mutation/light/on_grow(obj/structure/spacevine/holder) + if(holder.energy) + holder.set_light(severity, 0.3) + +/datum/spacevine_mutation/toxicity + name = "toxic" + hue = "#ff00ff" + severity = 10 + quality = NEGATIVE + +/datum/spacevine_mutation/toxicity/on_cross(obj/structure/spacevine/holder, mob/living/crosser) + if(issilicon(crosser)) + return + if(prob(severity) && istype(crosser) && !isvineimmune(crosser)) + to_chat(crosser, "You accidentally touch the vine and feel a strange sensation.") + crosser.adjustToxLoss(5) + +/datum/spacevine_mutation/toxicity/on_eat(obj/structure/spacevine/holder, mob/living/eater) + if(!isvineimmune(eater)) + eater.adjustToxLoss(5) + +/datum/spacevine_mutation/explosive //OH SHIT IT CAN CHAINREACT RUN!!! + name = "explosive" + hue = "#ff0000" + quality = NEGATIVE + severity = 2 + +/datum/spacevine_mutation/explosive/on_explosion(explosion_severity, target, obj/structure/spacevine/holder) + if(explosion_severity < 3) + qdel(holder) + else + . = 1 + QDEL_IN(holder, 5) + +/datum/spacevine_mutation/explosive/on_death(obj/structure/spacevine/holder, mob/hitter, obj/item/I) + explosion(holder, light_impact_range = severity, adminlog = FALSE) + +/datum/spacevine_mutation/fire_proof + name = "fire proof" + hue = "#ff8888" + quality = MINOR_NEGATIVE + +/datum/spacevine_mutation/fire_proof/process_temperature(obj/structure/spacevine/holder, temp, volume) + return 1 + +/datum/spacevine_mutation/fire_proof/on_hit(obj/structure/spacevine/holder, mob/hitter, obj/item/I, expected_damage) + if(I && I.damtype == BURN) + . = 0 + else + . = expected_damage + +/datum/spacevine_mutation/vine_eating + name = "vine eating" + hue = "#ff7700" + quality = MINOR_NEGATIVE + +/// Destroys any vine on spread-target's tile. The checks for if this should be done are in the spread() proc. +/datum/spacevine_mutation/vine_eating/on_spread(obj/structure/spacevine/holder, turf/target) + for(var/obj/structure/spacevine/prey in target) + qdel(prey) + +/datum/spacevine_mutation/aggressive_spread //very OP, but im out of other ideas currently + name = "aggressive spreading" + hue = "#333333" + severity = 3 + quality = NEGATIVE + +/// Checks mobs on spread-target's turf to see if they should be hit by a damaging proc or not. +/datum/spacevine_mutation/aggressive_spread/on_spread(obj/structure/spacevine/holder, turf/target, mob/living) + for(var/mob/living/M in target) + if(!isvineimmune(M) && M.stat != DEAD) // Don't kill immune creatures. Dead check to prevent log spam when a corpse is trapped between vine eaters. + aggrospread_act(holder, M) + +/// What happens if an aggr spreading vine buckles a mob. +/datum/spacevine_mutation/aggressive_spread/on_buckle(obj/structure/spacevine/holder, mob/living/buckled) + aggrospread_act(holder, buckled) + +/// Hurts mobs. To be used when a vine with aggressive spread mutation spreads into the mob's tile or buckles them. +/datum/spacevine_mutation/aggressive_spread/aggrospread_act(obj/structure/spacevine/S, mob/living/M) + var/mob/living/carbon/C = M //If the mob is carbon then it now also exists as a "C", and not just an M. + if(istype(C)) //If the mob (M) is a carbon subtype (C) we move on to pick a more complex damage proc, with damage zones, wounds and armor mitigation. + var/obj/item/bodypart/limb = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG, BODY_ZONE_HEAD, BODY_ZONE_CHEST) //Picks a random bodypart. Does not runtime even if it's missing. + var/armor = C.run_armor_check(limb, MELEE, null, null) //armor = the armor value of that randomly chosen bodypart. Nulls to not print a message, because it would still print on pierce. + var/datum/spacevine_mutation/thorns/T = locate() in S.mutations //Searches for the thorns mutation in the "mutations"-list inside obj/structure/spacevine, and defines T if it finds it. + if(T && (prob(40))) //If we found the thorns mutation there is now a chance to get stung instead of lashed or smashed. + C.apply_damage(50, BRUTE, def_zone = limb, wound_bonus = rand(-20,10), sharpness = SHARP_POINTY) //This one gets a bit lower damage because it ignores armor. + C.Stun(1 SECONDS) //Stopped in place for a moment. + playsound(M, 'sound/weapons/pierce.ogg', 50, TRUE, -1) + M.visible_message("[M] is nailed by a sharp thorn!", \ + "You are nailed by a sharp thorn!") + log_combat(S, M, "aggressively pierced") //"Aggressively" for easy ctrl+F'ing in the attack logs. + else + if(prob(80)) + C.apply_damage(60, BRUTE, def_zone = limb, blocked = armor, wound_bonus = rand(-20,10), sharpness = SHARP_EDGED) + C.Knockdown(2 SECONDS) + playsound(M, 'sound/weapons/whip.ogg', 50, TRUE, -1) + M.visible_message("[M] is lacerated by an outburst of vines!", \ + "You are lacerated by an outburst of vines!") + log_combat(S, M, "aggressively lacerated") + else + C.apply_damage(60, BRUTE, def_zone = limb, blocked = armor, wound_bonus = rand(-20,10), sharpness = NONE) + C.Knockdown(3 SECONDS) + var/atom/throw_target = get_edge_target_turf(C, get_dir(S, get_step_away(C, S))) + C.throw_at(throw_target, 3, 6) + playsound(M, 'sound/effects/hit_kick.ogg', 50, TRUE, -1) + M.visible_message("[M] is smashed by a large vine!", \ + "You are smashed by a large vine!") + log_combat(S, M, "aggressively smashed") + else //Living but not a carbon? Maybe a silicon? Can't be wounded so have a big chunk of simple bruteloss with no special effects. They can be entangled. + M.adjustBruteLoss(75) + playsound(M, 'sound/weapons/whip.ogg', 50, TRUE, -1) + M.visible_message("[M] is brutally threshed by [S]!", \ + "You are brutally threshed by [S]!") + log_combat(S, M, "aggressively spread into") //You aren't being attacked by the vines. You just happen to stand in their way. + +/datum/spacevine_mutation/transparency + name = "transparent" + hue = "" + quality = POSITIVE + +/datum/spacevine_mutation/transparency/on_grow(obj/structure/spacevine/holder) + holder.set_opacity(0) + holder.alpha = 125 + +/datum/spacevine_mutation/oxy_eater + name = "oxygen consuming" + hue = "#ffff88" + severity = 3 + quality = NEGATIVE + +/datum/spacevine_mutation/oxy_eater/process_mutation(obj/structure/spacevine/holder) + var/turf/open/floor/T = holder.loc + if(istype(T)) + var/datum/gas_mixture/GM = T.air + if(!GM.gases[/datum/gas/oxygen]) + return + GM.gases[/datum/gas/oxygen][MOLES] = max(GM.gases[/datum/gas/oxygen][MOLES] - severity * holder.energy, 0) + GM.garbage_collect() + +/datum/spacevine_mutation/nitro_eater + name = "nitrogen consuming" + hue = "#8888ff" + severity = 3 + quality = NEGATIVE + +/datum/spacevine_mutation/nitro_eater/process_mutation(obj/structure/spacevine/holder) + var/turf/open/floor/T = holder.loc + if(istype(T)) + var/datum/gas_mixture/GM = T.air + if(!GM.gases[/datum/gas/nitrogen]) + return + GM.gases[/datum/gas/nitrogen][MOLES] = max(GM.gases[/datum/gas/nitrogen][MOLES] - severity * holder.energy, 0) + GM.garbage_collect() + +/datum/spacevine_mutation/carbondioxide_eater + name = "CO2 consuming" + hue = "#00ffff" + severity = 3 + quality = POSITIVE + +/datum/spacevine_mutation/carbondioxide_eater/process_mutation(obj/structure/spacevine/holder) + var/turf/open/floor/T = holder.loc + if(istype(T)) + var/datum/gas_mixture/GM = T.air + if(!GM.gases[/datum/gas/carbon_dioxide]) + return + GM.gases[/datum/gas/carbon_dioxide][MOLES] = max(GM.gases[/datum/gas/carbon_dioxide][MOLES] - severity * holder.energy, 0) + GM.garbage_collect() + +/datum/spacevine_mutation/plasma_eater + name = "toxins consuming" + hue = "#ffbbff" + severity = 3 + quality = POSITIVE + +/datum/spacevine_mutation/plasma_eater/process_mutation(obj/structure/spacevine/holder) + var/turf/open/floor/T = holder.loc + if(istype(T)) + var/datum/gas_mixture/GM = T.air + if(!GM.gases[/datum/gas/plasma]) + return + GM.gases[/datum/gas/plasma][MOLES] = max(GM.gases[/datum/gas/plasma][MOLES] - severity * holder.energy, 0) + GM.garbage_collect() + +/datum/spacevine_mutation/thorns + name = "thorny" + hue = "#666666" + severity = 10 + quality = NEGATIVE + +/datum/spacevine_mutation/thorns/on_cross(obj/structure/spacevine/holder, mob/living/crosser) + if(prob(severity) && istype(crosser) && !isvineimmune(crosser)) + var/mob/living/M = crosser + M.adjustBruteLoss(5) + to_chat(M, "You cut yourself on the thorny vines.") + +/datum/spacevine_mutation/thorns/on_hit(obj/structure/spacevine/holder, mob/living/hitter, obj/item/I, expected_damage) + if(prob(severity) && istype(hitter) && !isvineimmune(hitter)) + var/mob/living/M = hitter + M.adjustBruteLoss(5) + to_chat(M, "You cut yourself on the thorny vines.") + . = expected_damage + +/datum/spacevine_mutation/woodening + name = "hardened" + hue = "#997700" + quality = NEGATIVE + +/datum/spacevine_mutation/woodening/on_grow(obj/structure/spacevine/holder) + if(holder.energy) + holder.density = TRUE + holder.max_integrity = 100 + holder.obj_integrity = holder.max_integrity + +/datum/spacevine_mutation/woodening/on_hit(obj/structure/spacevine/holder, mob/living/hitter, obj/item/I, expected_damage) + if(I?.get_sharpness()) + . = expected_damage * 0.5 + else + . = expected_damage + +/datum/spacevine_mutation/flowering + name = "flowering" + hue = "#0A480D" + quality = NEGATIVE + severity = 10 + +/datum/spacevine_mutation/flowering/on_grow(obj/structure/spacevine/holder) + if(holder.energy == 2 && prob(severity) && !locate(/obj/structure/alien/resin/flower_bud) in range(5,holder)) + new/obj/structure/alien/resin/flower_bud(get_turf(holder)) + +/datum/spacevine_mutation/flowering/on_cross(obj/structure/spacevine/holder, mob/living/crosser) + if(prob(25)) + holder.entangle(crosser) + +/datum/spacevine_mutation/slipping + name = "slipping" + hue = "#97eaff" + severity = 1 + quality = NEGATIVE + +/datum/spacevine_mutation/slipping/on_cross(obj/structure/spacevine/holder, mob/living/crosser) + if(issilicon(crosser)) + return + if(ishuman(crosser)) + var/mob/living/carbon/human/H = crosser + H.slip(20) + to_chat(H, "The vines slip you!") + +/datum/spacevine_mutation/teleporting + name = "teleporting" + hue = "#1105b6" + severity = 3 + quality = NEGATIVE + +/datum/spacevine_mutation/teleporting/on_hit(obj/structure/spacevine/holder, mob/hitter, obj/item/I, expected_damage) + if(isliving(hitter)) + var/mob/living/M = hitter + if(isvineimmune(M)) + return + if(prob(25)) + do_teleport(M, get_turf(M), 8, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) + . = expected_damage + +/datum/spacevine_mutation/meleereflecting + name = "melee reflecting" + hue = "#b6054f" + severity = 2 + quality = NEGATIVE + +/datum/spacevine_mutation/meleereflecting/on_hit(obj/structure/spacevine/holder, mob/hitter, obj/item/I, expected_damage) + if(isliving(hitter)) + var/mob/living/M = hitter + if(isvineimmune(M)) + return + if(prob(10)) + M.adjustBruteLoss(expected_damage) + else + . = expected_damage + +/mob/living/proc/plant_kudzu() + var/turf/T = get_turf(src) + var/list/added_mut_list = list() + new /datum/spacevine_controller(T, added_mut_list, 50, 5) + new /mob/living/simple_animal/hostile/venus_human_trap(T) + +/datum/spacevine_mutation/seeding + name = "seeding" + hue = "#68b95d" + severity = 3 + quality = NEGATIVE + +/datum/spacevine_mutation/seeding/on_cross(obj/structure/spacevine/holder, mob/crosser) + if(isliving(crosser)) + var/mob/living/M = crosser + if(isvineimmune(M) || M.stat == DEAD) + return + if(prob(10)) + addtimer(CALLBACK(M, /mob/living/proc/plant_kudzu), 1 MINUTES) + +/datum/spacevine_mutation/seeding/on_hit(obj/structure/spacevine/holder, mob/hitter, obj/item/I, expected_damage) + if(isliving(hitter)) + var/mob/living/M = hitter + if(isvineimmune(M)) + return + if(prob(10)) + addtimer(CALLBACK(M, /mob/living/proc/plant_kudzu), 1 MINUTES) + . = expected_damage + +/datum/spacevine_mutation/electrify + name = "electrified" + hue = "#f7eb86" + severity = 3 + quality = NEGATIVE + +/datum/spacevine_mutation/electrify/on_hit(obj/structure/spacevine/holder, mob/hitter, obj/item/I, expected_damage) + if(isliving(hitter)) + var/mob/living/M = hitter + if(isvineimmune(M)) + return + if(prob(20)) + M.electrocute_act(10, holder) + . = expected_damage + +/datum/spacevine_mutation/emp + name = "emp" + hue = "#ffffff" + severity = 3 + quality = NEGATIVE + +/datum/spacevine_mutation/emp/on_death(obj/structure/spacevine/holder) + empulse(holder, 1, 2) + +/datum/spacevine_mutation/randreagent + name = "reagent injecting" + hue = "#003cff" + severity = 3 + quality = NEGATIVE + +/datum/spacevine_mutation/randreagent/on_cross(obj/structure/spacevine/holder, mob/crosser) + if(isliving(crosser)) + var/mob/living/M = crosser + if(isvineimmune(M)) + return + if(prob(10)) + var/choose_reagent = pick(subtypesof(/datum/reagent)) + M.reagents.add_reagent(choose_reagent, 10) + +/datum/spacevine_mutation/radiation + name = "radiation pulsing" + hue = "#ffef62" + severity = 3 + quality = NEGATIVE + +/datum/spacevine_mutation/radiation/on_grow(obj/structure/spacevine/holder) + radiation_pulse(holder, 100, 3) + +/datum/spacevine_mutation/miasmagenerating + name = "miasma" + hue = "#470566" + severity = 5 + quality = NEGATIVE + +/datum/spacevine_mutation/miasmagenerating/on_grow(obj/structure/spacevine/holder) + var/turf/holder_turf = get_turf(holder) + holder_turf.atmos_spawn_air("miasma=100;TEMP=100") + +/datum/spacevine_mutation/fleshmending + name = "flesh-mending" + hue = "#470566" + severity = 10 + quality = POSITIVE + +/datum/spacevine_mutation/fleshmending/on_cross(obj/structure/spacevine/holder, mob/crosser) + if(isliving(crosser)) + var/mob/living/living_crosser = crosser + living_crosser.adjustBruteLoss(-1) + living_crosser.adjustFireLoss(-1) + living_crosser.adjustToxLoss(-1) + +/datum/spacevine_mutation/fleshmending/on_eat(obj/structure/spacevine/holder, mob/living/eater) + if(isliving(eater)) + var/mob/living/living_eater = eater + living_eater.adjustBruteLoss(-5) + living_eater.adjustFireLoss(-5) + living_eater.adjustToxLoss(-5) + +/datum/spacevine_mutation/oxygen_producing + name = "oxygen-producing" + hue = "#4620ee" + severity = 10 + quality = POSITIVE + +/datum/spacevine_mutation/oxygen_producing/on_grow(obj/structure/spacevine/holder) + var/turf/holder_turf = get_turf(holder) + holder_turf.atmos_spawn_air("o2=100;TEMP=100") + +/datum/spacevine_mutation/nitrogen_producing + name = "nitrogen-producing" + hue = "#ce2929" + severity = 10 + quality = POSITIVE + +/datum/spacevine_mutation/nitrogen_producing/on_grow(obj/structure/spacevine/holder) + var/turf/holder_turf = get_turf(holder) + holder_turf.atmos_spawn_air("n2=100;TEMP=100") + +// SPACE VINES (Note that this code is very similar to Biomass code) +/obj/structure/spacevine + name = "space vines" + desc = "An extremely expansionistic species of vine." + icon = 'icons/effects/spacevines.dmi' + icon_state = "Light1" + anchored = TRUE + density = FALSE + layer = SPACEVINE_LAYER + mouse_opacity = MOUSE_OPACITY_OPAQUE //Clicking anywhere on the turf is good enough + pass_flags = PASSTABLE | PASSGRILLE + max_integrity = 50 + var/energy = 0 + var/datum/spacevine_controller/master = null + var/list/mutations = list() + var/plantbgone_resist = FALSE + +/obj/structure/spacevine/Initialize(mapload) + . = ..() + add_atom_colour("#ffffff", FIXED_COLOUR_PRIORITY) + AddElement(/datum/element/atmos_sensitive, mapload) + +/obj/structure/spacevine/examine(mob/user) + . = ..() + var/text = "This one is a" + if(mutations.len) + for(var/A in mutations) + var/datum/spacevine_mutation/SM = A + text += " [SM.name]" + else + text += " normal" + text += " vine." + . += text + +/obj/structure/spacevine/Destroy() + for(var/datum/spacevine_mutation/SM in mutations) + SM.on_death(src) + if(master) + master.VineDestroyed(src) + mutations = list() + set_opacity(0) + if(has_buckled_mobs()) + unbuckle_all_mobs(force=1) + return ..() + +/obj/structure/spacevine/proc/on_chem_effect(datum/reagent/R) + var/override = 0 + for(var/datum/spacevine_mutation/SM in mutations) + override += SM.on_chem(src, R) + if(!override && istype(R, /datum/reagent/toxin/plantbgone) && !plantbgone_resist) + if(prob(50)) + qdel(src) + +/obj/structure/spacevine/proc/eat(mob/eater) + var/override = 0 + for(var/datum/spacevine_mutation/SM in mutations) + override += SM.on_eat(src, eater) + if(!override) + qdel(src) + +/obj/structure/spacevine/attacked_by(obj/item/I, mob/living/user) + var/damage_dealt = I.force + if(I.get_sharpness()) + damage_dealt *= 4 + if(I.damtype == BURN) + damage_dealt *= 4 + + for(var/datum/spacevine_mutation/SM in mutations) + damage_dealt = SM.on_hit(src, user, I, damage_dealt) //on_hit now takes override damage as arg and returns new value for other mutations to permutate further + take_damage(damage_dealt, I.damtype, MELEE, 1) + +/obj/structure/spacevine/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + if(damage_amount) + playsound(src, 'sound/weapons/slash.ogg', 50, TRUE) + else + playsound(src, 'sound/weapons/tap.ogg', 50, TRUE) + if(BURN) + playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE) + +/obj/structure/spacevine/Crossed(atom/movable/AM) + . = ..() + if(!isliving(AM)) + return + for(var/datum/spacevine_mutation/SM in mutations) + SM.on_cross(src, AM) + if(istype(AM, /mob/living/simple_animal/hostile/venus_human_trap)) //skyrat change: vines heal flytraps 10% on cross + var/mob/living/simple_animal/hostile/venus_human_trap/VS = AM + if(VS.health >= VS.maxHealth) + return + VS.adjustHealth(-clamp(VS.health += 5, 0, VS.maxHealth), TRUE, TRUE) + to_chat(VS, "The vines attempt to regenerate some of your wounds!") + return + +//ATTACK HAND IGNORING PARENT RETURN VALUE +/obj/structure/spacevine/attack_hand(mob/user, list/modifiers) + for(var/datum/spacevine_mutation/SM in mutations) + SM.on_hit(src, user) + user_unbuckle_mob(user, user) + . = ..() + +/obj/structure/spacevine/attack_paw(mob/living/user, list/modifiers) + for(var/datum/spacevine_mutation/SM in mutations) + SM.on_hit(src, user) + user_unbuckle_mob(user,user) + +/obj/structure/spacevine/attack_alien(mob/living/user, list/modifiers) + eat(user) + +/datum/spacevine_controller + var/list/obj/structure/spacevine/vines + var/list/growth_queue + var/spread_multiplier = 5 + var/spread_cap = 30 + var/list/vine_mutations_list + var/mutativeness = 1 + +/datum/spacevine_controller/New(turf/location, list/muts, potency, production, datum/round_event/event = null) + vines = list() + growth_queue = list() + var/obj/structure/spacevine/SV = spawn_spacevine_piece(location, null, muts) + if (event) + event.announce_to_ghosts(SV) + START_PROCESSING(SSobj, src) + vine_mutations_list = list() + init_subtypes(/datum/spacevine_mutation/, vine_mutations_list) + if(potency != null) + mutativeness = potency / 10 + if(production != null && production <= 10) //Prevents runtime in case production is set to 11. + spread_cap *= (11 - production) / 5 //Best production speed of 1 doubles spread_cap to 60 while worst speed of 10 lowers it to 6. Even distribution. + spread_multiplier /= (11 - production) / 5 + +/datum/spacevine_controller/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION(VV_HK_SPACEVINE_PURGE, "Delete Vines") + +/datum/spacevine_controller/vv_do_topic(href_list) + . = ..() + if(href_list[VV_HK_SPACEVINE_PURGE]) + if(alert(usr, "Are you sure you want to delete this spacevine cluster?", "Delete Vines", "Yes", "No") == "Yes") + DeleteVines() + +/datum/spacevine_controller/proc/DeleteVines() //this is kill + QDEL_LIST(vines) //this will also qdel us + +/datum/spacevine_controller/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/datum/spacevine_controller/proc/spawn_spacevine_piece(turf/location, obj/structure/spacevine/parent, list/muts) + var/obj/structure/spacevine/SV = new(location) + growth_queue += SV + vines += SV + SV.master = src + if(muts?.len) + for(var/datum/spacevine_mutation/M in muts) + M.add_mutation_to_vinepiece(SV) + if(parent) + SV.mutations |= parent.mutations + var/parentcolor = parent.atom_colours[FIXED_COLOUR_PRIORITY] + SV.add_atom_colour(parentcolor, FIXED_COLOUR_PRIORITY) + if(prob(mutativeness)) + var/datum/spacevine_mutation/randmut = pick(vine_mutations_list - SV.mutations) + randmut.add_mutation_to_vinepiece(SV) + + for(var/datum/spacevine_mutation/SM in SV.mutations) + SM.on_birth(SV) + location.Entered(SV) + return SV + +/datum/spacevine_controller/proc/VineDestroyed(obj/structure/spacevine/S) + S.master = null + vines -= S + growth_queue -= S + if(!vines.len) + var/obj/item/seeds/kudzu/KZ = new(S.loc) + KZ.mutations |= S.mutations + KZ.set_potency(mutativeness * 10) + KZ.set_production(11 - (spread_cap / initial(spread_cap)) * 5) //Reverts spread_cap formula so resulting seed gets original production stat or equivalent back. + qdel(src) + +/datum/spacevine_controller/process(delta_time) + if(!LAZYLEN(vines)) + qdel(src) //space vines exterminated. Remove the controller + return + if(!growth_queue) + qdel(src) //Sanity check + return + + var/length = round(clamp(delta_time * 0.5 * vines.len / spread_multiplier, 1, spread_cap)) + var/i = 0 + var/list/obj/structure/spacevine/queue_end = list() + + for(var/obj/structure/spacevine/SV in growth_queue) + if(QDELETED(SV)) + continue + i++ + queue_end += SV + growth_queue -= SV + for(var/datum/spacevine_mutation/SM in SV.mutations) + SM.process_mutation(SV) + if(SV.energy < 2) //If tile isn't fully grown + if(DT_PROB(50, delta_time)) //SKYRAT EDIT CHANGE + SV.grow() + else //If tile is fully grown + SV.entangle_mob() + + SV.spread() + if(i >= length) + break + + growth_queue = growth_queue + queue_end + +/obj/structure/spacevine/proc/grow() + if(!energy) + src.icon_state = pick("Med1", "Med2", "Med3") + energy = 1 + set_opacity(1) + else + src.icon_state = pick("Hvy1", "Hvy2", "Hvy3") + energy = 2 + + for(var/datum/spacevine_mutation/SM in mutations) + SM.on_grow(src) + +/obj/structure/spacevine/proc/entangle_mob() + if(!has_buckled_mobs() && prob(25)) + for(var/mob/living/V in src.loc) + entangle(V) + if(has_buckled_mobs()) + break //only capture one mob at a time + +/obj/structure/spacevine/proc/entangle(mob/living/V) + if(!V || isvineimmune(V)) + return + for(var/datum/spacevine_mutation/SM in mutations) + SM.on_buckle(src, V) + if((V.stat != DEAD) && (V.buckled != src)) //not dead or captured + to_chat(V, "The vines [pick("wind", "tangle", "tighten")] around you!") + buckle_mob(V, 1) + +/// Finds a target tile to spread to. If checks pass it will spread to it and also proc on_spread on target. +/obj/structure/spacevine/proc/spread() + var/direction = pick(GLOB.cardinals) + var/turf/stepturf = get_step(src,direction) + for(var/obj/machinery/door/D in stepturf.contents) + if(prob(50)) + D.open() + if(!isspaceturf(stepturf) && stepturf.Enter(src)) + var/obj/structure/spacevine/spot_taken = locate() in stepturf //Locates any vine on target turf. Calls that vine "spot_taken". + var/datum/spacevine_mutation/vine_eating/E = locate() in mutations //Locates the vine eating trait in our own seed and calls it E. + if(!spot_taken || (E && (spot_taken && !spot_taken.mutations.Find(E)))) //Proceed if there isn't a vine on the target turf, OR we have vine eater AND target vine is from our seed and doesn't. Vines from other seeds are eaten regardless. + if(master) + for(var/datum/spacevine_mutation/SM in mutations) + SM.on_spread(src, stepturf) //Only do the on_spread proc if it actually spreads. + stepturf = get_step(src,direction) //in case turf changes, to make sure no runtimes happen + master.spawn_spacevine_piece(stepturf, src) + +/obj/structure/spacevine/ex_act(severity, target) + var/i + for(var/datum/spacevine_mutation/SM in mutations) + i += SM.on_explosion(severity, target, src) + if(!i && prob(34 * severity)) + qdel(src) + +/obj/structure/spacevine/should_atmos_process(datum/gas_mixture/air, exposed_temperature) + return exposed_temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD //if you're cold you're safe + +/obj/structure/spacevine/atmos_expose(datum/gas_mixture/air, exposed_temperature) + var/volume = air.return_volume() + for(var/datum/spacevine_mutation/SM in mutations) + if(SM.process_temperature(src, exposed_temperature, volume)) //If it's ever true we're safe + return + qdel(src) + +/obj/structure/spacevine/CanAllowThrough(atom/movable/mover, turf/target) + . = ..() + if(isvineimmune(mover)) + return TRUE + +/proc/isvineimmune(atom/A) + if(isliving(A)) + var/mob/living/M = A + if(("vines" in M.faction) || ("plants" in M.faction)) + return TRUE + return FALSE diff --git a/modular_skyrat/modules/aesthetics/stacks/stack_objects.dmi b/modular_skyrat/modules/aesthetics/stacks/stack_objects.dmi index 29273b72c24..6ed3d598709 100644 Binary files a/modular_skyrat/modules/aesthetics/stacks/stack_objects.dmi and b/modular_skyrat/modules/aesthetics/stacks/stack_objects.dmi differ diff --git a/modular_skyrat/modules/biohazard_blob/code/_biohazard_blob_defines.dm b/modular_skyrat/modules/biohazard_blob/code/_biohazard_blob_defines.dm index 9d294c788b4..5188345b37b 100644 --- a/modular_skyrat/modules/biohazard_blob/code/_biohazard_blob_defines.dm +++ b/modular_skyrat/modules/biohazard_blob/code/_biohazard_blob_defines.dm @@ -2,6 +2,7 @@ #define BIO_BLOB_TYPE_FIRE "fire" #define BIO_BLOB_TYPE_EMP "emp" #define BIO_BLOB_TYPE_TOXIC "toxic" -#define ALL_BIO_BLOB_TYPES list(BIO_BLOB_TYPE_FUNGUS, BIO_BLOB_TYPE_FIRE, BIO_BLOB_TYPE_EMP, BIO_BLOB_TYPE_TOXIC) +#define BIO_BLOB_TYPE_RADIOACTIVE "radioactive" +#define ALL_BIO_BLOB_TYPES list(BIO_BLOB_TYPE_FUNGUS, BIO_BLOB_TYPE_FIRE, BIO_BLOB_TYPE_EMP, BIO_BLOB_TYPE_TOXIC, BIO_BLOB_TYPE_RADIOACTIVE) #define MOLD_FACTION "mold" diff --git a/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_controller.dm b/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_controller.dm index de9ae5c5bd0..3d7fd4b19ff 100644 --- a/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_controller.dm +++ b/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_controller.dm @@ -1,9 +1,9 @@ -#define SPREAD_PROCESS 3 -#define SPREAD_STALLED_PROCESS 20 +#define SPREAD_PROCESS 2 +#define SPREAD_STALLED_PROCESS 10 -#define PROGRESSION_FOR_STRUCTURE 30 -#define PROGRESSION_RETALIATED 3 -#define STRUCTURE_PROGRESSION_START 23 +#define PROGRESSION_FOR_STRUCTURE 20 +#define PROGRESSION_RETALIATED 5 +#define STRUCTURE_PROGRESSION_START 20 #define RESIN_CANT_SPREAD 0 #define RESIN_DID_SPREAD 1 @@ -33,9 +33,10 @@ /datum/biohazard_blob_controller/proc/SpawnExpansion() var/list/turfs = list() - var/hatcheries_to_spawn = 2 - var/bulbs_to_spawn = 1 - var/spread_radius = 3 + var/hatcheries_to_spawn = 3 + var/bulbs_to_spawn = rand(3, 5) + var/conditioners_to_spawn = 2 + var/spread_radius = 5 var/our_turf = get_turf(our_core) turfs[our_turf] = TRUE for(var/i in 1 to spread_radius) @@ -54,6 +55,9 @@ else if(bulbs_to_spawn && prob(40)) bulbs_to_spawn-- SpawnStructureLoc(1, T) + else if(conditioners_to_spawn && prob(40)) + conditioners_to_spawn-- + SpawnStructureLoc(3, T) /datum/biohazard_blob_controller/proc/SpawnStructureLoc(index, location) var/spawn_type @@ -62,6 +66,9 @@ spawn_type = /obj/structure/biohazard_blob/structure/bulb if(2) spawn_type = /obj/structure/biohazard_blob/structure/spawner + if(3) + spawn_type = /obj/structure/biohazard_blob/structure/conditioner + var/struct = new spawn_type(location, blob_type) other_structures[struct] = TRUE our_core.max_integrity += 10 @@ -86,9 +93,11 @@ a_resin.blooming = FALSE a_resin.set_light(0) a_resin.update_overlays() - //With the death of the core, we kill all structures - for(var/t in other_structures) - var/obj/structure/biohazard_blob/structure/our_structure = t + for(var/obj/structure/biohazard_blob/structure/conditioner/c in other_structures) + var/obj/structure/biohazard_blob/structure/our_structure = c + qdel(our_structure) + for(var/obj/structure/biohazard_blob/structure/spawner/s in other_structures) + var/obj/structure/biohazard_blob/structure/our_structure = s qdel(our_structure) return @@ -103,20 +112,19 @@ break if(!forbidden) structure_progression -= PROGRESSION_FOR_STRUCTURE - var/random = rand(1,2) + var/random = rand(1,3) SpawnStructureLoc(random, ownturf) //Check if we can attack an airlock for(var/a in get_adjacent_open_turfs(spreaded_resin)) var/turf/open/open_turf = a for(var/obj/O in open_turf) - if(istype(O, /obj/machinery/door/airlock) || istype(O, /obj/machinery/door/firedoor) || istype(O, /obj/structure/door_assembly)) - if(O.density) - spreaded_resin.do_attack_animation(O, ATTACK_EFFECT_PUNCH) - playsound(O, 'sound/effects/attackblob.ogg', 50, TRUE) - O.take_damage(40, BRUTE, MELEE, 1, get_dir(O, spreaded_resin)) - . = RESIN_ATTACKED_DOOR - break + if(istype(O, /obj/machinery/door/airlock) || istype(O, /obj/machinery/door/firedoor) || istype(O, /obj/machinery/door/window) || istype(O, /obj/structure/door_assembly) || istype(O, /obj/machinery/door/window)) + spreaded_resin.do_attack_animation(O, ATTACK_EFFECT_PUNCH) + playsound(O, 'sound/effects/attackblob.ogg', 50, TRUE) + O.take_damage(40, BRUTE, MELEE, 1, get_dir(O, spreaded_resin)) + . = RESIN_ATTACKED_DOOR + break if(.) break diff --git a/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_disease.dm b/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_disease.dm index f2f4e73a524..a3fe48d9ee8 100644 --- a/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_disease.dm +++ b/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_disease.dm @@ -7,52 +7,58 @@ cures = list(/datum/reagent/medicine/spaceacillin, /datum/reagent/medicine/c2/convermol) agent = "Fungal Cordycep bacillus" viable_mobtypes = list(/mob/living/carbon/human) - cure_chance = 30 + cure_chance = 20 desc = "Fungal virus that attacks patient's muscles and brain in an attempt to hijack them. Causes fever, headaches, muscle spasms, and fatigue." severity = DISEASE_SEVERITY_BIOHAZARD bypasses_immunity = TRUE -/datum/disease/cordyceps/stage_act() +/datum/disease/cordyceps/stage_act(delta_time, times_fired) . = ..() if(!.) return switch(stage) if(2) - if(prob(2)) + if(DT_PROB(2, delta_time)) affected_mob.emote("twitch") to_chat(affected_mob, "You twitch.") - if(prob(2)) - to_chat(affected_mob, "You feel tired") //SKYRAT EDIT Grammar - if(prob(5)) - to_chat(affected_mob, "Your head hurts.") //SKYRAT EDIT Grammar + if(DT_PROB(2, delta_time)) + to_chat(affected_mob, "You feel tired.") + if(DT_PROB(5, delta_time)) + to_chat(affected_mob, "Your head hurts.") if(3,4) - if(prob(2)) + if(DT_PROB(2, delta_time)) to_chat(affected_mob, "You see four of everything!") affected_mob.Dizzy(5) - if(prob(2)) + if(DT_PROB(2, delta_time)) to_chat(affected_mob, "You suddenly feel exhausted.") affected_mob.adjustStaminaLoss(30, FALSE) - if(prob(2)) + if(DT_PROB(2, delta_time)) to_chat(affected_mob, "You feel hot.") affected_mob.adjust_bodytemperature(20) + if(DT_PROB(5, delta_time)) + to_chat(affected_mob, "You feel air escape from your lungs painfully.") + affected_mob.adjustOxyLoss(25, FALSE) + affected_mob.emote("gasp") if(5) - if(prob(5)) + if(DT_PROB(5, delta_time)) to_chat(affected_mob, "[pick("Your muscles seize!", "You collapse!")]") affected_mob.adjustStaminaLoss(50, FALSE) affected_mob.Paralyze(40, FALSE) affected_mob.adjustBruteLoss(5) //It's damaging the muscles - if(prob(2)) + if(DT_PROB(2, delta_time)) affected_mob.adjustStaminaLoss(100, FALSE) affected_mob.visible_message("[affected_mob] faints!", "You surrender yourself and feel at peace...") affected_mob.AdjustSleeping(100) - if(prob(5)) + if(DT_PROB(5, delta_time)) to_chat(affected_mob, "You feel your mind relax and your thoughts drift!") affected_mob.set_confusion(min(100, affected_mob.get_confusion() + 8)) affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10) - if(prob(10)) + if(DT_PROB(10, delta_time)) to_chat(affected_mob, "[pick("You feel uncomfortably hot...", "You feel like unzipping your jumpsuit", "You feel like taking off some clothes...")]") affected_mob.adjust_bodytemperature(30) + if(DT_PROB(5, delta_time)) + affected_mob.vomit(20) /datum/reagent/cordycepsspores name = "Cordycep bacillus microbes" diff --git a/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_mobs.dm b/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_mobs.dm index 2672698a907..8202942e214 100644 --- a/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_mobs.dm +++ b/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_mobs.dm @@ -22,6 +22,7 @@ turns_per_move = 4 maxHealth = 150 health = 150 + speed = 0 obj_damage = 40 melee_damage_lower = 10 melee_damage_upper = 15 @@ -34,6 +35,8 @@ light_power = 1 light_color = LIGHT_COLOR_FIRE damage_coeff = list(BRUTE = 1, BURN = 0, TOX = 0, CLONE = 1, STAMINA = 0, OXY = 0) + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minbodytemp = 0 maxbodytemp = INFINITY gender = MALE @@ -78,6 +81,7 @@ maxHealth = 70 health = 70 obj_damage = 30 + speed = 0 melee_damage_lower = 7 melee_damage_upper = 13 faction = list(MOLD_FACTION) @@ -88,6 +92,14 @@ attack_sound = 'sound/weapons/bite.ogg' melee_damage_type = BRUTE +/mob/living/simple_animal/hostile/biohazard_blob/diseased_rat/AttackingTarget() + . = ..() + if(iscarbon(target)) + var/mob/living/carbon/C = target + if(prob(40)) + to_chat(C, "[src] manages to penetrate your clothing with it's teeth!") + C.ForceContractDisease(new /datum/disease/cordyceps(), FALSE, TRUE) + /mob/living/simple_animal/hostile/biohazard_blob/electric_mosquito name = "electric mosquito" desc = "An ovesized mosquito, with what it seems like electricity inside its body." @@ -100,18 +112,73 @@ turns_per_move = 4 maxHealth = 70 health = 70 + speed = 0 obj_damage = 20 - melee_damage_lower = 5 - melee_damage_upper = 6 + melee_damage_lower = 7 + melee_damage_upper = 10 faction = list(MOLD_FACTION) attack_verb_continuous = "stings" attack_verb_simple = "sting" attack_sound = 'sound/effects/attackblob.ogg' melee_damage_type = BRUTE pass_flags = PASSTABLE + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minbodytemp = 0 + maxbodytemp = INFINITY /mob/living/simple_animal/hostile/biohazard_blob/electric_mosquito/AttackingTarget() . = ..() if(iscarbon(target)) var/mob/living/carbon/C = target C.reagents.add_reagent(/datum/reagent/teslium, 2) + +/mob/living/simple_animal/hostile/biohazard_blob/centaur + name = "centaur" + desc = "A horrific combination of bone and flesh with multiple sets of legs and feet." + icon_state = "centaur" + icon_living = "centaur" + icon_dead = "centaur_dead" + speak_emote = list("moans") + emote_hear = list("moans") + speak_chance = 5 + turns_per_move = 1 + maxHealth = 120 + health = 120 + speed = 0.5 + obj_damage = 40 + melee_damage_lower = 10 + melee_damage_upper = 15 + faction = list(MOLD_FACTION) + attack_sound = 'sound/effects/wounds/crackandbleed.ogg' + melee_damage_type = BRUTE + light_system = MOVABLE_LIGHT + light_range = 2 + light_power = 1 + light_color = LIGHT_COLOR_GREEN + damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 1, STAMINA = 0, OXY = 0) + gender = NEUTER + wound_bonus = 30 + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minbodytemp = 0 + maxbodytemp = INFINITY + +/mob/living/simple_animal/hostile/biohazard_blob/centaur/Initialize() + . = ..() + update_overlays() + +/mob/living/simple_animal/hostile/biohazard_blob/centaur/death(gibbed) + visible_message("The [src] ruptures!") + var/datum/reagents/R = new/datum/reagents(300) + R.my_atom = src + R.add_reagent(/datum/reagent/toxin/mutagen, 50) + chem_splash(loc, 5, list(R)) + playsound(src, 'sound/effects/splat.ogg', 50, TRUE) + return ..() + +/mob/living/simple_animal/hostile/biohazard_blob/centaur/AttackingTarget() + . = ..() + if(isliving(target)) + var/mob/living/L = target + if(prob(20)) + radiation_pulse(L, 300, 1, FALSE, TRUE) + playsound(src, 'modular_skyrat/modules/horrorform/sound/effects/horror_scream.ogg', 60, TRUE) diff --git a/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_structures.dm b/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_structures.dm index 5d61d45e563..c5f8d8a1870 100644 --- a/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_structures.dm +++ b/modular_skyrat/modules/biohazard_blob/code/biohazard_blob_structures.dm @@ -30,6 +30,9 @@ if(BIO_BLOB_TYPE_TOXIC) color = "#480" resistance_flags = UNACIDABLE | ACID_PROOF + if(BIO_BLOB_TYPE_RADIOACTIVE) + color = "#80ff00" + resistance_flags = ACID_PROOF | FIRE_PROOF //Shit's gonna get hot /obj/structure/biohazard_blob/structure density = TRUE @@ -39,7 +42,7 @@ mid_sounds = list('modular_skyrat/master_files/sound/effects/heart_beat_loop3.ogg'=1) volume = 20 -#define CORE_RETALIATION_COOLDOWN 30 SECONDS +#define CORE_RETALIATION_COOLDOWN 5 SECONDS /obj/structure/biohazard_blob/structure/core name = "glowing core" @@ -49,7 +52,7 @@ light_range = 2 light_power = 1 light_color = LIGHT_COLOR_LAVA - max_integrity = 450 + max_integrity = 1200 var/datum/looping_sound/core_heartbeat/soundloop var/next_retaliation = 0 @@ -65,6 +68,9 @@ /obj/structure/biohazard_blob/structure/core/toxic blob_type = BIO_BLOB_TYPE_TOXIC +/obj/structure/biohazard_blob/structure/core/radioactive + blob_type = BIO_BLOB_TYPE_RADIOACTIVE + /obj/structure/biohazard_blob/structure/core/Initialize() if(!blob_type) blob_type = pick(ALL_BIO_BLOB_TYPES) @@ -104,8 +110,8 @@ my_turf.atmos_spawn_air("o2=20;plasma=20;TEMP=600") if(BIO_BLOB_TYPE_EMP) visible_message("The [src] sends out electrical discharges!") + empulse(src, 5, 10) if(prob(50)) - empulse(src, 3, 4) for(var/mob/living/M in get_hearers_in_view(3, my_turf)) if(M.flash_act(affect_silicon = 1)) M.Paralyze(20) @@ -122,6 +128,15 @@ var/datum/effect_system/foam_spread/foam = new foam.set_up(40, my_turf, R) foam.start() + if(BIO_BLOB_TYPE_RADIOACTIVE) + visible_message("The [src] emits a strong radiation pulse!") + radiation_pulse(src, 1500, 10, FALSE, TRUE) + var/datum/reagents/R = new/datum/reagents(300) + R.my_atom = src + R.add_reagent(/datum/reagent/toxin/mutagen, 50) + var/datum/effect_system/foam_spread/foam = new + foam.set_up(50, my_turf, R) + foam.start() return ..() /obj/structure/biohazard_blob/structure/core/update_overlays() @@ -160,6 +175,9 @@ desc += " You can notice small sparks travelling in the vines." if(BIO_BLOB_TYPE_TOXIC) desc += " It feels damp and smells of rat poison." + if(BIO_BLOB_TYPE_RADIOACTIVE) + desc += " It glows softly." + AddComponent(/datum/component/slippery, 80) /obj/structure/biohazard_blob/resin/update_overlays() . = ..() @@ -230,7 +248,6 @@ /obj/structure/biohazard_blob/structure/bulb name = "empty bulb" - density = TRUE icon = 'modular_skyrat/modules/biohazard_blob/icons/blob_bulb.dmi' icon_state = "blob_bulb_empty" density = FALSE @@ -285,7 +302,7 @@ T.atmos_spawn_air("o2=20;plasma=20;TEMP=600") if(BIO_BLOB_TYPE_EMP) if(prob(50)) - empulse(src, 3, 4) + empulse(src, 5, 7) for(var/mob/living/M in get_hearers_in_view(3, T)) if(M.flash_act(affect_silicon = 1)) M.Paralyze(20) @@ -300,7 +317,16 @@ var/datum/effect_system/foam_spread/foam = new foam.set_up(40, T, R) foam.start() - + if(BIO_BLOB_TYPE_RADIOACTIVE) + radiation_pulse(src, 1500, 15, FALSE, TRUE) + fire_nuclear_particle() + empulse(src, 5, 7) + var/datum/reagents/R = new/datum/reagents(300) + R.my_atom = src + R.add_reagent(/datum/reagent/toxin/mutagen, 50) + var/datum/effect_system/foam_spread/foam = new + foam.set_up(50, T, R) + foam.start() is_full = FALSE name = "empty bulb" icon_state = "blob_bulb_empty" @@ -308,9 +334,17 @@ set_light(0) update_overlays() density = FALSE - addtimer(CALLBACK(src, .proc/make_full), 150 SECONDS, TIMER_UNIQUE|TIMER_NO_HASH_WAIT) + addtimer(CALLBACK(src, .proc/make_full), 1 MINUTES, TIMER_UNIQUE|TIMER_NO_HASH_WAIT) -/obj/structure/biohazard_blob/structure/bulb/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) +/obj/structure/biohazard_blob/structure/bulb/attack_generic(mob/user, damage_amount, damage_type, damage_flag, sound_effect, armor_penetration) + if(MOLD_FACTION in user.faction) + return ..() + discharge() + . = ..() + +/obj/structure/biohazard_blob/structure/bulb/bullet_act(obj/projectile/P) + if(istype(P, /obj/projectile/energy/nuclear_particle)) + return ..() discharge() . = ..() @@ -355,6 +389,53 @@ our_controller.other_structures -= src return ..() +/obj/structure/biohazard_blob/structure/conditioner + name = "pulsating vent" + desc = "An unsightly vent, it appears to be puffing something out." + density = FALSE + icon = 'modular_skyrat/modules/biohazard_blob/icons/blob_spawner.dmi' + icon_state = "blob_vent" + density = FALSE + layer = LOW_OBJ_LAYER + max_integrity = 150 + ///The mold atmosphere conditioner will spawn the molds preferred atmosphere every so often. + var/happy_atmos = null + var/puff_cooldown = 15 SECONDS + var/puff_delay = 0 + +/obj/structure/biohazard_blob/structure/conditioner/Destroy() + STOP_PROCESSING(SSobj, src) + if(our_controller) + our_controller.other_structures -= src + return ..() + +/obj/structure/biohazard_blob/structure/conditioner/Initialize() + . = ..() + switch(blob_type) + if(BIO_BLOB_TYPE_FUNGUS) + happy_atmos = "miasma=50;TEMP=296" + if(BIO_BLOB_TYPE_FIRE) + happy_atmos = "co2=30;TEMP=1000" + if(BIO_BLOB_TYPE_EMP) + happy_atmos = "n2=30;TEMP=100" + if(BIO_BLOB_TYPE_TOXIC) + happy_atmos = "miasma=50;TEMP=296" + if(BIO_BLOB_TYPE_RADIOACTIVE) + happy_atmos = "tritium=5;TEMP=296" + + START_PROCESSING(SSobj, src) + +/obj/structure/biohazard_blob/structure/conditioner/process(delta_time) + if(!happy_atmos) + return + if(puff_delay > world.time) + return + puff_delay = world.time + puff_cooldown + var/turf/holder_turf = get_turf(src) + holder_turf.atmos_spawn_air(happy_atmos) + if(blob_type == BIO_BLOB_TYPE_RADIOACTIVE) + fire_nuclear_particle() + /obj/structure/biohazard_blob/structure/spawner name = "hatchery" density = FALSE @@ -365,7 +446,7 @@ max_integrity = 150 var/monster_types = list() var/max_spawns = 1 - var/spawn_cooldown = 600 //In deciseconds + var/spawn_cooldown = 1200 //In deciseconds /obj/structure/biohazard_blob/structure/spawner/Destroy() if(our_controller) @@ -377,15 +458,14 @@ switch(blob_type) if(BIO_BLOB_TYPE_FUNGUS) monster_types = list(/mob/living/simple_animal/hostile/biohazard_blob/diseased_rat) - max_spawns = 2 spawn_cooldown = 500 if(BIO_BLOB_TYPE_FIRE) monster_types = list(/mob/living/simple_animal/hostile/biohazard_blob/oil_shambler) if(BIO_BLOB_TYPE_EMP) monster_types = list(/mob/living/simple_animal/hostile/biohazard_blob/electric_mosquito) - max_spawns = 2 spawn_cooldown = 500 if(BIO_BLOB_TYPE_TOXIC) - monster_types = list(/mob/living/simple_animal/hostile/poison/giant_spider) //Laziness - + monster_types = list(/mob/living/simple_animal/hostile/poison/giant_spider) + if(BIO_BLOB_TYPE_RADIOACTIVE) + monster_types = list(/mob/living/simple_animal/hostile/biohazard_blob/centaur) AddComponent(/datum/component/spawner, monster_types, spawn_cooldown, list(MOLD_FACTION), "emerges from", max_spawns) diff --git a/modular_skyrat/modules/biohazard_blob/code/mold_event.dm b/modular_skyrat/modules/biohazard_blob/code/mold_event.dm new file mode 100644 index 00000000000..e52851f3f07 --- /dev/null +++ b/modular_skyrat/modules/biohazard_blob/code/mold_event.dm @@ -0,0 +1,55 @@ +/datum/round_event_control/mold + name = "Moldies" + typepath = /datum/round_event/mold + weight = 15 + max_occurrences = 3 + min_players = 10 + +/datum/round_event/mold + fakeable = FALSE + var/list/available_molds = list( + /obj/structure/biohazard_blob/structure/core/fungus, + /obj/structure/biohazard_blob/structure/core/fire, + /obj/structure/biohazard_blob/structure/core/emp, + /obj/structure/biohazard_blob/structure/core/toxic, + /obj/structure/biohazard_blob/structure/core/radioactive + ) + +/datum/round_event/mold/start() + var/list/turfs = list() //list of all the empty floor turfs in the hallway areas + + var/molds2spawn = rand(2, 3) + + var/obj/structure/biohazard_blob/resin/resintest = new() + + var/list/possible_spawn_areas = typecacheof(typesof(/area/maintenance, /area/security/prison, /area/construction)) + + for(var/area/A in world) + if(!is_station_level(A.z)) + continue + if(!is_type_in_typecache(A, possible_spawn_areas)) + continue + for(var/turf/open/floor in A) + if(!floor.Enter(resintest)) + continue + if(locate(/turf/closed) in range(2, floor)) + continue + turfs += floor + + qdel(resintest) + + for(var/i = 1, i <= molds2spawn) + var/picked_mold = pick(available_molds) + shuffle(turfs) + var/turf/picked_turf = pick(turfs) + if(turfs.len) //Pick a turf to spawn at if we can + if(locate(/obj/structure/biohazard_blob/structure/core) in range(20, picked_turf)) + turfs -= picked_turf + continue + var/obj/structure/biohazard_blob/boob = new picked_mold(picked_turf) + announce_to_ghosts(boob) + turfs -= picked_turf + i++ + else + message_admins("Mold failed to spawn.") + break diff --git a/modular_skyrat/modules/biohazard_blob/icons/blob_mobs.dmi b/modular_skyrat/modules/biohazard_blob/icons/blob_mobs.dmi index 257d58ebf57..96de9c702c0 100644 Binary files a/modular_skyrat/modules/biohazard_blob/icons/blob_mobs.dmi and b/modular_skyrat/modules/biohazard_blob/icons/blob_mobs.dmi differ diff --git a/modular_skyrat/modules/biohazard_blob/icons/blob_spawner.dmi b/modular_skyrat/modules/biohazard_blob/icons/blob_spawner.dmi index ebca9eee4a9..265534275d9 100644 Binary files a/modular_skyrat/modules/biohazard_blob/icons/blob_spawner.dmi and b/modular_skyrat/modules/biohazard_blob/icons/blob_spawner.dmi differ diff --git a/modular_skyrat/modules/cme/code/cme.dm b/modular_skyrat/modules/cme/code/cme.dm index 5d5a4be240a..74b5062425a 100644 --- a/modular_skyrat/modules/cme/code/cme.dm +++ b/modular_skyrat/modules/cme/code/cme.dm @@ -15,7 +15,7 @@ Armageddon is truly going to fuck the station, use it sparingly. /datum/round_event_control/cme name = "Coronal Mass Ejection: Minimal" typepath = /datum/round_event/cme - weight = 0 + weight = 10 min_players = 30 max_occurrences = 3 earliest_start = 25 MINUTES @@ -180,7 +180,8 @@ Armageddon is truly going to fuck the station, use it sparingly. anchored = TRUE opacity = FALSE density = FALSE - plane = LIGHTING_PLANE + plane = MASSIVE_OBJ_PLANE + plane = ABOVE_LIGHTING_PLANE CanAtmosPass = ATMOS_PASS_DENSITY var/timeleft = CME_MINIMAL_BUBBLE_BURST_TIME var/cme_light_range_lower = CME_MINIMAL_LIGHT_RANGE_LOWER diff --git a/tgstation.dme b/tgstation.dme index a53f00fc389..4f4ed45603e 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3590,6 +3590,7 @@ #include "modular_skyrat\master_files\code\modules\clothing\non_anthro_clothes.dm" #include "modular_skyrat\master_files\code\modules\clothing\head\monkey_magnification_helmet.dm" #include "modular_skyrat\master_files\code\modules\clothing\outfits\ert.dm" +#include "modular_skyrat\master_files\code\modules\events\spacevine.dm" #include "modular_skyrat\master_files\code\modules\events\spider_infestation.dm" #include "modular_skyrat\master_files\code\modules\jobs\job_types\cyborg.dm" #include "modular_skyrat\master_files\code\modules\language\language_holders.dm" @@ -3730,6 +3731,7 @@ #include "modular_skyrat\modules\biohazard_blob\code\biohazard_blob_disease.dm" #include "modular_skyrat\modules\biohazard_blob\code\biohazard_blob_mobs.dm" #include "modular_skyrat\modules\biohazard_blob\code\biohazard_blob_structures.dm" +#include "modular_skyrat\modules\biohazard_blob\code\mold_event.dm" #include "modular_skyrat\modules\blueshield\code\game\area\Space_Station_13_areas.dm" #include "modular_skyrat\modules\blueshield\code\game\objects\effects\landmarks.dm" #include "modular_skyrat\modules\blueshield\code\game\objects\items\devices\radio\encryptionkey.dm"