diff --git a/_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm b/_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm
index 3d983d2a5be..5d159c28d40 100644
--- a/_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm
+++ b/_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm
@@ -11,7 +11,7 @@
/area/ruin/space/unpowered)
"d" = (
/obj/structure/alien/weeds,
-/obj/structure/alien/resin/membrane,
+/obj/structure/alien/resin/wall,
/turf/simulated/floor/plating/airless,
/area/ruin/space/unpowered)
"e" = (
@@ -47,10 +47,6 @@
/obj/structure/alien/resin/wall,
/turf/simulated/floor/plating/airless,
/area/ruin/space/unpowered)
-"l" = (
-/obj/structure/alien/resin/membrane,
-/turf/simulated/floor/plating/airless,
-/area/ruin/space/unpowered)
"m" = (
/obj/structure/alien/weeds,
/obj/structure/table,
@@ -819,7 +815,7 @@ f
c
f
f
-l
+k
b
b
a
@@ -862,7 +858,7 @@ f
f
f
f
-l
+k
q
b
a
@@ -1229,8 +1225,8 @@ a
a
b
b
-l
-l
+k
+k
p
p
a
diff --git a/code/__DEFINES/icon_smoothing.dm b/code/__DEFINES/icon_smoothing.dm
index bcc1c8fa8af..023d7b63d32 100644
--- a/code/__DEFINES/icon_smoothing.dm
+++ b/code/__DEFINES/icon_smoothing.dm
@@ -117,7 +117,7 @@ DEFINE_BITFIELD(smoothing_flags, list(
#define SMOOTH_GROUP_REINFORCED_TABLES S_OBJ(56) ///obj/structure/table/reinforced, /obj/structure/table/glass/reinforced
#define SMOOTH_GROUP_ALIEN_RESIN S_OBJ(60) ///obj/structure/alien/resin
-#define SMOOTH_GROUP_ALIEN_WALLS S_OBJ(61) ///obj/structure/alien/resin/wall, /obj/structure/alien/resin/membrane
+#define SMOOTH_GROUP_ALIEN_WALLS S_OBJ(61) ///obj/structure/alien/resin/wall,
#define SMOOTH_GROUP_ALIEN_WEEDS S_OBJ(62) ///obj/structure/alien/weeds
#define SMOOTH_GROUP_SECURITY_BARRICADE S_OBJ(63) ///obj/structure/barricade/security
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 523d0d0d6c7..eed6f6627ba 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1384,6 +1384,12 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays)
shock(user, 100) //Mmm, fried xeno!
return
if(!density) //Already open
+ if(!arePowerSystemsOn())
+ close(TRUE)
+ return
+ if(HAS_TRAIT_FROM(user, TRAIT_FORCE_DOORS, VAMPIRE_TRAIT))
+ close(TRUE)
+ return
return
if(locked || welded) //Extremely generic, as aliens only understand the basics of how airlocks work.
to_chat(user, "[src] refuses to budge!")
@@ -1391,14 +1397,22 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays)
if(prying_so_hard)
return
prying_so_hard = TRUE
- user.visible_message("[user] begins prying open [src].",\
- "You begin digging your claws into [src] with all your might!",\
- "You hear groaning metal...")
- var/time_to_open = 5
+ var/time_to_open = 0
if(arePowerSystemsOn())
+ if(HAS_TRAIT_FROM(user, TRAIT_FORCE_DOORS, VAMPIRE_TRAIT))
+ open(TRUE)
+ visible_message("[user] forces the door!")
+ playsound(loc, "sparks", 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+ prying_so_hard = FALSE
+ return
+ user.visible_message("[user] begins prying open [src].",\
+ "You begin digging your claws into [src] with all your might!",\
+ "You hear groaning metal...")
time_to_open = 50 //Powered airlocks take longer to open, and are loud.
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE)
-
+ else
+ visible_message("[user] forces the door!")
+ playsound(loc, "sparks", 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
if(do_after(user, time_to_open, TRUE, src))
if(density && !open(2)) //The airlock is still closed, but something prevented it opening. (Another player noticed and bolted/welded the airlock in time!)
diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm
index 56071ee5650..1235b7d9add 100644
--- a/code/game/objects/structures/aliens.dm
+++ b/code/game/objects/structures/aliens.dm
@@ -53,12 +53,18 @@
max_integrity = 200
var/resintype = null
-/obj/structure/alien/resin/Initialize()
+/obj/structure/alien/resin/Initialize(mapload)
air_update_turf(1)
- ..()
+ for(var/obj/structure/alien/weeds/node/W in get_turf(src))
+ qdel(W)
+ if(locate(/obj/structure/alien/weeds) in get_turf(src))
+ return ..()
+ new /obj/structure/alien/weeds(loc)
+ return ..()
/obj/structure/alien/resin/Destroy()
var/turf/T = get_turf(src)
+ playsound(loc, 'sound/effects/alien_resin_break2.ogg', 100, TRUE)
. = ..()
T.air_update_turf(TRUE)
@@ -70,6 +76,14 @@
/obj/structure/alien/resin/CanAtmosPass()
return !density
+/obj/structure/alien/resin/attack_alien(mob/living/carbon/alien/humanoid/user)
+ if(user.a_intent != INTENT_HARM)
+ return
+ to_chat(user, "We begin tearing down this resin structure.")
+ if(!do_after(user, 40, target = src) || QDELETED(src))
+ return
+ qdel(src)
+
/obj/structure/alien/resin/wall
name = "resin wall"
desc = "Thick resin solidified into a wall."
@@ -82,23 +96,140 @@
/obj/structure/alien/resin/wall/BlockSuperconductivity()
return TRUE
-/obj/structure/alien/resin/membrane
- name = "resin membrane"
- desc = "Resin just thin enough to let light pass through."
- icon = 'icons/obj/smooth_structures/alien/resin_membrane.dmi'
- icon_state = "resin_membrane-0"
- base_icon_state = "resin_membrane"
- opacity = FALSE
- max_integrity = 160
- resintype = "membrane"
+/*
+ *Resin-Door - Borrows its code from Mineral-Door, not a subtype due to needing many overrides if so
+*/
+/obj/structure/alien/resin/door
+ name = "resin door"
+ density = TRUE
+ anchored = TRUE
+ opacity = TRUE
+
+ icon = 'icons/obj/smooth_structures/alien/resin_door.dmi'
+ icon_state = "resin"
+ base_icon_state = "resin"
+ max_integrity = 150
+ armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 50, ACID = 50)
+ damage_deflection = 0
+ flags_2 = RAD_PROTECT_CONTENTS_2 | RAD_NO_CONTAMINATE_2
+ rad_insulation = RAD_MEDIUM_INSULATION
+ var/initial_state
+ var/state_open = FALSE
+ var/is_operating = FALSE
+ var/close_delay = 1.5 SECONDS
+ smoothing_flags = null
+ var/open_sound = 'sound/machines/alien_airlock.ogg'
+ var/close_sound = 'sound/machines/alien_airlock.ogg'
+
smoothing_groups = list(SMOOTH_GROUP_ALIEN_RESIN, SMOOTH_GROUP_ALIEN_WALLS)
canSmoothWith = list(SMOOTH_GROUP_ALIEN_WALLS)
-/obj/structure/alien/resin/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && mover.checkpass(PASSGLASS))
- return !opacity
+/obj/structure/alien/resin/door/Initialize(mapload)
+ . = ..()
+ initial_state = icon_state
+ QUEUE_SMOOTH_NEIGHBORS(src)
+
+/obj/structure/alien/resin/door/Destroy()
+ density = FALSE
+ QUEUE_SMOOTH_NEIGHBORS(src)
+ air_update_turf(1)
+ return ..()
+
+/obj/structure/alien/resin/door/Move()
+ var/turf/T = loc
+ . = ..()
+ move_update_air(T)
+
+/obj/structure/alien/resin/door/Crossed(mob/living/L, oldloc)
+ ..()
+ if(!state_open)
+ return try_to_operate(L)
+
+/obj/structure/alien/resin/door/attack_ai(mob/user)
+ return
+
+/obj/structure/alien/resin/door/attack_hand(mob/user)
+ return try_to_operate(user)
+
+/obj/structure/alien/resin/door/attack_ghost(mob/user)
+ if(user.can_advanced_admin_interact())
+ operate()
+
+/obj/structure/alien/resin/door/CanAtmosPass(turf/T)
return !density
+/obj/structure/alien/resin/door/proc/try_to_operate(mob/user)
+ if(is_operating)
+ return
+ if(!iscarbon(user))
+ return
+ var/mob/living/carbon/C = user
+ if(C.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
+ if(world.time - C.last_bumped <= 60)
+ return
+ if(!C.handcuffed)
+ operate()
+ return
+ to_chat(user, "Your lack of connection to the hive prevents the resin door from opening")
+/*
+ * This 2nd try_to_operate() is needed so that CALLBACK can close the door without having to either call operate() and get bugged when clicked much or
+ * call try_to_operate(atom/user) and not be able to use it due to not having a mob using it
+*/
+/obj/structure/alien/resin/door/proc/mobless_try_to_operate()
+ if(is_operating)
+ if(state_open)
+ addtimer(CALLBACK(src, PROC_REF(mobless_try_to_operate)), close_delay)
+ return
+ operate()
+
+/obj/structure/alien/resin/door/proc/operate()
+ is_operating = TRUE
+ if(!state_open)
+ playsound(loc, open_sound, 100, TRUE)
+ flick("[initial_state]opening", src)
+ else
+ for(var/mob/living/L in get_turf(src))
+ is_operating = FALSE
+ if(state_open)
+ addtimer(CALLBACK(src, PROC_REF(mobless_try_to_operate)), close_delay)
+ return
+ playsound(loc, close_sound, 100, 1)
+ flick("[initial_state]closing", src)
+ density = !density
+ opacity = !opacity
+ state_open = !state_open
+ addtimer(CALLBACK(src, PROC_REF(operate_update)), 1 SECONDS)
+
+/obj/structure/alien/resin/door/proc/operate_update()
+ air_update_turf(1)
+ update_icon(UPDATE_ICON_STATE)
+ is_operating = FALSE
+
+ if(state_open)
+ addtimer(CALLBACK(src, PROC_REF(mobless_try_to_operate)), close_delay)
+
+/obj/structure/alien/resin/door/update_icon_state()
+ icon_state = state_open ? "[initial_state]open" : initial_state
+
+/obj/structure/alien/resin/door/attack_alien(mob/living/carbon/alien/humanoid/user)
+ if(user.a_intent != INTENT_HARM)
+ try_to_operate(user)
+ return
+ to_chat(user, "We begin tearing down this resin structure.")
+ if(!do_after(user, 40, target = src) || QDELETED(src))
+ return
+ qdel(src)
+
+/obj/structure/alien/resin/door/CanPass(atom/movable/mover, turf/target)
+ if(iscarbon(mover))
+ var/mob/living/carbon/C = mover
+ if(C.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
+ return TRUE
+ if(iscarbon(mover.pulledby))
+ var/mob/living/carbon/L = mover.pulledby
+ if(L.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
+ return TRUE
+ return !density
/*
* Weeds
@@ -112,38 +243,91 @@
desc = "A thick resin surface covers the floor."
anchored = TRUE
density = FALSE
- layer = ABOVE_OPEN_TURF_LAYER
plane = FLOOR_PLANE
- icon = 'icons/obj/smooth_structures/alien/weeds1.dmi'
- icon_state = "weeds1"
- base_icon_state = "weeds1"
+ icon = 'icons/obj/smooth_structures/alien/weeds.dmi'
+ icon_state = "weeds"
+ base_icon_state = "weeds"
max_integrity = 15
+ layer = WIRE_TERMINAL_LAYER
smoothing_flags = SMOOTH_BITMASK
smoothing_groups = list(SMOOTH_GROUP_ALIEN_RESIN, SMOOTH_GROUP_ALIEN_WEEDS)
canSmoothWith = list(SMOOTH_GROUP_ALIEN_WEEDS, SMOOTH_GROUP_WALLS)
- transform = matrix(1, 0, -4, 0, 1, -4)
var/obj/structure/alien/weeds/node/linked_node = null
+ var/obj/structure/alien/wallweed/wall_weed // This var is used to handle wall-weed interactions for when they need to be deleted
var/static/list/weedImageCache
+ var/check_counter // This var is how many process() procs it takes for a weed to spread
-
-/obj/structure/alien/weeds/New(pos, node)
+/obj/structure/alien/weeds/Initialize(mapload, node)
..()
linked_node = node
if(isspaceturf(loc))
qdel(src)
return
- if(icon_state == "weeds")
- icon_state = pick("weeds", "weeds1", "weeds2")
- spawn(rand(150, 200))
- if(src)
- Life()
+ check_surroundings()
+ START_PROCESSING(SSobj, src)
/obj/structure/alien/weeds/Destroy()
+ STOP_PROCESSING(SSobj, src)
QUEUE_SMOOTH_NEIGHBORS(src)
+ playsound(loc, pick('sound/effects/alien_resin_break2.ogg','sound/effects/alien_resin_break1.ogg'), 50, FALSE)
linked_node = null
+ clear_wall_weed()
return ..()
-/obj/structure/alien/weeds/proc/Life()
+/obj/structure/alien/weeds/attack_alien(mob/living/carbon/alien/humanoid/user)
+ if(user.a_intent != INTENT_HARM)
+ return
+ return ..()
+
+/obj/structure/alien/weeds/process()
+ check_counter++
+ if(check_counter >= 5)
+ spread()
+ check_counter = 0
+
+/obj/structure/alien/weeds/proc/clear_wall_weed()
+ QDEL_NULL(wall_weed)
+
+/obj/structure/alien/weeds/proc/check_surroundings()
+ var/turf/T = get_turf(src)
+ var/list/nearby_dense_turfs = T.AdjacentTurfs(cardinal_only = FALSE, dense_only = TRUE)
+ if(!length(nearby_dense_turfs)) // There is no dense turfs around it
+ clear_wall_weed()
+ return
+
+ var/list/wall_dirs = list()
+ for(var/turf/W in nearby_dense_turfs)
+ if(iswallturf(W))
+ wall_dirs.Add(get_dir(W, T))
+ if(!length(wall_dirs)) // There is no walls around it
+ clear_wall_weed()
+ return
+
+ var/list/nearby_open_turfs = T.AdjacentTurfs(open_only = TRUE, cardinal_only = TRUE)
+
+ for(var/turf/W in nearby_open_turfs) // This handles removal of corner-weeds when they are to be replaced with a full side-weed instead
+ if(locate(/obj/structure/alien/weeds, W))
+ var/dirs = get_dir(W, T)
+ switch(dirs)
+ if(NORTH)
+ wall_dirs.Remove(NORTHEAST, NORTHWEST)
+ if(SOUTH)
+ wall_dirs.Remove(SOUTHEAST, SOUTHWEST)
+ if(EAST)
+ wall_dirs.Remove(NORTHEAST, SOUTHEAST)
+ if(WEST)
+ wall_dirs.Remove(NORTHWEST, SOUTHWEST)
+
+ if(!length(wall_dirs)) // No weeds will be applied, better off deleting it
+ clear_wall_weed()
+ return
+
+ if(!wall_weed || QDELETED(wall_weed))
+ wall_weed = new(get_turf(src))
+
+ wall_weed.compare_overlays(wall_dirs)
+
+/obj/structure/alien/weeds/proc/spread()
var/turf/U = get_turf(src)
if(isspaceturf(U))
@@ -154,29 +338,81 @@
return
for(var/turf/T in U.GetAtmosAdjacentTurfs())
-
if(locate(/obj/structure/alien/weeds) in T || isspaceturf(T))
continue
-
new /obj/structure/alien/weeds(T, linked_node)
+ check_surroundings()
/obj/structure/alien/weeds/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
if(exposed_temperature > 300)
take_damage(5, BURN, 0, 0)
-//Weed nodes
+/*
+ * Wall Weeds
+ */
+
+/obj/structure/alien/wallweed
+ name = "resin overgrowth"
+ desc = "A thick resin surface covers the wall."
+ icon = 'icons/obj/smooth_structures/alien/weeds.dmi'
+ icon_state = null
+ anchored = TRUE
+ layer = ABOVE_WINDOW_LAYER
+ plane = GAME_PLANE
+
+ max_integrity = 15
+ var/list/overlay_list = list()
+
+/obj/structure/alien/wallweed/Destroy()
+ playsound(loc, pick('sound/effects/alien_resin_break2.ogg','sound/effects/alien_resin_break1.ogg'), 50, FALSE)
+ return ..()
+
+/obj/structure/alien/wallweed/proc/compare_overlays(list/wall_dirs)
+ if(overlay_list != wall_dirs)
+ overlay_list = wall_dirs
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/structure/alien/wallweed/update_overlays()
+ . = ..()
+ if(!length(overlay_list))
+ return
+ for(var/dirs in overlay_list)
+ var/image/I = image(icon, icon_state = "wallweed-[dirs]")
+ switch(dirs)
+ if(NORTH, NORTHEAST, NORTHWEST)
+ I.pixel_y = -32
+ if(SOUTH, SOUTHEAST, SOUTHWEST)
+ I.pixel_y = 32
+ switch(dirs)
+ if(EAST, NORTHEAST, SOUTHEAST)
+ I.pixel_x = -32
+ if(WEST, NORTHWEST, SOUTHWEST)
+ I.pixel_x = 32
+ I.layer = BELOW_MOB_LAYER
+ . += I
+
+/obj/structure/alien/wallweed/attack_alien(mob/living/carbon/alien/humanoid/user)
+ if(user.a_intent != INTENT_HARM)
+ return
+ return ..()
+
+/*
+ * Weed nodes
+ */
+
/obj/structure/alien/weeds/node
- name = "glowing resin"
- desc = "Blue bioluminescence shines from beneath the surface."
- icon = 'icons/obj/smooth_structures/alien/weednode.dmi'
- icon_state = "weednode"
- base_icon_state = "weednode"
+ name = "resin node"
+ desc = "A large bulbous node pumping resin into the surface bellow it."
+ icon = 'icons/obj/smooth_structures/alien/weeds.dmi'
+ icon_state = "weeds"
+ base_icon_state = "weeds"
light_range = 1
var/node_range = NODERANGE
-/obj/structure/alien/weeds/node/New()
+/obj/structure/alien/weeds/node/Initialize()
+ add_overlay("weednode")
..(loc, src)
#undef NODERANGE
@@ -208,7 +444,7 @@
/*can be GROWING, GROWN or BURST; all mutually exclusive. GROWING has the egg in the grown state, and it will take 180-300 seconds for it to advance to the hatched state
*In the GROWN state, an alien egg can be destroyed or attacked by a xenomorph to force it to be burst, going near an egg in this state will also cause it to burst if you can be infected by a face hugger
*In the BURST/BURSTING state, the alien egg can be removed by being attacked by a alien or any other weapon
- **/
+ **/
var/status = GROWING
/obj/structure/alien/egg/grown
@@ -231,7 +467,7 @@
return attack_hand(user)
/obj/structure/alien/egg/attack_hand(mob/living/user)
- if(user.get_int_organ(/obj/item/organ/internal/xenos/plasmavessel))
+ if(user.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
switch(status)
if(BURST)
to_chat(user, "You clear the hatched egg.")
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index d664e0f3495..90a0e4e21c0 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -19,8 +19,8 @@
var/hardness = 1
var/sheetType = /obj/item/stack/sheet/metal
var/sheetAmount = 7
- var/openSound = 'sound/effects/stonedoor_openclose.ogg'
- var/closeSound = 'sound/effects/stonedoor_openclose.ogg'
+ var/open_sound = 'sound/effects/stonedoor_openclose.ogg'
+ var/close_sound = 'sound/effects/stonedoor_openclose.ogg'
var/damageSound = null
/obj/structure/mineral_door/Initialize()
@@ -82,15 +82,18 @@
/obj/structure/mineral_door/proc/operate()
is_operating = TRUE
if(!state_open)
- playsound(loc, openSound, 100, 1)
+ playsound(loc, open_sound, 100, TRUE)
flick("[initial_state]opening",src)
else
var/turf/T = get_turf(src)
for(var/mob/living/L in T)
+ is_operating = FALSE
return
- playsound(loc, closeSound, 100, 1)
+ playsound(loc, close_sound, 100, TRUE)
flick("[initial_state]closing",src)
- sleep(10)
+ addtimer(CALLBACK(src, PROC_REF(operate_update)), 1 SECONDS)
+
+/obj/structure/mineral_door/proc/operate_update()
density = !density
opacity = !opacity
state_open = !state_open
@@ -198,24 +201,10 @@
/obj/structure/mineral_door/wood
name = "wood door"
icon_state = "wood"
- openSound = 'sound/effects/doorcreaky.ogg'
- closeSound = 'sound/effects/doorcreaky.ogg'
+ open_sound = 'sound/effects/doorcreaky.ogg'
+ close_sound = 'sound/effects/doorcreaky.ogg'
sheetType = /obj/item/stack/sheet/wood
hardness = 1
resistance_flags = FLAMMABLE
max_integrity = 200
rad_insulation = RAD_VERY_LIGHT_INSULATION
-
-/obj/structure/mineral_door/resin
- name = "resin door"
- icon_state = "resin"
- hardness = 1.5
- close_delay = 100
- openSound = 'sound/effects/attackblob.ogg'
- closeSound = 'sound/effects/attackblob.ogg'
- damageSound = 'sound/effects/attackblob.ogg'
- sheetType = null
-
-/obj/structure/mineral_door/resin/try_to_operate(atom/user)
- if(isalien(user))
- return ..()
diff --git a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
index 80a3ab3b3d9..cc4ac4e012f 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm
@@ -14,12 +14,12 @@
. = ..()
nest_overlay = image('icons/mob/alien.dmi', "nestoverlay", layer=MOB_LAYER - 0.2)
-/obj/structure/bed/nest/user_unbuckle_mob(mob/living/user)
+/obj/structure/bed/nest/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
if(has_buckled_mobs())
for(var/buck in buckled_mobs) //breaking a nest releases all the buckled mobs, because the nest isn't holding them down anymore
var/mob/living/M = buck
- if(user.get_int_organ(/obj/item/organ/internal/xenos/plasmavessel))
+ if(user.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
unbuckle_mob(M)
add_fingerprint(user)
return
@@ -45,15 +45,16 @@
unbuckle_mob(M)
add_fingerprint(user)
-
/obj/structure/bed/nest/user_buckle_mob(mob/living/M, mob/living/user)
if (!ismob(M) || (get_dist(src, user) > 1) || (M.loc != loc) || user.incapacitated() || M.buckled)
return
- if(M.get_int_organ(/obj/item/organ/internal/xenos/plasmavessel))
+ if(M.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
+ to_chat(user, "[M]'s linkage with the hive prevents you from securing them into [src]")
return
- if(!user.get_int_organ(/obj/item/organ/internal/xenos/plasmavessel))
+ if(!user.get_int_organ(/obj/item/organ/internal/xenos/hivenode))
+ to_chat(user, "Your lack of linkage to the hive prevents you from buckling [M] into [src]")
return
if(has_buckled_mobs())
@@ -87,8 +88,10 @@
/obj/structure/bed/nest/attack_alien(mob/living/carbon/alien/user)
if(user.a_intent != INTENT_HARM)
return attack_hand(user)
- else
- return ..()
+ if(!do_after(user, 4 SECONDS, target = src) || QDELETED(src))
+ return
+ playsound(loc, pick('sound/effects/alien_resin_break2.ogg','sound/effects/alien_resin_break1.ogg'), 50, FALSE)
+ qdel(src)
/obj/structure/bed/nest/prevents_buckled_mobs_attacking()
return TRUE
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index c55913c0205..485e843e399 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -279,11 +279,16 @@
//update firedoor adjacency
var/list/turfs_to_check = get_adjacent_open_turfs(src) | src
- for(var/I in turfs_to_check)
- var/turf/T = I
+ for(var/turf/T in turfs_to_check)
for(var/obj/machinery/door/firedoor/FD in T)
FD.CalculateAffectingAreas()
+ // Check for weeds and either update, create or delete wall weeds
+ turfs_to_check = AdjacentTurfs(open_only = TRUE, cardinal_only = FALSE)
+ for(var/turf/T in turfs_to_check)
+ for(var/obj/structure/alien/weeds/W in T)
+ W.check_surroundings()
+
if(!keep_cabling && !can_have_cabling())
for(var/obj/structure/cable/C in contents)
qdel(C)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
index a62dc4be832..1593bab6d4d 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
@@ -28,9 +28,14 @@ Doesn't work on other aliens/AI.*/
return
if(powerc(50,1))
+ for(var/obj/structure/alien/resin in get_turf(src))
+ to_chat(src, "There is already a resin construction here.")
+ return
adjustPlasma(-50)
for(var/mob/O in viewers(src, null))
O.show_message(text("[src] has planted some alien weeds!"), 1)
+ for(var/obj/structure/alien/weeds/W in get_turf(src))
+ qdel(W)
new /obj/structure/alien/weeds/node(loc)
return
@@ -114,29 +119,39 @@ Doesn't work on other aliens/AI.*/
return
/mob/living/carbon/alien/humanoid/proc/resin() // -- TLE
- set name = "Secrete Resin (55)"
+ set name = "Secrete Resin"
set desc = "Secrete tough malleable resin."
set category = "Alien"
+ var/list/resin_buildings = list("Resin Wall (55)" = image(icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi', icon_state = "resin_wall-0"),
+ "Resin Nest (55)" = image(icon = 'icons/mob/alien.dmi', icon_state = "nest"),
+ "Resin Door (80)" = image(icon = 'icons/obj/smooth_structures/alien/resin_door.dmi', icon_state = "resin"))
+ var/choice = show_radial_menu(src, src, resin_buildings, src, radius = 40)
if(powerc(55, TRUE))
- var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist
-
- if(!choice || !powerc(55, TRUE))
- return
- var/obj/structure/alien/resin/T = locate() in get_turf(src)
- if(T)
+ var/built = FALSE
+ if(locate(/obj/structure/alien/resin) in get_turf(src))
to_chat(src, "There is already a resin construction here.")
return
adjustPlasma(-55)
- for(var/mob/O in viewers(src, null))
- O.show_message(text("[src] vomits up a thick purple substance and shapes it!"), 1)
+
switch(choice)
- if("resin wall")
+ if("Resin Wall (55)")
new /obj/structure/alien/resin/wall(loc)
- if("resin membrane")
- new /obj/structure/alien/resin/membrane(loc)
- if("resin nest")
+ built = TRUE
+ if("Resin Nest (55)")
new /obj/structure/bed/nest(loc)
+ built = TRUE
+ if("Resin Door (80)")
+ if(powerc(25, TRUE))
+ var/obj/structure/alien/resin/door/door = new(loc)
+ door.dir = dir
+ adjustPlasma(-25)
+ built = TRUE
+ else
+ to_chat(src, "Not enough plasma stored.")
+ adjustPlasma(55)
+ if(built)
+ visible_message("[src] vomits up a thick purple substance and shapes it!")
return
/mob/living/carbon/alien/humanoid/verb/regurgitate()
diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm
index 6b53be110cc..093d279908d 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm
@@ -15,14 +15,15 @@
alien_slash_damage = 30 //Queens do higher slashing damage to people
alien_movement_delay = 1 //This represents a movement delay of 1, or roughly 80% the movement speed of a normal carbon mob
-
/mob/living/carbon/alien/humanoid/queen/Initialize(mapload)
. = ..()
//there should only be one queen
for(var/mob/living/carbon/alien/humanoid/queen/Q in GLOB.alive_mob_list)
if(Q == src)
+ ADD_TRAIT(Q, TRAIT_FORCE_DOORS, VAMPIRE_TRAIT)
continue
if(Q.stat == DEAD)
+ ADD_TRAIT(Q, TRAIT_FORCE_DOORS, VAMPIRE_TRAIT)
continue
if(Q.client)
name = "alien princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it.
diff --git a/icons/mob/alien.dmi b/icons/mob/alien.dmi
index 74154047ccc..15631f719db 100644
Binary files a/icons/mob/alien.dmi and b/icons/mob/alien.dmi differ
diff --git a/icons/obj/doors/mineral_doors.dmi b/icons/obj/doors/mineral_doors.dmi
index 56d5a32bc59..eb5b7100809 100644
Binary files a/icons/obj/doors/mineral_doors.dmi and b/icons/obj/doors/mineral_doors.dmi differ
diff --git a/icons/obj/smooth_structures/alien/nest.dmi b/icons/obj/smooth_structures/alien/nest.dmi
deleted file mode 100644
index 6de377886f9..00000000000
Binary files a/icons/obj/smooth_structures/alien/nest.dmi and /dev/null differ
diff --git a/icons/obj/smooth_structures/alien/resin_door.dmi b/icons/obj/smooth_structures/alien/resin_door.dmi
new file mode 100644
index 00000000000..3d54a2ceb07
Binary files /dev/null and b/icons/obj/smooth_structures/alien/resin_door.dmi differ
diff --git a/icons/obj/smooth_structures/alien/resin_membrane.dmi b/icons/obj/smooth_structures/alien/resin_membrane.dmi
deleted file mode 100644
index 1ea306eaa66..00000000000
Binary files a/icons/obj/smooth_structures/alien/resin_membrane.dmi and /dev/null differ
diff --git a/icons/obj/smooth_structures/alien/resin_wall.dmi b/icons/obj/smooth_structures/alien/resin_wall.dmi
index 7d837172b8c..9ceb50e935d 100644
Binary files a/icons/obj/smooth_structures/alien/resin_wall.dmi and b/icons/obj/smooth_structures/alien/resin_wall.dmi differ
diff --git a/icons/obj/smooth_structures/alien/weednode.dmi b/icons/obj/smooth_structures/alien/weednode.dmi
deleted file mode 100644
index 888fce62ad1..00000000000
Binary files a/icons/obj/smooth_structures/alien/weednode.dmi and /dev/null differ
diff --git a/icons/obj/smooth_structures/alien/weeds.dmi b/icons/obj/smooth_structures/alien/weeds.dmi
new file mode 100644
index 00000000000..17131956916
Binary files /dev/null and b/icons/obj/smooth_structures/alien/weeds.dmi differ
diff --git a/icons/obj/smooth_structures/alien/weeds1.dmi b/icons/obj/smooth_structures/alien/weeds1.dmi
deleted file mode 100644
index e9022e89414..00000000000
Binary files a/icons/obj/smooth_structures/alien/weeds1.dmi and /dev/null differ
diff --git a/icons/obj/smooth_structures/alien/weeds2.dmi b/icons/obj/smooth_structures/alien/weeds2.dmi
deleted file mode 100644
index 13207496e1c..00000000000
Binary files a/icons/obj/smooth_structures/alien/weeds2.dmi and /dev/null differ
diff --git a/icons/obj/smooth_structures/alien/weeds3.dmi b/icons/obj/smooth_structures/alien/weeds3.dmi
deleted file mode 100644
index 2ed86420b4d..00000000000
Binary files a/icons/obj/smooth_structures/alien/weeds3.dmi and /dev/null differ
diff --git a/sound/effects/alien_resin_break1.ogg b/sound/effects/alien_resin_break1.ogg
new file mode 100644
index 00000000000..bf2cd2053a7
Binary files /dev/null and b/sound/effects/alien_resin_break1.ogg differ
diff --git a/sound/effects/alien_resin_break2.ogg b/sound/effects/alien_resin_break2.ogg
new file mode 100644
index 00000000000..57e13bfc943
Binary files /dev/null and b/sound/effects/alien_resin_break2.ogg differ
diff --git a/sound/machines/alien_airlock.ogg b/sound/machines/alien_airlock.ogg
new file mode 100644
index 00000000000..078af38d077
Binary files /dev/null and b/sound/machines/alien_airlock.ogg differ