mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 13:10:02 +01:00
393 lines
11 KiB
Plaintext
393 lines
11 KiB
Plaintext
#define CORE_RETALIATION_COOLDOWN (5 SECONDS)
|
|
#define MOLD_BULB_ALPHA 100
|
|
|
|
/obj/structure/mold
|
|
anchored = TRUE
|
|
|
|
/// The controller controlling the mold's expansion
|
|
var/datum/mold_controller/mold_controller
|
|
/// The type of mold
|
|
var/datum/mold_type/mold_type
|
|
|
|
/obj/structure/mold/Destroy()
|
|
if(!mold_controller)
|
|
qdel(mold_type)
|
|
mold_controller = null
|
|
mold_type = null
|
|
playsound(src.loc, 'sound/effects/splat.ogg', 30, TRUE)
|
|
return ..()
|
|
|
|
/obj/structure/mold/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
|
switch(damage_type)
|
|
if(BRUTE)
|
|
playsound(loc, 'sound/effects/blob/attackblob.ogg', 100, TRUE)
|
|
if(BURN)
|
|
playsound(loc, 'sound/items/tools/welder.ogg', 100, TRUE)
|
|
|
|
/obj/structure/mold/Initialize(mapload, passed_type)
|
|
. = ..()
|
|
if(!mold_type)
|
|
mold_type = mold_controller?.mold_type || passed_type
|
|
|
|
color = mold_type.mold_color
|
|
resistance_flags = mold_type.resistance_flags
|
|
name = "[mold_type.name] [name]"
|
|
update_appearance()
|
|
|
|
/obj/structure/mold/structure
|
|
density = TRUE
|
|
/// Does the structure emit light?
|
|
var/emits_light = FALSE
|
|
|
|
/obj/structure/mold/structure/Initialize(mapload, passed_type)
|
|
. = ..()
|
|
if(emits_light)
|
|
light_range = 2
|
|
light_power = 1
|
|
if(mold_type.structure_light_color)
|
|
light_color = mold_type.structure_light_color
|
|
|
|
/datum/looping_sound/core_heartbeat
|
|
mid_length = 3 SECONDS
|
|
mid_sounds = list('modular_zubbers/sound/effects/heart_beat_loop3.ogg' = 1)
|
|
volume = 20
|
|
|
|
/**
|
|
* The core
|
|
*/
|
|
/obj/structure/mold/structure/core
|
|
name = "core"
|
|
icon = 'modular_skyrat/modules/mold/icons/blob_core.dmi'
|
|
icon_state = "blob_core"
|
|
layer = TABLE_LAYER
|
|
max_integrity = 600
|
|
|
|
/// The soundloop played by the core
|
|
var/datum/looping_sound/core_heartbeat/soundloop
|
|
/// The time to the next attack
|
|
var/next_retaliation = 0
|
|
|
|
/obj/structure/mold/structure/core/Initialize(mapload, passed_type)
|
|
if(mold_type)
|
|
passed_type = new mold_type
|
|
new /datum/mold_controller(src, passed_type)
|
|
. = ..()
|
|
soundloop = new(src, TRUE)
|
|
update_overlays()
|
|
|
|
/obj/structure/mold/structure/core/Destroy()
|
|
if(mold_controller)
|
|
mold_controller.our_core = null
|
|
soundloop.stop()
|
|
QDEL_NULL(soundloop)
|
|
return ..()
|
|
|
|
/obj/structure/mold/structure/core/run_atom_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
|
|
if(!(damage_amount > 10) || !(world.time > next_retaliation) || !prob(40))
|
|
return ..()
|
|
|
|
mold_controller?.core_retaliated()
|
|
next_retaliation = world.time + CORE_RETALIATION_COOLDOWN
|
|
|
|
mold_type.core_defense(src)
|
|
|
|
/obj/structure/mold/structure/core/update_overlays()
|
|
. = ..()
|
|
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
|
SSvis_overlays.add_vis_overlay(src, icon, "blob_core_overlay", layer, plane, dir, alpha)
|
|
SSvis_overlays.add_vis_overlay(src, icon, "blob_core_overlay", 0, EMISSIVE_PLANE, dir, alpha)
|
|
var/obj/effect/overlay/vis/overlay1 = managed_vis_overlays[1]
|
|
var/obj/effect/overlay/vis/overlay2 = managed_vis_overlays[2]
|
|
overlay1.appearance_flags = PIXEL_SCALE | TILE_BOUND | RESET_COLOR
|
|
overlay2.appearance_flags = PIXEL_SCALE | TILE_BOUND | RESET_COLOR
|
|
|
|
/**
|
|
* Preset types
|
|
* Useful for admins
|
|
*/
|
|
/obj/structure/mold/structure/core/fire
|
|
mold_type = /datum/mold_type/fire
|
|
|
|
/obj/structure/mold/structure/core/disease
|
|
mold_type = /datum/mold_type/disease
|
|
|
|
/obj/structure/mold/structure/core/emp
|
|
mold_type = /datum/mold_type/emp
|
|
|
|
/obj/structure/mold/structure/core/toxic
|
|
mold_type = /datum/mold_type/toxic
|
|
|
|
/obj/structure/mold/structure/core/radioactive
|
|
mold_type = /datum/mold_type/radioactive
|
|
|
|
|
|
|
|
/**
|
|
* Mold resin
|
|
*/
|
|
/obj/structure/mold/resin
|
|
name = "mold"
|
|
desc = "It looks like mold, but it seems alive."
|
|
icon = 'modular_skyrat/modules/mold/icons/blob_resin.dmi'
|
|
icon_state = "blob_floor"
|
|
density = FALSE
|
|
plane = GAME_PLANE
|
|
layer = LOW_SIGIL_LAYER
|
|
max_integrity = 25
|
|
var/blooming = FALSE
|
|
/// Are we a floor resin? If not then we're a wall resin
|
|
var/floor = TRUE
|
|
|
|
/obj/structure/mold/resin/examine(mob/user)
|
|
. = ..()
|
|
. += mold_type.examine_text
|
|
|
|
/obj/structure/mold/resin/update_overlays()
|
|
. = ..()
|
|
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
|
if(blooming)
|
|
SSvis_overlays.add_vis_overlay(src, icon, "[icon_state]_overlay", layer, plane, dir, alpha)
|
|
SSvis_overlays.add_vis_overlay(src, icon, "[icon_state]_overlay", 0, EMISSIVE_PLANE, dir, alpha)
|
|
var/obj/effect/overlay/vis/overlay1 = managed_vis_overlays[1]
|
|
var/obj/effect/overlay/vis/overlay2 = managed_vis_overlays[2]
|
|
overlay1.appearance_flags = PIXEL_SCALE | TILE_BOUND | RESET_COLOR
|
|
overlay2.appearance_flags = PIXEL_SCALE | TILE_BOUND | RESET_COLOR
|
|
|
|
/obj/structure/mold/resin/proc/calculate_direction()
|
|
var/direction = 16
|
|
var/turf/location = loc
|
|
for(var/wallDir in GLOB.cardinals)
|
|
var/turf/newTurf = get_step(location,wallDir)
|
|
if(newTurf && newTurf.density)
|
|
direction |= wallDir
|
|
|
|
for(var/obj/structure/mold/resin/tomato in location)
|
|
if(tomato == src)
|
|
continue
|
|
if(tomato.floor) //special
|
|
direction &= ~16
|
|
else
|
|
direction &= ~tomato.dir
|
|
|
|
var/list/dirList = list()
|
|
|
|
for(var/i=1,i<=16,i <<= 1)
|
|
if(direction & i)
|
|
dirList += i
|
|
|
|
if(dirList.len)
|
|
var/newDir = pick(dirList)
|
|
if(newDir == 16)
|
|
setDir(pick(GLOB.cardinals))
|
|
else
|
|
floor = FALSE
|
|
setDir(newDir)
|
|
switch(dir) //offset to make it be on the wall rather than on the floor
|
|
if(NORTH)
|
|
pixel_y = 32
|
|
if(SOUTH)
|
|
pixel_y = -32
|
|
if(EAST)
|
|
pixel_x = 32
|
|
if(WEST)
|
|
pixel_x = -32
|
|
icon_state = "blob_wall"
|
|
plane = GAME_PLANE
|
|
layer = LOW_SIGIL_LAYER
|
|
|
|
if(prob(7))
|
|
blooming = TRUE
|
|
set_light(2, 1, LIGHT_COLOR_LAVA)
|
|
update_overlays()
|
|
|
|
/obj/structure/mold/resin/Destroy()
|
|
if(mold_controller)
|
|
mold_controller.activate_adjacent_resin(get_turf(src))
|
|
mold_controller.all_resin -= src
|
|
mold_controller.active_resin -= src
|
|
return ..()
|
|
|
|
/obj/structure/mold/resin/test
|
|
mold_type = /datum/mold_type
|
|
|
|
/**
|
|
* Bulbs
|
|
*/
|
|
/obj/structure/mold/structure/bulb
|
|
name = "bulb"
|
|
icon = 'modular_skyrat/modules/mold/icons/blob_bulb.dmi'
|
|
icon_state = "blob_bulb_empty"
|
|
density = FALSE
|
|
layer = TABLE_LAYER
|
|
light_range = 2
|
|
light_power = 1
|
|
light_color = LIGHT_COLOR_LAVA
|
|
var/is_full = FALSE
|
|
var/list/registered_turfs = list()
|
|
max_integrity = 50
|
|
|
|
/obj/structure/mold/structure/bulb/Initialize(mapload)
|
|
. = ..()
|
|
make_full()
|
|
for(var/adjacent_turf in get_adjacent_open_turfs(src))
|
|
registered_turfs += adjacent_turf
|
|
RegisterSignal(adjacent_turf, COMSIG_ATOM_ENTERED, PROC_REF(proximity_trigger))
|
|
|
|
/obj/structure/mold/structure/bulb/proc/proximity_trigger(datum/source, atom/movable/nearby_atom)
|
|
SIGNAL_HANDLER
|
|
if(!isliving(nearby_atom))
|
|
return
|
|
var/mob/living/nearby_mob = nearby_atom
|
|
if(!(nearby_mob.has_faction(FACTION_MOLD)))
|
|
INVOKE_ASYNC(src, PROC_REF(discharge))
|
|
|
|
/obj/structure/mold/structure/bulb/proc/make_full()
|
|
//Called by a timer, check if we exist
|
|
if(QDELETED(src))
|
|
return
|
|
is_full = TRUE
|
|
icon_state = "blob_bulb_full"
|
|
set_light(2, 1, LIGHT_COLOR_LAVA)
|
|
density = TRUE
|
|
update_overlays()
|
|
|
|
|
|
/obj/structure/mold/structure/bulb/proc/discharge()
|
|
if(!is_full)
|
|
return
|
|
|
|
mold_type.bulb_discharge(src)
|
|
|
|
is_full = FALSE
|
|
icon_state = "blob_bulb_empty"
|
|
playsound(src, 'sound/effects/bamf.ogg', 100, TRUE)
|
|
set_light(0)
|
|
update_overlays()
|
|
density = FALSE
|
|
addtimer(CALLBACK(src, PROC_REF(make_full)), 1 MINUTES, TIMER_UNIQUE|TIMER_NO_HASH_WAIT)
|
|
|
|
/obj/structure/mold/structure/bulb/attack_generic(mob/user, damage_amount, damage_type, damage_flag, sound_effect, armor_penetration)
|
|
if(user.has_faction(FACTION_MOLD))
|
|
return ..()
|
|
discharge()
|
|
. = ..()
|
|
|
|
/obj/structure/mold/structure/bulb/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit = FALSE)
|
|
. = ..()
|
|
if(istype(hitting_projectile, /obj/projectile/energy/nuclear_particle) || . != BULLET_ACT_HIT)
|
|
return
|
|
discharge()
|
|
|
|
/obj/structure/mold/structure/bulb/Destroy()
|
|
if(mold_controller)
|
|
mold_controller.other_structures -= src
|
|
for(var/checked_turfs in registered_turfs)
|
|
UnregisterSignal(checked_turfs, COMSIG_ATOM_ENTERED)
|
|
registered_turfs = null
|
|
return ..()
|
|
|
|
/obj/structure/mold/structure/bulb/update_overlays()
|
|
. = ..()
|
|
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
|
if(is_full)
|
|
SSvis_overlays.add_vis_overlay(src, icon, "blob_bulb_overlay", layer, plane, dir, MOLD_BULB_ALPHA)
|
|
SSvis_overlays.add_vis_overlay(src, icon, "blob_bulb_overlay", 0, EMISSIVE_PLANE, dir, alpha)
|
|
var/obj/effect/overlay/vis/overlay1 = managed_vis_overlays[1]
|
|
var/obj/effect/overlay/vis/overlay2 = managed_vis_overlays[2]
|
|
overlay1.appearance_flags = PIXEL_SCALE | TILE_BOUND | RESET_COLOR
|
|
overlay2.appearance_flags = PIXEL_SCALE | TILE_BOUND | RESET_COLOR
|
|
|
|
|
|
/**
|
|
* Wall
|
|
*/
|
|
/obj/structure/mold/structure/wall
|
|
name = "mold wall"
|
|
desc = "Looks like some kind of thick resin."
|
|
icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi'
|
|
icon_state = "resin_wall-0"
|
|
base_icon_state = "resin_wall"
|
|
opacity = TRUE
|
|
smoothing_flags = SMOOTH_BITMASK
|
|
smoothing_groups = SMOOTH_GROUP_ALIEN_RESIN
|
|
canSmoothWith = SMOOTH_GROUP_ALIEN_RESIN
|
|
max_integrity = 100
|
|
can_atmos_pass = ATMOS_PASS_DENSITY
|
|
|
|
/obj/structure/mold/wall/Destroy()
|
|
if(mold_controller)
|
|
mold_controller.activate_adjacent_resin(get_turf(src))
|
|
mold_controller.other_structures -= src
|
|
return ..()
|
|
|
|
|
|
/**
|
|
* Conditioner
|
|
*/
|
|
/obj/structure/mold/structure/conditioner
|
|
name = "pulsating vent"
|
|
desc = "An unsightly vent, it appears to be puffing something out."
|
|
density = FALSE
|
|
icon = 'modular_skyrat/modules/mold/icons/blob_spawner.dmi'
|
|
icon_state = "blob_vent"
|
|
density = FALSE
|
|
layer = SIGIL_LAYER
|
|
max_integrity = 75
|
|
/// The mold atmosphere conditioner will spawn the mold's preferred atmosphere every so often.
|
|
var/happy_atmos = null
|
|
/// The time between injections of that mold type's preferred atmos
|
|
var/puff_cooldown = 30 SECONDS
|
|
/// Tracks the status of the cooldown
|
|
var/puff_delay = 0
|
|
|
|
/obj/structure/mold/structure/conditioner/Destroy()
|
|
STOP_PROCESSING(SSobj, src)
|
|
if(mold_controller)
|
|
mold_controller.other_structures -= src
|
|
return ..()
|
|
|
|
/obj/structure/mold/structure/conditioner/Initialize(mapload)
|
|
. = ..()
|
|
happy_atmos = mold_type.preferred_atmos_conditions
|
|
START_PROCESSING(SSobj, src)
|
|
|
|
/obj/structure/mold/structure/conditioner/process(seconds_per_tick)
|
|
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)
|
|
mold_type.bonus_conditioner_effects(src)
|
|
|
|
|
|
/**
|
|
* Hatchery
|
|
*/
|
|
/obj/structure/mold/structure/spawner
|
|
name = "hatchery"
|
|
icon = 'modular_skyrat/modules/mold/icons/blob_spawner.dmi'
|
|
icon_state = "blob_spawner"
|
|
density = FALSE
|
|
layer = SIGIL_LAYER
|
|
max_integrity = 75
|
|
|
|
/obj/structure/mold/structure/spawner/Destroy()
|
|
if(mold_controller)
|
|
mold_controller.other_structures -= src
|
|
return ..()
|
|
|
|
/obj/structure/mold/structure/spawner/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/spawner, \
|
|
spawn_types = mold_type.mob_types, \
|
|
spawn_time = mold_type.spawn_cooldown, \
|
|
max_spawned = mold_type.max_spawns, \
|
|
faction = list(FACTION_MOLD), \
|
|
spawn_text = "emerges from", \
|
|
)
|
|
|
|
#undef CORE_RETALIATION_COOLDOWN
|
|
#undef MOLD_BULB_ALPHA
|