diff --git a/_maps/shuttles/fluffy/whiteship_xeno.dmm b/_maps/shuttles/fluffy/whiteship_xeno.dmm
new file mode 100644
index 00000000000..8c05ddb0f50
--- /dev/null
+++ b/_maps/shuttles/fluffy/whiteship_xeno.dmm
@@ -0,0 +1,1468 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"bl" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/portable_atmospherics/scrubber,
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"bF" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/box/corners{
+ dir = 8
+ },
+/obj/effect/turf_decal/box/corners{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/general/visible,
+/obj/structure/alien/weeds,
+/obj/structure/bed/nest,
+/obj/effect/mob_spawn/corpse/human/damaged,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"cD" = (
+/obj/structure/grille/broken,
+/obj/effect/decal/cleanable/glass/titanium,
+/obj/structure/alien/weeds,
+/obj/structure/alien/resin/membrane,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"cM" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"dP" = (
+/obj/effect/turf_decal/stripes/line,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/unary/portables_connector{
+ dir = 1
+ },
+/obj/machinery/power/apc/auto_name/directional/south,
+/obj/machinery/portable_atmospherics/canister/air,
+/obj/structure/cable,
+/obj/effect/mapping_helpers/apc/no_charge,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"eD" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/binary/valve,
+/obj/structure/alien/weeds,
+/obj/effect/decal/cleanable/blood/gibs,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"eE" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/effect/decal/cleanable/blood/gibs/old,
+/obj/machinery/power/apc/auto_name/directional/east,
+/obj/structure/cable,
+/obj/effect/turf_decal/tile/bar{
+ dir = 1
+ },
+/obj/effect/mapping_helpers/apc/no_charge,
+/turf/open/floor/iron/white/corner{
+ dir = 4
+ },
+/area/shuttle/abandoned/bar)
+"eT" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/reagent_dispensers/watertank,
+/obj/item/reagent_containers/cup/bucket,
+/obj/item/mop,
+/obj/item/storage/bag/trash{
+ pixel_x = 6
+ },
+/obj/effect/decal/cleanable/blood/old,
+/obj/effect/turf_decal/delivery,
+/obj/effect/turf_decal/stripes/line{
+ dir = 10
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"fL" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/corner{
+ dir = 1
+ },
+/obj/structure/extinguisher_cabinet/directional/north,
+/obj/structure/closet/crate/bin,
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 8
+ },
+/obj/item/organ/stomach,
+/obj/item/trash/syndi_cakes,
+/obj/effect/turf_decal/tile/bar{
+ dir = 1
+ },
+/turf/open/floor/iron/white/corner{
+ dir = 4
+ },
+/area/shuttle/abandoned/bar)
+"gk" = (
+/turf/closed/wall/mineral/titanium/nodiagonal,
+/area/shuttle/abandoned/bar)
+"gA" = (
+/obj/effect/turf_decal/stripes/corner{
+ dir = 4
+ },
+/obj/machinery/light/cold/no_nightlight/directional/south,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/blood/gibs/robot_debris/down,
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"gL" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/structure/cable,
+/obj/effect/decal/cleanable/blood/splatter,
+/obj/effect/spawner/random/armory/e_gun,
+/obj/structure/alien/weeds,
+/turf/open/floor/pod/light,
+/area/shuttle/abandoned/crew)
+"hN" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/greenglow,
+/obj/machinery/light/small/red/directional/west,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/bar)
+"id" = (
+/turf/closed/wall/mineral/titanium/nodiagonal,
+/area/shuttle/abandoned/crew)
+"ie" = (
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/storage/belt/utility{
+ pixel_y = 9
+ },
+/obj/item/screwdriver,
+/obj/effect/turf_decal/trimline/brown/corner{
+ dir = 4
+ },
+/obj/effect/turf_decal/trimline/brown/warning{
+ dir = 10
+ },
+/turf/open/floor/pod/dark,
+/area/shuttle/abandoned/engine)
+"ig" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes{
+ dir = 8
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/effect/decal/cleanable/blood/gibs/old,
+/obj/structure/cable,
+/obj/machinery/airalarm/directional/south,
+/obj/effect/mapping_helpers/airalarm/all_access,
+/obj/effect/turf_decal/tile/bar{
+ dir = 1
+ },
+/turf/open/floor/iron/white/corner{
+ dir = 8
+ },
+/area/shuttle/abandoned/bar)
+"ik" = (
+/obj/effect/turf_decal/delivery,
+/obj/machinery/door/airlock/external/ruin{
+ id_tag = "ntms_exterior";
+ name = "NTMS-037 Mining Airlock"
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{
+ cycle_id = "exterior_whiteship"
+ },
+/obj/effect/mapping_helpers/airlock/locked,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/bar)
+"iI" = (
+/obj/effect/spawner/structure/window/reinforced/shuttle,
+/obj/machinery/door/poddoor/shutters{
+ id = "whiteship_bridge";
+ name = "Cockpit Emergency Blast Door"
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/bridge)
+"jr" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/machinery/power/shuttle_engine/propulsion/left{
+ dir = 8
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/abandoned/engine)
+"jM" = (
+/obj/structure/table,
+/obj/machinery/microwave{
+ pixel_y = 5
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/siding/thinplating_new{
+ dir = 6
+ },
+/obj/effect/turf_decal/tile/bar/opposingcorners,
+/turf/open/floor/iron/cafeteria{
+ dir = 1
+ },
+/area/shuttle/abandoned/bar)
+"kq" = (
+/obj/structure/rack,
+/obj/effect/turf_decal/bot,
+/obj/effect/spawner/random/maintenance/three,
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"ku" = (
+/obj/machinery/door/airlock/external/ruin{
+ name = "External Freight Airlock"
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/turf_decal/stripes/line,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/general/visible,
+/obj/docking_port/mobile{
+ callTime = 250;
+ can_move_docking_ports = 1;
+ dir = 2;
+ shuttle_id = "xenohijack";
+ launch_status = 0;
+ movement_force = list("KNOCKDOWN"=0,"THROW"=0);
+ name = "Mining Shuttle";
+ port_direction = 8;
+ preferred_direction = 4
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"kG" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/bot,
+/obj/structure/alien/weeds,
+/obj/structure/ore_box,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"kY" = (
+/obj/item/chair,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/greenglow,
+/turf/open/floor/bamboo,
+/area/shuttle/abandoned/bar)
+"lg" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes{
+ dir = 9
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/effect/decal/cleanable/blood/footprints{
+ dir = 1
+ },
+/obj/structure/cable,
+/obj/effect/turf_decal/tile/bar{
+ dir = 1
+ },
+/turf/open/floor/iron/cafeteria{
+ dir = 1
+ },
+/area/shuttle/abandoned/bar)
+"mt" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/obj/machinery/button/door/directional/east{
+ id = "ntms_exterior";
+ name = "NTMS-037 Mining Airlock Bolt Control";
+ normaldoorcontrol = 1;
+ specialfunctions = 4
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/bar)
+"mu" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/effect/decal/cleanable/vomit/old,
+/obj/machinery/light/small/broken/directional/west,
+/obj/structure/cable,
+/obj/machinery/airalarm/directional/west,
+/obj/effect/mapping_helpers/airalarm/all_access,
+/obj/effect/mob_spawn/corpse/human/damaged,
+/obj/structure/alien/weeds,
+/turf/open/floor/pod/light,
+/area/shuttle/abandoned/crew)
+"mH" = (
+/obj/effect/turf_decal/stripes{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/corner,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/machinery/power/apc/auto_name/directional/south,
+/obj/effect/decal/cleanable/glass,
+/obj/structure/cable,
+/obj/effect/decal/cleanable/blood/splatter,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/bridge)
+"mX" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/machinery/power/shuttle_engine/propulsion{
+ dir = 8
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/abandoned/engine)
+"nt" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/glass,
+/obj/structure/alien/weeds,
+/obj/effect/decal/cleanable/blood/gibs,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"nN" = (
+/obj/machinery/door/airlock/command{
+ name = "NTMS-037 Ship Control"
+ },
+/obj/effect/turf_decal/delivery/white{
+ color = "#52B4E9"
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/structure/cable,
+/turf/open/floor/mineral/titanium/tiled/white,
+/area/shuttle/abandoned/bridge)
+"oQ" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/machinery/power/shuttle_engine/propulsion/right{
+ dir = 8
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/abandoned/bar)
+"pI" = (
+/obj/effect/turf_decal/delivery,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/general/visible,
+/obj/machinery/door/airlock/shuttle{
+ name = "NTMS-037 Cargo Bay"
+ },
+/obj/effect/mapping_helpers/airlock/abandoned,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/engine)
+"pV" = (
+/obj/effect/turf_decal/delivery,
+/obj/machinery/suit_storage_unit,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/engine)
+"qu" = (
+/obj/effect/turf_decal/trimline/white/warning,
+/obj/effect/turf_decal/trimline/white/filled/warning{
+ dir = 1
+ },
+/obj/structure/chair/office/light{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/blood,
+/obj/item/paper/crumpled/bloody{
+ default_raw_text = "We struck gold, literally. We found some good rocks out near Centurai-II rich with the stuff. Kae said he and Milos found something out while prospecting, some sort of glowing cube. It's jammed in there good, so we're anchoring until we sort this out...";
+ pixel_x = 4;
+ pixel_y = 4
+ },
+/obj/machinery/atmospherics/components/unary/vent_pump/on,
+/turf/open/floor/pod/light,
+/area/shuttle/abandoned/bridge)
+"qL" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/blood/gibs/robot_debris,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"ry" = (
+/obj/effect/spawner/structure/window/reinforced/shuttle{
+ name = "Exterior Window Blast Door"
+ },
+/obj/effect/mapping_helpers/damaged_window,
+/obj/machinery/door/poddoor/shutters/preopen{
+ id = "whiteship_windows"
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"rC" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/machinery/power/shuttle_engine/propulsion/right{
+ dir = 8
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/abandoned/engine)
+"rX" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/structure/cable,
+/obj/effect/decal/cleanable/glass,
+/turf/open/floor/iron,
+/area/shuttle/abandoned/bar)
+"sz" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/chair{
+ dir = 4
+ },
+/turf/open/floor/bamboo,
+/area/shuttle/abandoned/bar)
+"sB" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/effect/turf_decal/stripes/corner,
+/obj/structure/cable,
+/obj/machinery/power/apc/auto_name/directional/south,
+/obj/effect/mapping_helpers/apc/no_charge,
+/obj/structure/alien/weeds/node,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"tf" = (
+/obj/machinery/atmospherics/components/tank/air,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"tk" = (
+/obj/effect/turf_decal/stripes/end{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/blood/xeno,
+/turf/open/floor/mineral/titanium/tiled/yellow,
+/area/shuttle/abandoned/engine)
+"tz" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/delivery,
+/obj/structure/alien/weeds,
+/obj/structure/closet/crate/trashcart/filled,
+/obj/item/bikehorn/rubberducky,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/cargo)
+"uf" = (
+/obj/effect/turf_decal/trimline/white/corner{
+ dir = 8
+ },
+/obj/effect/turf_decal/trimline/white/filled/warning{
+ dir = 5
+ },
+/obj/machinery/computer/shuttle/white_ship/bridge{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/cobweb/cobweb2,
+/obj/machinery/light/small/blacklight/directional/east,
+/turf/open/floor/pod/light,
+/area/shuttle/abandoned/bridge)
+"uA" = (
+/turf/closed/wall/mineral/titanium,
+/area/shuttle/abandoned/crew)
+"vk" = (
+/turf/closed/wall/mineral/titanium,
+/area/shuttle/abandoned/cargo)
+"vM" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/box/corners{
+ dir = 4
+ },
+/obj/effect/turf_decal/box/corners,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/general/visible,
+/obj/structure/alien/weeds,
+/obj/structure/bed/nest,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"xh" = (
+/turf/closed/wall/mineral/titanium/nodiagonal,
+/area/shuttle/abandoned/cargo)
+"yj" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/structure/cable,
+/obj/effect/decal/cleanable/blood/trail,
+/obj/effect/decal/cleanable/glass/titanium,
+/obj/structure/alien/weeds/node,
+/mob/living/carbon/alien/adult/tgmc/drone,
+/turf/open/floor/pod/light,
+/area/shuttle/abandoned/crew)
+"yG" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
+ dir = 4
+ },
+/obj/effect/turf_decal/stripes/line,
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"zl" = (
+/obj/effect/turf_decal/trimline/white/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/trimline/white/filled/warning{
+ dir = 4
+ },
+/obj/effect/turf_decal/stripes/corner{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/frame/computer{
+ anchored = 1;
+ dir = 8
+ },
+/obj/item/shard{
+ icon_state = "medium"
+ },
+/obj/item/stack/cable_coil/cut,
+/obj/machinery/airalarm/directional/south,
+/obj/effect/mapping_helpers/airalarm/all_access,
+/turf/open/floor/pod/light,
+/area/shuttle/abandoned/bridge)
+"zu" = (
+/obj/machinery/cell_charger,
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/stock_parts/power_store/cell/emproof/empty{
+ pixel_y = 7;
+ pixel_x = 5
+ },
+/obj/effect/turf_decal/tile/brown,
+/obj/structure/alien/weeds,
+/turf/open/floor/iron/white/corner{
+ dir = 8
+ },
+/area/shuttle/abandoned/cargo)
+"zJ" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/item/cigbutt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/effect/decal/cleanable/blood/footprints{
+ dir = 8
+ },
+/obj/structure/cable,
+/turf/open/floor/iron,
+/area/shuttle/abandoned/bar)
+"Am" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/delivery,
+/obj/structure/alien/weeds,
+/obj/structure/closet/crate/secure/weapon,
+/obj/item/gun/energy/laser/retro,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/cargo)
+"Bk" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/general/visible,
+/obj/structure/alien/weeds/node,
+/mob/living/carbon/alien/larva/tgmc,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"BL" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/corner{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/blood,
+/obj/machinery/airalarm/directional/west,
+/obj/effect/mapping_helpers/airalarm/all_access,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"BS" = (
+/turf/closed/wall/mineral/plastitanium,
+/area/shuttle/abandoned/bar)
+"CG" = (
+/turf/closed/wall/mineral/plastitanium/nodiagonal,
+/area/shuttle/abandoned/engine)
+"CQ" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/general/visible,
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/greenglow,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"Fr" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/effect/decal/cleanable/blood/footprints{
+ dir = 8
+ },
+/obj/structure/cable,
+/obj/effect/decal/cleanable/blood/old,
+/turf/open/floor/iron,
+/area/shuttle/abandoned/bar)
+"FW" = (
+/obj/effect/spawner/structure/window/reinforced/shuttle,
+/obj/machinery/door/poddoor/shutters{
+ id = "whiteship_windows";
+ name = "Exterior Window Blast Door"
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/crew)
+"Gj" = (
+/obj/effect/spawner/structure/window/reinforced/shuttle,
+/obj/machinery/door/poddoor/shutters{
+ id = "whiteship_windows";
+ name = "Exterior Window Blast Door"
+ },
+/obj/effect/decal/cleanable/blood/splatter/over_window,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"Gu" = (
+/turf/template_noop,
+/area/template_noop)
+"Gz" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/bot_white,
+/obj/machinery/door/poddoor{
+ id = "whiteship_port";
+ name = "NTMS-037 Bay Blast Door"
+ },
+/obj/machinery/conveyor{
+ id = "NTMSLoad2";
+ name = "on ramp"
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"GW" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/trimline/brown/filled/shrink_cw{
+ dir = 4
+ },
+/obj/effect/turf_decal/trimline/brown/warning{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/cobweb/cobweb2,
+/obj/structure/closet/crate/internals,
+/obj/item/tank/internals/emergency_oxygen/engi{
+ pixel_x = 5
+ },
+/obj/item/tank/internals/emergency_oxygen/engi,
+/turf/open/floor/pod/dark,
+/area/shuttle/abandoned/engine)
+"HD" = (
+/obj/effect/turf_decal/siding/thinplating_new/dark{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/spawner/random/clothing/wardrobe_closet_colored,
+/obj/machinery/power/apc/auto_name/directional/south,
+/obj/structure/cable,
+/obj/effect/mapping_helpers/apc/no_charge,
+/obj/structure/alien/weeds,
+/turf/open/floor/iron/freezer,
+/area/shuttle/abandoned/crew)
+"In" = (
+/obj/effect/turf_decal/stripes/corner{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/corner{
+ dir = 1
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/blood/tracks,
+/obj/structure/cable,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/mob_spawn/corpse/human/engineer,
+/turf/open/floor/mineral/titanium/tiled/yellow,
+/area/shuttle/abandoned/engine)
+"IX" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/obj/machinery/atmospherics/components/binary/pump/off{
+ dir = 8;
+ name = "Dock to Air"
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable,
+/obj/machinery/power/terminal,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"Jd" = (
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/storage/box/gum/happiness,
+/obj/item/stack/cable_coil/five,
+/obj/effect/turf_decal/tile/brown,
+/obj/structure/alien/weeds,
+/turf/open/floor/iron/white/corner{
+ dir = 8
+ },
+/area/shuttle/abandoned/cargo)
+"JG" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/greenglow,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"JL" = (
+/obj/structure/closet/secure_closet/freezer{
+ locked = 0;
+ name = "fridge"
+ },
+/obj/item/food/sausage,
+/obj/item/reagent_containers/cup/glass/bottle/beer,
+/obj/item/food/sandwich,
+/obj/effect/turf_decal/siding/thinplating_new{
+ dir = 10
+ },
+/obj/machinery/light/warm/no_nightlight/directional/north,
+/obj/item/food/grown/potato,
+/obj/effect/turf_decal/tile/bar/opposingcorners,
+/turf/open/floor/iron/cafeteria{
+ dir = 1
+ },
+/area/shuttle/abandoned/bar)
+"JX" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 6
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable,
+/obj/machinery/power/smes/engineering,
+/obj/effect/mapping_helpers/broken_machine,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"Kx" = (
+/obj/effect/spawner/structure/window/reinforced/shuttle,
+/obj/machinery/door/poddoor/shutters{
+ id = "whiteship_windows";
+ name = "Exterior Window Blast Door"
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/bar)
+"KS" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/corner{
+ dir = 1
+ },
+/obj/effect/turf_decal/stripes/corner,
+/obj/effect/decal/cleanable/cobweb{
+ icon_state = "cobweb2"
+ },
+/obj/structure/sign/warning/vacuum/external/directional/north,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"Lj" = (
+/obj/effect/turf_decal/delivery,
+/obj/machinery/door/airlock/external/ruin{
+ name = "NTMS-037 Mining Airlock"
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{
+ cycle_id = "exterior_whiteship"
+ },
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/bar)
+"LE" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/unary/vent_pump/on,
+/obj/structure/closet/crate/cardboard,
+/obj/machinery/light/cold/no_nightlight/directional/north,
+/obj/item/storage/box/lights/mixed{
+ pixel_y = 5
+ },
+/obj/effect/spawner/random/maintenance/three,
+/obj/item/wirebrush,
+/obj/item/stack/sheet/mineral/plasma/five,
+/obj/item/stack/sheet/mineral/plasma/five,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"LK" = (
+/obj/effect/spawner/structure/window/reinforced/shuttle,
+/obj/machinery/door/poddoor/shutters{
+ id = "whiteship_windows";
+ name = "Exterior Window Blast Door"
+ },
+/obj/effect/decal/cleanable/blood/splatter/over_window,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/bar)
+"Ml" = (
+/obj/effect/turf_decal/delivery,
+/obj/machinery/suit_storage_unit/standard_unit{
+ desc = "An industrial suit storage device carrying retro space suits. Neat!";
+ helmet_type = /obj/item/clothing/head/helmet/space;
+ suit_type = /obj/item/clothing/suit/space
+ },
+/obj/machinery/light/warm/no_nightlight/directional/south,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/engine)
+"Mt" = (
+/obj/effect/turf_decal/stripes,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/blood/splatter,
+/obj/structure/cable,
+/mob/living/carbon/alien/adult/tgmc/drone,
+/turf/open/floor/mineral/titanium/tiled/yellow,
+/area/shuttle/abandoned/engine)
+"MI" = (
+/obj/machinery/power/shuttle_engine/heater{
+ dir = 8
+ },
+/obj/structure/window/reinforced/spawner/directional/east,
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/abandoned/engine)
+"Nh" = (
+/turf/closed/wall/mineral/plastitanium,
+/area/shuttle/abandoned/engine)
+"Nt" = (
+/obj/effect/turf_decal/bot,
+/obj/machinery/atmospherics/components/unary/portables_connector{
+ dir = 1
+ },
+/obj/machinery/portable_atmospherics/canister,
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"NV" = (
+/turf/closed/wall/mineral/titanium/nodiagonal,
+/area/shuttle/abandoned/bridge)
+"Of" = (
+/turf/closed/wall/mineral/plastitanium/nodiagonal,
+/area/shuttle/abandoned/bar)
+"OS" = (
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/reagent_containers/cup/glass/drinkingglass/filled/cola{
+ pixel_y = 5;
+ pixel_x = 8
+ },
+/obj/item/plate/small{
+ pixel_x = -5
+ },
+/obj/item/storage/box/donkpockets,
+/turf/open/floor/bamboo,
+/area/shuttle/abandoned/bar)
+"OZ" = (
+/obj/machinery/power/shuttle_engine/heater{
+ dir = 8
+ },
+/obj/structure/window/reinforced/spawner/directional/east,
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/abandoned/bar)
+"Pe" = (
+/obj/machinery/button/door/directional/north{
+ id = "whiteship_port";
+ name = "Cargo Bay Control"
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/line{
+ dir = 9
+ },
+/obj/effect/decal/cleanable/insectguts,
+/obj/structure/extinguisher_cabinet/directional/west,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"Pz" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/machinery/power/shuttle_engine/propulsion/left{
+ dir = 8
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/abandoned/bar)
+"PR" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
+ dir = 4
+ },
+/obj/effect/turf_decal/stripes/end{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/blood/tracks,
+/obj/structure/cable,
+/obj/item/weldingtool/largetank,
+/turf/open/floor/mineral/titanium/tiled/yellow,
+/area/shuttle/abandoned/engine)
+"Qm" = (
+/obj/effect/turf_decal/stripes{
+ dir = 10
+ },
+/obj/effect/turf_decal/stripes/corner{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/blood/gibs/core,
+/obj/structure/cable,
+/turf/open/floor/mineral/titanium/tiled/yellow,
+/area/shuttle/abandoned/engine)
+"QR" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/structure/cable,
+/turf/open/floor/iron,
+/area/shuttle/abandoned/bar)
+"Rr" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/bot_white,
+/obj/machinery/door/poddoor{
+ id = "whiteship_port";
+ name = "NTMS-037 Bay Blast Door"
+ },
+/obj/machinery/conveyor{
+ dir = 1;
+ id = "NTMSLoad";
+ name = "off ramp"
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"RF" = (
+/obj/effect/turf_decal/delivery,
+/obj/machinery/door/airlock/shuttle{
+ name = "NTMS-037 Lockers"
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/structure/cable,
+/obj/effect/mapping_helpers/airlock/abandoned,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/crew)
+"RI" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/blood/oil,
+/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"RN" = (
+/obj/effect/turf_decal/delivery,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/structure/cable,
+/obj/effect/decal/cleanable/glass/titanium,
+/obj/structure/alien/weeds,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/crew)
+"Ss" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/reagent_dispensers/fueltank,
+/obj/effect/turf_decal/delivery/red,
+/obj/effect/turf_decal/stripes/line{
+ dir = 9
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"SL" = (
+/turf/closed/wall/mineral/titanium/nodiagonal,
+/area/shuttle/abandoned/engine)
+"SM" = (
+/obj/machinery/door/airlock/command{
+ name = "NTMS-037 Ship Control"
+ },
+/obj/effect/turf_decal/delivery/white{
+ color = "#52B4E9"
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/structure/cable,
+/obj/effect/mapping_helpers/airlock/abandoned,
+/turf/open/floor/mineral/titanium/tiled/white,
+/area/shuttle/abandoned/bridge)
+"Ta" = (
+/obj/effect/turf_decal/trimline/white/line,
+/obj/effect/turf_decal/trimline/white/filled/warning{
+ dir = 1
+ },
+/obj/machinery/computer/camera_advanced/shuttle_docker/whiteship{
+ dir = 4;
+ view_range = 14;
+ y_offset = 5;
+ x_offset = 0
+ },
+/obj/effect/turf_decal/stripes/corner{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/button/door{
+ id = "whiteship_windows";
+ name = "NTMS-037 Windows Blast Door Control";
+ pixel_x = -24;
+ pixel_y = 6
+ },
+/obj/machinery/button/door{
+ id = "whiteship_bridge";
+ name = "NTMS-037 Bridge Blast Door Control";
+ pixel_x = -24;
+ pixel_y = -6
+ },
+/turf/open/floor/pod/light,
+/area/shuttle/abandoned/bridge)
+"Tf" = (
+/obj/structure/table,
+/obj/effect/turf_decal/trimline/brown/filled/shrink_ccw{
+ dir = 1
+ },
+/obj/effect/turf_decal/trimline/brown/warning,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/megaphone{
+ pixel_x = 4;
+ pixel_y = 4
+ },
+/obj/item/storage/box/stockparts/basic{
+ pixel_y = 6
+ },
+/obj/machinery/airalarm/directional/north,
+/obj/effect/mapping_helpers/airalarm/all_access,
+/turf/open/floor/pod/dark,
+/area/shuttle/abandoned/engine)
+"Tg" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/effect/turf_decal/stripes/line,
+/obj/structure/cable,
+/obj/effect/decal/cleanable/blood/splatter/xeno,
+/obj/structure/alien/weeds,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"TP" = (
+/obj/structure/closet/secure_closet/personal,
+/obj/effect/turf_decal/siding/thinplating_new/dark{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/alien/weeds,
+/turf/open/floor/iron/freezer,
+/area/shuttle/abandoned/crew)
+"VP" = (
+/obj/effect/turf_decal/stripes/end{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable,
+/turf/open/floor/mineral/titanium/tiled/yellow,
+/area/shuttle/abandoned/engine)
+"Wj" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/blood/xeno,
+/obj/structure/alien/weeds,
+/obj/item/clothing/mask/facehugger/impregnated,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/cargo)
+"Xe" = (
+/obj/structure/reagent_dispensers/water_cooler,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/iron,
+/area/shuttle/abandoned/bar)
+"Xk" = (
+/turf/closed/wall/mineral/titanium,
+/area/shuttle/abandoned/bar)
+"XL" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
+ dir = 4
+ },
+/obj/machinery/door/airlock/shuttle{
+ name = "NTMS-037 Engine Room"
+ },
+/obj/structure/cable,
+/obj/effect/turf_decal/delivery,
+/obj/effect/mapping_helpers/airlock/welded,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/engine)
+"XP" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable,
+/obj/effect/turf_decal/bot,
+/obj/effect/turf_decal/stripes/line{
+ dir = 5
+ },
+/obj/machinery/power/port_gen/pacman,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"Yh" = (
+/obj/machinery/door/window/survival_pod/left/directional/east,
+/obj/effect/turf_decal/stripes{
+ dir = 4
+ },
+/obj/structure/bed/pod{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/item/bedsheet/captain{
+ dir = 4
+ },
+/turf/open/floor/wood/tile,
+/area/shuttle/abandoned/crew)
+"YM" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/item/storage/toolbox/mechanical,
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"YN" = (
+/obj/effect/spawner/structure/window/reinforced/shuttle,
+/obj/machinery/door/poddoor/shutters{
+ id = "whiteship_windows";
+ name = "Exterior Window Blast Door"
+ },
+/turf/open/floor/plating,
+/area/shuttle/abandoned/engine)
+"YU" = (
+/obj/effect/turf_decal/stripes{
+ dir = 4
+ },
+/obj/structure/bed/pod{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/cobweb,
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/glass/titanium,
+/obj/structure/alien/weeds,
+/obj/item/stack/sheet/cloth,
+/turf/open/floor/wood/tile,
+/area/shuttle/abandoned/crew)
+"YV" = (
+/obj/effect/turf_decal/stripes,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/obj/effect/decal/cleanable/ash,
+/obj/structure/cable,
+/obj/effect/decal/cleanable/blood/xeno,
+/turf/open/floor/mineral/plastitanium,
+/area/shuttle/abandoned/bridge)
+"ZW" = (
+/obj/machinery/washing_machine,
+/obj/effect/turf_decal/siding/thinplating_new/dark{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/alien/weeds,
+/turf/open/floor/iron/freezer,
+/area/shuttle/abandoned/crew)
+
+(1,1,1) = {"
+Nh
+jr
+mX
+rC
+Nh
+Gu
+Gu
+Gu
+Gu
+Gu
+Gu
+Gu
+Gu
+"}
+(2,1,1) = {"
+Nh
+MI
+MI
+MI
+CG
+jr
+mX
+rC
+Nh
+Gu
+Gu
+Gu
+Gu
+"}
+(3,1,1) = {"
+CG
+Ss
+bl
+eT
+CG
+MI
+MI
+MI
+CG
+Gu
+Gu
+Gu
+Gu
+"}
+(4,1,1) = {"
+SL
+LE
+cM
+dP
+SL
+pV
+tk
+Ml
+SL
+Gu
+Gu
+Gu
+Gu
+"}
+(5,1,1) = {"
+SL
+tf
+YM
+yG
+XL
+PR
+In
+Qm
+Gj
+Gu
+Gu
+Gu
+Gu
+"}
+(6,1,1) = {"
+SL
+XP
+IX
+JX
+SL
+GW
+ie
+Mt
+YN
+Gu
+Gu
+Gu
+Gu
+"}
+(7,1,1) = {"
+SL
+SL
+pI
+SL
+SL
+SL
+Tf
+VP
+SL
+Gu
+Gu
+Gu
+Gu
+"}
+(8,1,1) = {"
+xh
+Pe
+CQ
+BL
+kq
+NV
+NV
+SM
+NV
+Pz
+oQ
+BS
+Gu
+"}
+(9,1,1) = {"
+Gz
+nt
+bF
+eD
+Nt
+iI
+Ta
+mH
+NV
+OZ
+OZ
+Of
+Gu
+"}
+(10,1,1) = {"
+ku
+Bk
+vM
+Wj
+zu
+iI
+qu
+YV
+nN
+lg
+ig
+gk
+gk
+"}
+(11,1,1) = {"
+Rr
+JG
+kG
+RI
+Jd
+iI
+uf
+zl
+NV
+fL
+zJ
+sz
+Kx
+"}
+(12,1,1) = {"
+xh
+KS
+qL
+gA
+id
+NV
+NV
+NV
+NV
+JL
+Fr
+OS
+LK
+"}
+(13,1,1) = {"
+vk
+xh
+tz
+sB
+id
+YU
+id
+Yh
+id
+jM
+QR
+kY
+Kx
+"}
+(14,1,1) = {"
+Gu
+xh
+Am
+Tg
+RN
+yj
+mu
+gL
+RF
+eE
+rX
+Xe
+gk
+"}
+(15,1,1) = {"
+Gu
+vk
+ry
+cD
+id
+TP
+ZW
+HD
+id
+gk
+Lj
+gk
+Xk
+"}
+(16,1,1) = {"
+Gu
+Gu
+Gu
+Gu
+uA
+FW
+FW
+FW
+gk
+hN
+mt
+gk
+Gu
+"}
+(17,1,1) = {"
+Gu
+Gu
+Gu
+Gu
+Gu
+Gu
+Gu
+Gu
+Xk
+ik
+gk
+Xk
+Gu
+"}
diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm
index 5a3d2c2a384..a59a0d608d8 100644
--- a/code/__DEFINES/atom_hud.dm
+++ b/code/__DEFINES/atom_hud.dm
@@ -56,6 +56,10 @@
/// If they have the DNR trait
#define DNR_HUD "27"
// NOVA EDIT ADDITION END
+// FLUFFY FRONTIER ADDITION START
+#define XENO_HUD "30"
+#define XENOPLASMA_HUD "31"
+// FLUFFY FRONTIER ADDITION END
//by default everything in the hud_list of an atom is an image
//a value in hud_list with one of these will change that behavior
@@ -74,6 +78,7 @@
#define DATA_HUD_FAN 9
#define DATA_HUD_MALF_APC 10
#define DATA_HUD_PERMIT 11 //NOVA EDIT ADDITION
+#define DATA_HUD_XENO (DATA_HUD_PERMIT + 1) // FLUFFY FRONTIER ADDITION
/// cooldown for being shown the images for any particular data hud
#define ADD_HUD_TO_COOLDOWN 20
diff --git a/code/__DEFINES/~ff_defines/signals.dm b/code/__DEFINES/~ff_defines/signals.dm
new file mode 100644
index 00000000000..490358c1f00
--- /dev/null
+++ b/code/__DEFINES/~ff_defines/signals.dm
@@ -0,0 +1,2 @@
+// on call adjustPlasma() proc
+#define COMSIG_XENO_PLASMA_ADJUSTED "plasma_adjusted"
diff --git a/code/__DEFINES/~ff_defines/_globalvars/traits/declarations.dm b/code/__DEFINES/~ff_defines/traits/declarations.dm
similarity index 67%
rename from code/__DEFINES/~ff_defines/_globalvars/traits/declarations.dm
rename to code/__DEFINES/~ff_defines/traits/declarations.dm
index 9b3ae25f1ff..7da836a6b1b 100644
--- a/code/__DEFINES/~ff_defines/_globalvars/traits/declarations.dm
+++ b/code/__DEFINES/~ff_defines/traits/declarations.dm
@@ -1,6 +1,10 @@
+// xeno traits
/// Trait source for xeno innate abilities
#define TRAIT_XENO_INNATE "xeno_innate"
/// Trait source for something added BY a xeno ability
#define TRAIT_XENO_ABILITY_GIVEN "xeno_ability_given"
/// Determines if something can receive healing from a xeno
#define TRAIT_XENO_HEAL_AURA "trait_xeno_heal_aura"
+/// Trait source for traits added by fortify ability
+#define TRAIT_XENO_FORTIFY "xeno_fortify"
+#define TRAIT_XENO_HUD "xeno_hud"
diff --git a/code/__HELPERS/~ff_helpers/is_helpers.dm b/code/__HELPERS/~ff_helpers/is_helpers.dm
index aa2af5931b1..885f04dfc28 100644
--- a/code/__HELPERS/~ff_helpers/is_helpers.dm
+++ b/code/__HELPERS/~ff_helpers/is_helpers.dm
@@ -1 +1,12 @@
+// Nubbers
#define isnabber(A) (is_species(A, /datum/species/nabber))
+
+// TGMC Xenomorph
+#define istgmcalien(A) (istype(A, /mob/living/carbon/alien/adult/tgmc))
+#define istgmcalienqueen(A) (istype(A, /mob/living/carbon/alien/adult/tgmc/queen))
+#define istgmcalienpraetorian(A) (istype(A, /mob/living/carbon/alien/adult/tgmc/praetorian))
+#define istgmcalienravager(A) (istype(A, /mob/living/carbon/alien/adult/tgmc/ravager))
+#define istgmcaliencrusher(A) (istype(A, /mob/living/carbon/alien/adult/tgmc/crusher))
+#define istgmcalienspitter(A) (istype(A, /mob/living/carbon/alien/adult/tgmc/spitter))
+
+#define istgmcalientier2(A) (istgmcalienpraetorian(A) || istgmcalienravager(A) || istgmcaliencrusher(A) || istgmcalienspitter(A))
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index 084e08dc3fd..bf413baef4f 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -919,6 +919,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_XENO_ABILITY_GIVEN" = TRAIT_XENO_ABILITY_GIVEN,
"TRAIT_XENO_HEAL_AURA" = TRAIT_XENO_HEAL_AURA,
"TRAIT_XENO_INNATE" = TRAIT_XENO_INNATE,
+ "TRAIT_XENO_HUD" = TRAIT_XENO_HUD,
),
// FLUFFY FRONTIER ADDITION END
))
diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm
index cf7a9cbce87..b0fa90cc296 100644
--- a/code/_globalvars/traits/admin_tooling.dm
+++ b/code/_globalvars/traits/admin_tooling.dm
@@ -507,6 +507,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_XENO_ABILITY_GIVEN" = TRAIT_XENO_ABILITY_GIVEN,
"TRAIT_XENO_HEAL_AURA" = TRAIT_XENO_HEAL_AURA,
"TRAIT_XENO_INNATE" = TRAIT_XENO_INNATE,
+ "TRAIT_XENO_HUD" = TRAIT_XENO_HUD,
),
// FLUFFY FRONTIER ADDITION END
))
diff --git a/code/datums/hud.dm b/code/datums/hud.dm
index 9fb01c207a1..257ac61c504 100644
--- a/code/datums/hud.dm
+++ b/code/datums/hud.dm
@@ -19,6 +19,7 @@ GLOBAL_ALIST_INIT(huds, alist(
DATA_HUD_FAN = new /datum/atom_hud/data/human/fan_hud(),
DATA_HUD_MALF_APC = new /datum/atom_hud/data/malf_apc(),
DATA_HUD_PERMIT = new/datum/atom_hud/data/human/permit(), // NOVA EDIT ADDITION
+ DATA_HUD_XENO = new /datum/atom_hud/data/xeno(), // FLUFFY FRONTIER ADDITION
))
/// Assoc list of traits to the huds they give.
@@ -33,6 +34,7 @@ GLOBAL_LIST_INIT(trait_to_hud, list(
TRAIT_SECURITY_HUD = DATA_HUD_SECURITY_ADVANCED,
TRAIT_SECURITY_HUD_ID_ONLY = DATA_HUD_SECURITY_BASIC,
TRAIT_PERMIT_HUD = DATA_HUD_PERMIT, // NOVA EDIT ADDITION
+ TRAIT_XENO_HUD = DATA_HUD_XENO, // FLUFFY FRONTIER ADDITION
))
/// Assoc list of traits that block other traits' huds to list of hud (traits) that they block
diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
index 5c439212962..13a5a81c918 100644
--- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
+++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
@@ -123,7 +123,7 @@
owner.add_overlay(overlay)
var/atom/xeno_loc = get_turf(owner)
- var/mob/living/carbon/alien/larva/new_xeno = new larva_path(xeno_loc) // FLUFFY FRONTIER EDIT - TGMC XENOS. ORIGINAL: var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc)
+ var/mob/living/carbon/alien/larva/new_xeno = new larva_path(xeno_loc) // FLUFFY FRONTIER EDIT - TGMC_XENOS. ORIGINAL: var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc)
new_xeno.PossessByPlayer(ghost.key)
SEND_SOUND(new_xeno, sound('sound/mobs/non-humanoids/hiss/hiss5.ogg',0,0,0,100)) //To get the player's attention
new_xeno.add_traits(list(TRAIT_HANDS_BLOCKED, TRAIT_IMMOBILIZED, TRAIT_NO_TRANSFORM), type) //so we don't move during the bursting animation
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index a5e5adc63e7..a13b537e07d 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -190,7 +190,7 @@
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, MELEE))
return TRUE
-// FLUFFY FRONTIER EDIT BEGIN: TGMC_XENOS - moved to: tff_modular\modules\tgmc_xenos\code\human_defense.dm
+// FLUFFY FRONTIER EDIT BEGIN: TGMC_XENOS - moved to: tff_modular\modules\tgmc_xenos\code\defense\human_defense.dm
/*
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/adult/user, list/modifiers)
. = ..()
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index 44690288175..573aada3733 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -1024,6 +1024,15 @@
/obj/vehicle/sealed/mecha/proc/melee_attack_effect(mob/living/victim, heavy)
if(heavy)
+ // FLUFFY FRONTIER ADDITION START - TGMC_XENOS - Это нужно реворкнуть на апстриме
+ if(istgmcalien(victim))
+ var/mob/living/carbon/alien/adult/tgmc/tgmc_alien = victim
+ if(tgmc_alien.resist_heavy_hits)
+ if(health_percentage(tgmc_alien) >= 35)
+ return
+ if(!prob(50)) // 50% что при ударе по ослабленному ксеносу - он упадет в бессознательное состояние
+ return
+ // FLUFFY FRONTIER ADDITION END
victim.Unconscious(2 SECONDS)
else
victim.Knockdown(4 SECONDS)
diff --git a/tff_modular/modules/custom_huds/code/huds.dm b/tff_modular/modules/custom_huds/code/huds.dm
index 4d620afc251..e07220f1ea6 100644
--- a/tff_modular/modules/custom_huds/code/huds.dm
+++ b/tff_modular/modules/custom_huds/code/huds.dm
@@ -1,9 +1,13 @@
GLOBAL_VAR_INIT(merged_huds, merge_huds())
/proc/merge_huds()
- var/icon/huds = new('modular_nova/master_files/icons/mob/huds/hud.dmi')
- var/icon/ff_huds = new('tff_modular/modules/custom_huds/icons/hud.dmi')
+ var/icon/huds = icon('modular_nova/master_files/icons/mob/huds/hud.dmi')
+ var/list/icon/additional_huds = list(
+ icon('tff_modular/modules/custom_huds/icons/hud.dmi'),
+ icon('tff_modular/modules/tgmc_xenos/icons/xeno_hud.dmi'),
+ )
- for(var/state in icon_states(ff_huds))
- huds.Insert(icon(ff_huds, state), state)
+ for(var/icon/hud in additional_huds)
+ for(var/state in icon_states(hud))
+ huds.Insert(icon(hud, state), state)
return huds
diff --git a/tff_modular/modules/custom_huds/code/huds_for_ghosts.dm b/tff_modular/modules/custom_huds/code/huds_for_ghosts.dm
new file mode 100644
index 00000000000..e75afe4164e
--- /dev/null
+++ b/tff_modular/modules/custom_huds/code/huds_for_ghosts.dm
@@ -0,0 +1,27 @@
+GLOBAL_LIST_INIT(additional_observer_huds, list(
+ TRAIT_XENO_HUD,
+))
+GLOBAL_LIST_INIT(additional_combo_huds, list(
+ TRAIT_XENO_HUD,
+))
+
+/client/enable_combo_hud()
+ if(combo_hud_enabled)
+ return
+ mob.add_traits(GLOB.additional_combo_huds, ADMIN_TRAIT)
+ return ..()
+
+/client/disable_combo_hud()
+ if(!combo_hud_enabled)
+ return
+ mob.remove_traits(GLOB.additional_combo_huds, ADMIN_TRAIT)
+ return ..()
+
+/mob/dead/observer/show_data_huds()
+ . = ..()
+ add_traits(GLOB.additional_observer_huds, REF(src))
+
+/mob/dead/observer/remove_data_huds()
+ . = ..()
+ remove_traits(GLOB.additional_observer_huds, REF(src))
+
diff --git a/tff_modular/modules/tgmc_xenos/code/alien_egg.dm b/tff_modular/modules/tgmc_xenos/code/alien_egg.dm
deleted file mode 100644
index 10e15b9ba39..00000000000
--- a/tff_modular/modules/tgmc_xenos/code/alien_egg.dm
+++ /dev/null
@@ -1,14 +0,0 @@
-/obj/item/organ/alien/eggsac/tgmc
- actions_types = list(/datum/action/cooldown/alien/make_structure/lay_egg/tgmc)
-
-/datum/action/cooldown/alien/make_structure/lay_egg/tgmc
- made_structure_type = /obj/structure/alien/egg/tgmc
-
-/obj/structure/alien/egg/tgmc
- child_path = /obj/item/clothing/mask/facehugger/tgmc
-
-/obj/item/clothing/mask/facehugger/tgmc
- embryo_path = /obj/item/organ/body_egg/alien_embryo/tgmc
-
-/obj/item/organ/body_egg/alien_embryo/tgmc
- larva_path = /mob/living/carbon/alien/larva/tgmc
diff --git a/tff_modular/modules/tgmc_xenos/code/base_alien.dm b/tff_modular/modules/tgmc_xenos/code/base_alien.dm
new file mode 100644
index 00000000000..6c827d2f905
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/base_alien.dm
@@ -0,0 +1,172 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+/mob/living/carbon/alien/adult/tgmc
+ name = "rare bugged alien"
+ icon = 'tff_modular/modules/tgmc_xenos/icons/big_xenos.dmi'
+ hud_possible = list(ANTAG_HUD, XENO_HUD, XENOPLASMA_HUD)
+ rotate_on_lying = FALSE
+ base_pixel_w = -16
+ layer = LARGE_MOB_LAYER //above most mobs, but below speechbubbles
+ maptext_height = 64
+ maptext_width = 64
+ pressure_resistance = 200
+
+ armor_type = /datum/armor/tgmc_xeno
+
+ bodyparts = list(
+ /obj/item/bodypart/chest/alien/tgmc,
+ /obj/item/bodypart/head/alien/tgmc,
+ /obj/item/bodypart/arm/left/alien/tgmc,
+ /obj/item/bodypart/arm/right/alien/tgmc,
+ /obj/item/bodypart/leg/right/alien/tgmc,
+ /obj/item/bodypart/leg/left/alien/tgmc,
+ )
+
+ default_organ_types_by_slot = list(
+ ORGAN_SLOT_BRAIN = /obj/item/organ/brain/alien,
+ ORGAN_SLOT_XENO_HIVENODE = /obj/item/organ/alien/hivenode,
+ ORGAN_SLOT_TONGUE = /obj/item/organ/tongue/alien,
+ ORGAN_SLOT_EYES = /obj/item/organ/eyes/alien/tgmc,
+ ORGAN_SLOT_LIVER = /obj/item/organ/liver/alien,
+ ORGAN_SLOT_EARS = /obj/item/organ/ears,
+ ORGAN_SLOT_STOMACH = /obj/item/organ/stomach/alien,
+ )
+
+ /// What icon file update_held_items will look for when making inhands for xenos
+ var/alt_inhands_file = 'tff_modular/modules/tgmc_xenos/icons/big_xenos.dmi'
+ /// Setting this will give a xeno generic_evolve set to evolve them into this type
+ var/next_evolution
+ /// Keeps track of if a xeno has evolved recently, if so then we prevent them from evolving until that time is up
+ var/has_evolved_recently = FALSE
+ /// How long xenos should be unable to evolve after recently evolving
+ var/evolution_cooldown_time = 90 SECONDS
+ /// Determines if a xeno is unable to use abilities
+ var/unable_to_use_abilities = FALSE
+ /// Все дополнительные органы, что должны находиться в телах ксеносов
+ var/list/additional_organ_types_by_slot
+
+ // Оффсет для огня
+ var/fire_offset_x = 16
+ var/fire_offset_y = 0
+
+ // АП при атаке по мехам
+ var/mecha_armor_penetration = 10
+ // Способность выдержать тяжелые удары мехов и не потерять сознание
+ var/resist_heavy_hits = FALSE
+
+ // Включен ли в данный момент фортифай
+ var/fortify = FALSE
+
+ // Может ли переносить хагов
+ var/can_hold_facehuggers = FALSE
+
+/mob/living/carbon/alien/adult/tgmc/Initialize(mapload)
+ . = ..()
+ real_name = "alien [caste]"
+
+ update_offsets() // Необходимо, чтобы base_pixel_w применился
+ set_armor(armor_type)
+
+ var/datum/atom_hud/data/xeno/xeno_hud = GLOB.huds[DATA_HUD_XENO]
+ xeno_hud.add_atom_to_hud(src)
+
+ if(next_evolution)
+ GRANT_ACTION(/datum/action/cooldown/alien/tgmc/generic_evolve)
+
+ add_traits(list(TRAIT_XENO_HEAL_AURA, TRAIT_PIERCEIMMUNE, TRAIT_XENO_HUD), TRAIT_XENO_INNATE)
+ AddElement(/datum/element/resin_walker, /datum/movespeed_modifier/resin_speedup)
+ AddElement(/datum/element/prevent_xeno_attacking_of_types, GLOB.typecache_general_bad_hostile_attack_targets, "this tastes awful!")
+ AddComponent(/datum/component/seethrough_mob)
+
+/mob/living/carbon/alien/adult/tgmc/create_internal_organs()
+ if(additional_organ_types_by_slot)
+ for(var/slot in additional_organ_types_by_slot)
+ default_organ_types_by_slot[slot] = additional_organ_types_by_slot[slot]
+ return ..()
+
+/mob/living/carbon/alien/adult/tgmc/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers)
+ if(body_position == LYING_DOWN) // Лежим - значит отдыхаем. Никакой войны во время отдыха
+ to_chat(src, span_warning("You can't do that in this position!"))
+ return FALSE
+ if(fortify)
+ to_chat(src, span_warning("You can't do that in this position!"))
+ return FALSE
+ if(ishuman(attack_target))
+ var/mob/living/carbon/human/target = attack_target
+ if(target.stat == DEAD)
+ to_chat(src, span_warning("[target] is dead, why would you want to touch it?"))
+ return FALSE
+ return ..()
+
+/mob/living/carbon/alien/adult/tgmc/death(gibbed)
+ . = ..()
+ xeno_hud_set_plasma()
+
+/mob/living/carbon/alien/adult/tgmc/set_resting(new_resting, silent = TRUE, instant = FALSE)
+ if(fortify)
+ balloon_alert(src, "Cannot while fortified")
+ return FALSE
+ return ..()
+
+/mob/living/carbon/alien/adult/tgmc/on_lying_down(new_lying_angle)
+ . = ..()
+ add_movespeed_modifier(/datum/movespeed_modifier/tgmc_alien_sleeping)
+
+/mob/living/carbon/alien/adult/tgmc/on_standing_up()
+ . = ..()
+ remove_movespeed_modifier(/datum/movespeed_modifier/tgmc_alien_sleeping)
+
+/datum/movespeed_modifier/tgmc_alien_sleeping
+ multiplicative_slowdown = 8
+
+/mob/living/carbon/alien/adult/tgmc/getarmor(def_zone, type)
+ return get_armor_rating(type)
+
+/datum/armor/tgmc_xeno
+ acid = 100
+ bio = 100
+ bomb = 0
+ bullet = 0
+ consume = 0
+ energy = 0
+ laser = 0
+ fire = 0
+ melee = 0
+ wound = 100
+
+/mob/living/carbon/alien/adult/tgmc/get_fire_overlay(stacks, on_fire)
+ var/fire_icon = "generic_fire"
+
+ if(!GLOB.fire_appearances[fire_icon])
+ var/mutable_appearance/new_fire_overlay = mutable_appearance(
+ 'icons/mob/effects/onfire.dmi',
+ fire_icon,
+ -HIGHEST_LAYER,
+ appearance_flags = RESET_COLOR,
+ )
+ var/matrix/M = matrix(fire_offset_x, fire_offset_y, MATRIX_TRANSLATE)
+ new_fire_overlay.transform = M
+ GLOB.fire_appearances[fire_icon] = new_fire_overlay
+
+ return GLOB.fire_appearances[fire_icon]
+
+/mob/living/carbon/alien/adult/tgmc/add_shared_particles(particle_type, custom_key, particle_flags, pool_size)
+ . = ..()
+ var/obj/particle_holder = .
+ particle_holder.pixel_x = fire_offset_x
+ particle_holder.pixel_y = fire_offset_y
+
+/mob/living/carbon/alien/adult/tgmc/prepare_data_huds()
+ . = ..()
+ xeno_hud_set_plasma()
+
+/mob/living/carbon/proc/get_max_plasma()
+ var/obj/item/organ/alien/plasmavessel/vessel = get_organ_by_type(/obj/item/organ/alien/plasmavessel)
+ if(isnull(vessel))
+ return 0
+ return vessel.max_plasma
+
+/mob/living/carbon/alien/adult/tgmc/adjustPlasma(amount)
+ . = ..()
+ if(.)
+ SEND_SIGNAL(src, COMSIG_XENO_PLASMA_ADJUSTED, amount)
diff --git a/tff_modular/modules/tgmc_xenos/code/base_nova_xeno.dm b/tff_modular/modules/tgmc_xenos/code/base_nova_xeno.dm
deleted file mode 100644
index 13e92086158..00000000000
--- a/tff_modular/modules/tgmc_xenos/code/base_nova_xeno.dm
+++ /dev/null
@@ -1,228 +0,0 @@
-/// TGMC_XENOS (old nova sector xenos)
-
-/mob/living/carbon/alien/adult/tgmc
- name = "rare bugged alien"
- icon = 'tff_modular/modules/tgmc_xenos/icons/big_xenos.dmi'
- rotate_on_lying = FALSE
- base_pixel_x = -16 //All of the xeno sprites are 64x64, and we want them to be level with the tile they are on, much like oversized quirk users
- layer = LARGE_MOB_LAYER //above most mobs, but below speechbubbles
- maptext_height = 64
- maptext_width = 64
- pressure_resistance = 200
-
- default_organ_types_by_slot = list(
- ORGAN_SLOT_BRAIN = /obj/item/organ/brain/alien,
- ORGAN_SLOT_XENO_HIVENODE = /obj/item/organ/alien/hivenode,
- ORGAN_SLOT_TONGUE = /obj/item/organ/tongue/alien,
- ORGAN_SLOT_EYES = /obj/item/organ/eyes/alien,
- ORGAN_SLOT_LIVER = /obj/item/organ/liver/alien,
- ORGAN_SLOT_EARS = /obj/item/organ/ears,
- ORGAN_SLOT_STOMACH = /obj/item/organ/stomach/alien,
- )
-
- /// What icon file update_held_items will look for when making inhands for xenos
- var/alt_inhands_file = 'tff_modular/modules/tgmc_xenos/icons/big_xenos.dmi'
- /// Setting this will give a xeno generic_evolve set to evolve them into this type
- var/next_evolution
- /// Keeps track of if a xeno has evolved recently, if so then we prevent them from evolving until that time is up
- var/has_evolved_recently = FALSE
- /// How long xenos should be unable to evolve after recently evolving
- var/evolution_cooldown_time = 90 SECONDS
- /// Determines if a xeno is unable to use abilities
- var/unable_to_use_abilities = FALSE
- /// Pixel X shifting of the on fire overlay
- var/on_fire_pixel_x = 16
- /// Pixel Y shifting of the on fire overlay
- var/on_fire_pixel_y = 16
- /// Все дополнительные органы, что должны находиться в телах ксеносов
- var/list/additional_organ_types_by_slot
-
-/mob/living/carbon/alien/adult/tgmc/Initialize(mapload)
- . = ..()
-
- if(next_evolution)
- GRANT_ACTION(/datum/action/cooldown/alien/tgmc/generic_evolve)
-
- pixel_x = -16
-
- ADD_TRAIT(src, TRAIT_XENO_HEAL_AURA, TRAIT_XENO_INNATE)
- real_name = "alien [caste]"
-
-/mob/living/carbon/alien/adult/tgmc/create_internal_organs()
- if(additional_organ_types_by_slot)
- default_organ_types_by_slot += additional_organ_types_by_slot
- return ..()
-
-/// Called when a larva or xeno evolves, adds a configurable timer on evolving again to the xeno
-/mob/living/carbon/alien/adult/tgmc/proc/has_just_evolved()
- if(has_evolved_recently)
- return
- has_evolved_recently = TRUE
- addtimer(CALLBACK(src, PROC_REF(can_evolve_once_again)), evolution_cooldown_time)
-
-/// Allows xenos to evolve again if they are currently unable to
-/mob/living/carbon/alien/adult/tgmc/proc/can_evolve_once_again()
- if(!has_evolved_recently)
- return
- has_evolved_recently = FALSE
-
-/datum/action/cooldown/alien/tgmc
- button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
- /// Some xeno abilities block other abilities from being used, this allows them to get around that in cases where it is needed
- var/can_be_used_always = FALSE
-
-/datum/action/cooldown/alien/tgmc/IsAvailable(feedback = FALSE)
- . = ..()
- if(!.)
- return FALSE
-
- if(can_be_used_always)
- return TRUE
-
- var/mob/living/carbon/alien/adult/tgmc/owner_alien = owner
- if(!istype(owner_alien) || owner_alien.unable_to_use_abilities)
- return FALSE
-
-/datum/action/cooldown/alien/tgmc/generic_evolve
- name = "Evolve"
- desc = "Allows us to evolve to a higher caste of our type, if there is not one already."
- button_icon_state = "evolution"
- /// What type this ability will turn the owner into upon completion
- var/type_to_evolve_into
-
-/datum/action/cooldown/alien/tgmc/generic_evolve/Grant(mob/grant_to)
- . = ..()
- if(!isalien(owner))
- return
- var/mob/living/carbon/alien/target_alien = owner
- plasma_cost = target_alien.get_max_plasma() //This ability should always require that a xeno be at their max plasma capacity to use
-
-/datum/action/cooldown/alien/tgmc/generic_evolve/Activate()
- var/mob/living/carbon/alien/adult/tgmc/evolver = owner
-
- if(!istype(evolver))
- to_chat(owner, span_warning("You aren't an alien, you can't evolve!"))
- return FALSE
-
- type_to_evolve_into = evolver.next_evolution
- if(!type_to_evolve_into)
- to_chat(evolver, span_bolddanger("Something is wrong... We can't evolve into anything? (This is broken report it on GitHub)"))
- CRASH("Couldn't find an evolution for [owner] ([owner.type]).")
-
- if(!isturf(evolver.loc))
- return FALSE
-
- if(get_alien_type(type_to_evolve_into))
- evolver.balloon_alert(evolver, "too many of our evolution already")
- return FALSE
-
- var/obj/item/organ/alien/hivenode/node = evolver.get_organ_by_type(/obj/item/organ/alien/hivenode)
- if(!node)
- to_chat(evolver, span_bolddanger("We can't sense our node's connection to the hive... We can't evolve!"))
- return FALSE
-
- if(node.recent_queen_death)
- to_chat(evolver, span_bolddanger("The death of our queen... We can't seem to gather the mental energy required to evolve..."))
- return FALSE
-
- if(evolver.has_evolved_recently)
- evolver.balloon_alert(evolver, "can evolve in 1.5 minutes") //Make that 1.5 variable later, but it keeps fucking up for me :(
- return FALSE
-
- var/new_beno = new type_to_evolve_into(evolver.loc)
- evolver.alien_evolve(new_beno)
- return TRUE
-
-/datum/movespeed_modifier/alien_quick
- multiplicative_slowdown = -0.5
-
-/datum/movespeed_modifier/alien_slow
- multiplicative_slowdown = 0.5
-
-/datum/movespeed_modifier/alien_heavy
- multiplicative_slowdown = 1
-
-/datum/movespeed_modifier/alien_big
- multiplicative_slowdown = 2
-
-/mob/living/carbon/alien/adult/tgmc/update_held_items()
- ..()
- remove_overlay(HANDS_LAYER)
- var/list/hands = list()
-
- var/obj/item/l_hand = get_item_for_held_index(1)
- if(l_hand)
- var/itm_state = l_hand.inhand_icon_state
- if(!itm_state)
- itm_state = l_hand.icon_state
- var/mutable_appearance/l_hand_item = mutable_appearance(alt_inhands_file, "[itm_state][caste]_l", -HANDS_LAYER)
- if(l_hand.blocks_emissive)
- l_hand_item.overlays += emissive_blocker(l_hand_item.icon, l_hand_item.icon_state, alpha = l_hand_item.alpha)
- hands += l_hand_item
-
- var/obj/item/r_hand = get_item_for_held_index(2)
- if(r_hand)
- var/itm_state = r_hand.inhand_icon_state
- if(!itm_state)
- itm_state = r_hand.icon_state
- var/mutable_appearance/r_hand_item = mutable_appearance(alt_inhands_file, "[itm_state][caste]_r", -HANDS_LAYER)
- if(r_hand.blocks_emissive)
- r_hand_item.overlays += emissive_blocker(r_hand_item.icon, r_hand_item.icon_state, alpha = r_hand_item.alpha)
- hands += r_hand_item
-
- overlays_standing[HANDS_LAYER] = hands
- apply_overlay(HANDS_LAYER)
-
-/mob/living/carbon/proc/get_max_plasma()
- var/obj/item/organ/alien/plasmavessel/vessel = get_organ_by_type(/obj/item/organ/alien/plasmavessel)
- if(!vessel)
- return -1
- return vessel.max_plasma
-
-/mob/living/carbon/alien/adult/tgmc/alien_evolve(mob/living/carbon/alien/new_xeno, is_it_a_larva)
- var/mob/living/carbon/alien/adult/tgmc/xeno_to_transfer_to = new_xeno
-
- xeno_to_transfer_to.setDir(dir)
- if(!islarva(xeno_to_transfer_to))
- xeno_to_transfer_to.has_just_evolved()
- if(mind)
- mind.name = xeno_to_transfer_to.real_name
- mind.transfer_to(xeno_to_transfer_to)
- qdel(src)
-
-/mob/living/carbon/alien/adult/tgmc/get_fire_overlay(stacks, on_fire)
- var/fire_icon = "generic_fire"
-
- if(!GLOB.fire_appearances[fire_icon])
- var/mutable_appearance/new_fire_overlay = mutable_appearance(
- 'icons/mob/effects/onfire.dmi',
- fire_icon,
- -HIGHEST_LAYER,
- appearance_flags = RESET_COLOR,
- )
- GLOB.fire_appearances[fire_icon] = new_fire_overlay
-
- return GLOB.fire_appearances[fire_icon]
-
-/mob/living/carbon/alien/adult/tgmc/findQueen() //Yes we really do need to do this whole thing to let the queen finder work
- if(hud_used)
- hud_used.alien_queen_finder.cut_overlays()
- var/mob/queen = get_alien_type(/mob/living/carbon/alien/adult/tgmc/queen)
- if(!queen)
- return
- var/turf/Q = get_turf(queen)
- var/turf/A = get_turf(src)
- if(Q.z != A.z) //The queen is on a different Z level, we cannot sense that far.
- return
- var/Qdir = get_dir(src, Q)
- var/Qdist = get_dist(src, Q)
- var/finder_icon = "finder_center" //Overlay showed when adjacent to or on top of the queen!
- switch(Qdist)
- if(2 to 7)
- finder_icon = "finder_near"
- if(8 to 20)
- finder_icon = "finder_med"
- if(21 to INFINITY)
- finder_icon = "finder_far"
- var/image/finder_eye = image('icons/hud/screen_alien.dmi', finder_icon, dir = Qdir)
- hud_used.alien_queen_finder.add_overlay(finder_eye)
diff --git a/tff_modular/modules/tgmc_xenos/code/defense/alien_defense.dm b/tff_modular/modules/tgmc_xenos/code/defense/alien_defense.dm
new file mode 100644
index 00000000000..3a0a9982a99
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/defense/alien_defense.dm
@@ -0,0 +1,32 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+#define TGMC_XENO_FIRESTACK_DAMAGE 2
+
+/mob/living/carbon/alien/adult/tgmc/attack_alien(mob/living/carbon/alien/user, list/modifiers)
+ if(!user.combat_mode)
+ if(user == src && check_self_for_injuries())
+ return
+
+ playsound(loc, 'sound/items/weapons/thudswoosh.ogg', 50, TRUE, -1)
+ AdjustStun(-6 SECONDS)
+ AdjustKnockdown(-6 SECONDS)
+ AdjustImmobilized(-6 SECONDS)
+ AdjustParalyzed(-6 SECONDS)
+ AdjustUnconscious(-6 SECONDS)
+ AdjustSleeping(-10 SECONDS)
+
+ if(on_fire && fire_stacks > 0)
+ adjust_fire_stacks(-2)
+ if(fire_stacks > 0)
+ user.visible_message(span_danger("[user] tries to put out the fire on [src]!"), span_warning("You try to put out the fire on [src]!"), vision_distance = 5)
+ else
+ user.visible_message(span_danger("[user] has successfully extinguished the fire on [src]!"), span_notice("You extinguished the fire on [src]!"), vision_distance = 5)
+ else
+ visible_message(span_notice("[user.name] nuzzles [src]."))
+ return
+ else
+ return ..()
+
+/mob/living/carbon/alien/adult/tgmc/on_fire_stack(seconds_per_tick, datum/status_effect/fire_handler/fire_stacks/fire_handler)
+ . = ..()
+ adjust_fire_loss(seconds_per_tick * TGMC_XENO_FIRESTACK_DAMAGE)
diff --git a/tff_modular/modules/tgmc_xenos/code/human_defense.dm b/tff_modular/modules/tgmc_xenos/code/defense/human_defense.dm
similarity index 89%
rename from tff_modular/modules/tgmc_xenos/code/human_defense.dm
rename to tff_modular/modules/tgmc_xenos/code/defense/human_defense.dm
index bedf7587e99..0450e505d7c 100644
--- a/tff_modular/modules/tgmc_xenos/code/human_defense.dm
+++ b/tff_modular/modules/tgmc_xenos/code/defense/human_defense.dm
@@ -1,5 +1,6 @@
/// TGMC_XENOS (old nova sector xenos)
+// Переопредление прока из 'code\modules\mob\living\carbon\human\human_defense.dm'
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/adult/user, list/modifiers)
. = ..()
if(!.)
@@ -59,3 +60,9 @@
return TRUE
apply_damage(damage, BRUTE, affecting, armor_block)
+
+/mob/living/carbon/human/can_be_pulled(user, force)
+ . = ..()
+ if(. && stat == DEAD && istgmcalien(user))
+ to_chat(user, span_warning("[src] is dead, why would we want to touch it?"))
+ return FALSE
diff --git a/tff_modular/modules/tgmc_xenos/code/defense/mecha_defense.dm b/tff_modular/modules/tgmc_xenos/code/defense/mecha_defense.dm
new file mode 100644
index 00000000000..ffbabe34bf3
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/defense/mecha_defense.dm
@@ -0,0 +1,25 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+// Переопределяем прока атаки у меха, ведь мехи по сути неубиваемые для ксеносов
+/obj/vehicle/sealed/mecha/attack_alien(mob/living/carbon/alien/adult/tgmc/user, list/modifiers)
+ // Если это обычный ксенос - выполняется обычный прок, если нет - наш
+ if(!istype(user))
+ return ..()
+
+ log_message("Attack by alien. Attacker - [user].", LOG_MECHA, color="red")
+ playsound(loc, 'sound/items/weapons/slash.ogg', 100, TRUE)
+ var/damage = rand(user.melee_damage_lower, user.melee_damage_upper)
+ attack_generic(user, damage, BRUTE, MELEE, 0, armor_penetration = user.mecha_armor_penetration)
+
+// Так как плевки не могут наносить урон мехам из-за их брони к кислоте, то мы просто будем переопределять armor_flag этих самых плевков с кислоты на лазер
+/obj/vehicle/sealed/mecha/bullet_act(obj/projectile/source, def_zone, mode)
+ if(istype(source, /obj/projectile/neurotoxin/tgmc/acid))
+ source.armor_flag = LASER
+ source.damage /= 2
+ return ..()
+
+/obj/durand_shield/projectile_hit(obj/projectile/hitting_projectile, def_zone, piercing_hit = FALSE, blocked = null)
+ if(istype(hitting_projectile, /obj/projectile/neurotoxin/tgmc/acid))
+ hitting_projectile.armor_flag = LASER
+ hitting_projectile.damage /= 2
+ return ..()
diff --git a/tff_modular/modules/tgmc_xenos/code/larva.dm b/tff_modular/modules/tgmc_xenos/code/larva.dm
deleted file mode 100644
index 2ae9fa2ff0b..00000000000
--- a/tff_modular/modules/tgmc_xenos/code/larva.dm
+++ /dev/null
@@ -1,99 +0,0 @@
-/// TGMC_XENOS (old nova sector xenos)
-
-/mob/living/carbon/alien/larva/tgmc
-
-/mob/living/carbon/alien/larva/tgmc/Initialize(mapload)
- . = ..()
-
- for(var/datum/action/cooldown/alien/larva_evolve/action in actions)
- if(istype(action))
- action.Remove(src)
-
- var/static/list/innate_actions = list(
- /datum/action/cooldown/alien/larva_evolve/tgmc,
- )
- grant_actions_by_list(innate_actions)
-
- return
-
-
-/datum/action/cooldown/alien/larva_evolve/tgmc/Activate(atom/target)
- var/static/list/caste_options
- if(!caste_options)
- caste_options = list()
-
- // This --can probably-- (will not) be genericized in the future.
- make_xeno_caste_entry(
- caste_name = "Runner",
- caste_image = image(icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi', icon_state = "preview_runner"),
- caste_info = span_info("Runners are the most agile caste, the short stature of running on all fours \
- gives them great speed, the ability to dodge projectiles, and allows them to tackle while holding throw and clicking. \
- Eventually, runners can evolve onwards into the fearsome ravager, should the hive permit it."),
- caste_options = caste_options,
- )
-
- make_xeno_caste_entry(
- caste_name = "Sentinel",
- caste_image = image(icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi', icon_state = "preview_sentinel"),
- caste_info = span_info("Sentinels are a caste similar in shape to a drone, forfeiting the ability to \
- become royalty in exchange for spitting either acid, or a potent neurotoxin. They aren't as strong in close combat \
- as the other options, but can eventually evolve into a more dangerous form of acid spitter, should the hive have capacity."),
- caste_options = caste_options,
- )
-
- make_xeno_caste_entry(
- caste_name = "Defender",
- caste_image = image(icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi', icon_state = "preview_defender"),
- caste_info = span_info("Slow, tough, hard hitting, the defender is well and capable of what the name implies, \
- the defender's thick armor allows it to take a few more hits than other castes, which can be paired with a deadly tail club \
- and ability to make short charges to cause some real damage. Eventually, it will be able to evolve into the feared crusher, \
- destroyer of stationary objects should the hive have the capacity."),
- caste_options = caste_options,
- )
-
- make_xeno_caste_entry(
- caste_name = "Drone",
- caste_image = image(icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi', icon_state = "preview_drone"),
- caste_info = span_info("Drones are a somewhat weak, although fairly quick caste that fills a mainly \
- support role in a hive, having a higher plasma capacity than most first evolutions, and the ability to \
- make a healing aura for nearby xenos. Drones are the only caste that can evolve into both praetorians and \
- queens, though only one queen and one praetorian may exist at any time."),
- caste_options = caste_options,
- )
-
- var/alien_caste = show_radial_menu(owner, owner, caste_options, radius = 38, require_near = TRUE, tooltips = TRUE)
- if(QDELETED(src) || QDELETED(owner) || !IsAvailable(feedback = TRUE) || isnull(alien_caste))
- return
-
- spawn_new_xeno(alien_caste)
-
- return TRUE
-
-/// Generates a new entry to the
-/datum/action/cooldown/alien/larva_evolve/tgmc/proc/make_xeno_caste_entry(caste_name, caste_image, caste_info, list/caste_options)
- var/datum/radial_menu_choice/caste_option = new()
-
- caste_option.name = caste_name
- caste_option.image = caste_image
- caste_option.info = caste_info
-
- caste_options[caste_name] = caste_option
-
-/datum/action/cooldown/alien/larva_evolve/tgmc/proc/spawn_new_xeno(alien_caste)
- var/mob/living/carbon/alien/adult/tgmc/new_xeno
- var/mob/living/carbon/alien/larva/larva = owner
-
- switch(alien_caste)
- if("Runner")
- new_xeno = new /mob/living/carbon/alien/adult/tgmc/runner(larva.loc)
- if("Sentinel")
- new_xeno = new /mob/living/carbon/alien/adult/tgmc/sentinel(larva.loc)
- if("Defender")
- new_xeno = new /mob/living/carbon/alien/adult/tgmc/defender(larva.loc)
- if("Drone")
- new_xeno = new /mob/living/carbon/alien/adult/tgmc/drone(larva.loc)
- else
- CRASH("Alien evolve was given an invalid / incorrect alien cast type. Got: [alien_caste]")
-
- new_xeno.has_just_evolved()
- larva.alien_evolve(new_xeno)
diff --git a/tff_modular/modules/tgmc_xenos/code/misc/attack_prevent_element.dm b/tff_modular/modules/tgmc_xenos/code/misc/attack_prevent_element.dm
new file mode 100644
index 00000000000..cce3ab7900a
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/misc/attack_prevent_element.dm
@@ -0,0 +1,39 @@
+// TGMC_XENOS
+// Почти ПОЛНАЯ КОПИЯ code\datums\elements\prevent_attacking_of_types.dm, измененная под работу со всеми мобами, а не только базовыми
+
+/// This hostile will not be able to attack a given typecache, and will receive
+/// a balloon alert when it tries to.
+/datum/element/prevent_xeno_attacking_of_types
+ element_flags = ELEMENT_BESPOKE
+ argument_hash_start_idx = 2
+
+ /// The typecache of things this hostile can't attack
+ var/list/typecache
+
+ /// The message to send to the hostile mob when they try to attack something they can't
+ var/alert_message
+
+/datum/element/prevent_xeno_attacking_of_types/Attach(datum/target, list/typecache, alert_message)
+ . = ..()
+
+ if (!isliving(target))
+ return ELEMENT_INCOMPATIBLE
+
+ src.alert_message = alert_message
+ src.typecache = typecache
+
+ RegisterSignal(target, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_pre_attacking_target))
+
+/datum/element/prevent_xeno_attacking_of_types/Detach(datum/source, ...)
+ UnregisterSignal(source, COMSIG_LIVING_EARLY_UNARMED_ATTACK)
+ return ..()
+
+/datum/element/prevent_xeno_attacking_of_types/proc/on_pre_attacking_target(mob/source, atom/target)
+ SIGNAL_HANDLER
+
+ if (!typecache[target.type])
+ return
+
+ target.balloon_alert(source, alert_message)
+
+ return COMPONENT_CANCEL_ATTACK_CHAIN
diff --git a/tff_modular/modules/tgmc_xenos/code/misc/larva.dm b/tff_modular/modules/tgmc_xenos/code/misc/larva.dm
new file mode 100644
index 00000000000..e5f10e4197d
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/misc/larva.dm
@@ -0,0 +1,133 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+// Подтип фейсхаггера
+/obj/item/clothing/mask/facehugger/tgmc
+ embryo_path = /obj/item/organ/body_egg/alien_embryo/tgmc
+
+/obj/item/clothing/mask/facehugger/tgmc/proc/ProximityLeap(range = 1)
+ for(var/mob/victim in range(range, src))
+ if(!CanHug(victim))
+ continue
+ return Leap(victim)
+ return FALSE
+
+/obj/item/clothing/mask/facehugger/tgmc/attempt_pickup(mob/living/user, skip_grav)
+ if(istgmcalien(user))
+ var/mob/living/carbon/alien/adult/tgmc/xeno = user
+ if(!xeno.can_hold_facehuggers)
+ to_chat(user, span_alien("Your claws lack the dexterity to hold [src]"))
+ return TRUE
+ return ..()
+
+/obj/item/clothing/mask/facehugger/tgmc/can_be_pulled(user, force)
+ . = ..()
+ if(. && istgmcalien(user))
+ var/mob/living/carbon/alien/adult/tgmc/xeno = user
+ if(!xeno.can_hold_facehuggers)
+ to_chat(user, span_alien("Your claws lack the dexterity to hold [src]"))
+ return FALSE
+
+
+// То же самое, но для эмбриона ларвочки
+/obj/item/organ/body_egg/alien_embryo/tgmc
+ larva_path = /mob/living/carbon/alien/larva/tgmc
+
+
+// Наша собственная ларвочка. Крутая!
+/mob/living/carbon/alien/larva/tgmc
+
+/mob/living/carbon/alien/larva/tgmc/Initialize(mapload)
+ . = ..()
+ for(var/datum/action/cooldown/alien/larva_evolve/action in actions)
+ if(istype(action))
+ action.Remove(src)
+
+ GRANT_ACTION(/datum/action/cooldown/alien/larva_evolve/tgmc)
+
+// Способность, которая позволяет эволюционировать ларве в большого ксеноса
+/datum/action/cooldown/alien/larva_evolve/tgmc/Activate(atom/target)
+ var/static/list/caste_options
+ if(!caste_options)
+ caste_options = list()
+
+ make_xeno_caste_entry(
+ caste_name = "Runner",
+ caste_image = image(icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi', icon_state = "preview_runner"),
+ caste_info = span_info( \
+ "Runners are the most agile caste, the short stature of running on all fours \
+ gives them great speed, the ability to dodge projectiles, and allows them to tackle while holding throw and clicking. \
+ Eventually, runners can evolve onwards into the fearsome ravager, should the hive permit it." \
+ ),
+ caste_options = caste_options,
+ )
+
+ make_xeno_caste_entry(
+ caste_name = "Sentinel",
+ caste_image = image(icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi', icon_state = "preview_sentinel"),
+ caste_info = span_info( \
+ "Sentinels are a caste similar in shape to a drone, forfeiting the ability to \
+ become royalty in exchange for spitting either acid, or a potent neurotoxin. They aren't as strong in close combat \
+ as the other options, but can eventually evolve into a more dangerous form of acid spitter, should the hive have capacity." \
+ ),
+ caste_options = caste_options,
+ )
+
+ make_xeno_caste_entry(
+ caste_name = "Defender",
+ caste_image = image(icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi', icon_state = "preview_defender"),
+ caste_info = span_info( \
+ "Slow, tough, hard hitting, the defender is well and capable of what the name implies, \
+ the defender's thick armor allows it to take a few more hits than other castes, which can be paired with a deadly tail club \
+ and ability to make short charges to cause some real damage. Eventually, it will be able to evolve into the feared crusher, \
+ destroyer of stationary objects should the hive have the capacity." \
+ ),
+ caste_options = caste_options,
+ )
+
+ make_xeno_caste_entry(
+ caste_name = "Drone",
+ caste_image = image(icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi', icon_state = "preview_drone"),
+ caste_info = span_info( \
+ "Drones are a somewhat weak, although fairly quick caste that fills a mainly \
+ support role in a hive, having a higher plasma capacity than most first evolutions, and the ability to \
+ make a healing aura for nearby xenos. Drones are the only caste that can evolve into both praetorians and \
+ queens, though only one queen and one praetorian may exist at any time." \
+ ),
+ caste_options = caste_options,
+ )
+
+ var/alien_caste = show_radial_menu(owner, owner, caste_options, radius = 38, require_near = TRUE, tooltips = TRUE)
+ if(QDELETED(src) || QDELETED(owner) || !IsAvailable(feedback = TRUE) || isnull(alien_caste))
+ return
+
+ spawn_new_xeno(alien_caste)
+
+ return TRUE
+
+/datum/action/cooldown/alien/larva_evolve/tgmc/proc/make_xeno_caste_entry(caste_name, caste_image, caste_info, list/caste_options)
+ var/datum/radial_menu_choice/caste_option = new()
+
+ caste_option.name = caste_name
+ caste_option.image = caste_image
+ caste_option.info = caste_info
+
+ caste_options[caste_name] = caste_option
+
+/datum/action/cooldown/alien/larva_evolve/tgmc/proc/spawn_new_xeno(alien_caste)
+ var/mob/living/carbon/alien/adult/tgmc/new_xeno
+ var/mob/living/carbon/alien/larva/larva = owner
+
+ switch(alien_caste)
+ if("Runner")
+ new_xeno = new /mob/living/carbon/alien/adult/tgmc/runner(larva.loc)
+ if("Sentinel")
+ new_xeno = new /mob/living/carbon/alien/adult/tgmc/sentinel(larva.loc)
+ if("Defender")
+ new_xeno = new /mob/living/carbon/alien/adult/tgmc/defender(larva.loc)
+ if("Drone")
+ new_xeno = new /mob/living/carbon/alien/adult/tgmc/drone(larva.loc)
+ else
+ CRASH("Alien evolve was given an invalid / incorrect alien cast type. Got: [alien_caste]")
+
+ new_xeno.has_just_evolved()
+ larva.alien_evolve(new_xeno)
diff --git a/tff_modular/modules/tgmc_xenos/code/misc/projectiles.dm b/tff_modular/modules/tgmc_xenos/code/misc/projectiles.dm
new file mode 100644
index 00000000000..0179b43b087
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/misc/projectiles.dm
@@ -0,0 +1,35 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+/obj/projectile/neurotoxin/tgmc
+ name = "neurotoxin spit"
+ icon_state = "neurotoxin"
+ damage = 40
+ paralyze = 0
+ damage_type = STAMINA
+ armor_flag = BIO
+
+/obj/projectile/neurotoxin/tgmc/queen
+ damage = 80
+
+/obj/projectile/neurotoxin/tgmc/spitter_spread //Slightly nerfed because its a shotgun spread of these
+ name = "neurotoxin spit"
+ icon_state = "neurotoxin"
+ damage = 30
+
+
+/obj/projectile/neurotoxin/tgmc/acid
+ name = "acid spit"
+ icon_state = "toxin"
+ damage = 25
+ paralyze = 0
+ damage_type = BURN
+ armor_flag = ACID
+
+/obj/projectile/neurotoxin/tgmc/acid/queen
+ damage = 40
+
+/obj/projectile/neurotoxin/tgmc/acid/spitter_spread
+ name = "acid spit"
+ icon_state = "toxin"
+ damage = 20
+ damage_type = BURN
diff --git a/tff_modular/modules/tgmc_xenos/code/misc/queen_finder.dm b/tff_modular/modules/tgmc_xenos/code/misc/queen_finder.dm
new file mode 100644
index 00000000000..e752bfd2210
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/misc/queen_finder.dm
@@ -0,0 +1,25 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+//Yes we really do need to do this whole thing to let the queen finder work
+/mob/living/carbon/alien/adult/tgmc/findQueen()
+ if(hud_used)
+ hud_used.alien_queen_finder.cut_overlays()
+ var/mob/queen = get_alien_type(/mob/living/carbon/alien/adult/tgmc/queen)
+ if(!queen)
+ return
+ var/turf/Q = get_turf(queen)
+ var/turf/A = get_turf(src)
+ if(Q.z != A.z) //The queen is on a different Z level, we cannot sense that far.
+ return
+ var/Qdir = get_dir(src, Q)
+ var/Qdist = get_dist(src, Q)
+ var/finder_icon = "finder_center" //Overlay showed when adjacent to or on top of the queen!
+ switch(Qdist)
+ if(2 to 7)
+ finder_icon = "finder_near"
+ if(8 to 20)
+ finder_icon = "finder_med"
+ if(21 to INFINITY)
+ finder_icon = "finder_far"
+ var/image/finder_eye = image('icons/hud/screen_alien.dmi', finder_icon, dir = Qdir)
+ hud_used.alien_queen_finder.add_overlay(finder_eye)
diff --git a/tff_modular/modules/tgmc_xenos/code/misc/resin_walker.dm b/tff_modular/modules/tgmc_xenos/code/misc/resin_walker.dm
new file mode 100644
index 00000000000..a7febfc3809
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/misc/resin_walker.dm
@@ -0,0 +1,33 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+// Полная копирка с /datum/element/web_walker
+/datum/element/resin_walker
+ element_flags = ELEMENT_BESPOKE
+ argument_hash_start_idx = 2
+
+ var/datum/movespeed_modifier/on_resin_modifier
+
+/datum/element/resin_walker/Attach(datum/target, datum/movespeed_modifier/on_resin_modifier = /datum/movespeed_modifier/resin_speedup)
+ . = ..()
+ if (!isliving(target))
+ return ELEMENT_INCOMPATIBLE
+ src.on_resin_modifier = on_resin_modifier
+
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved))
+
+/datum/element/resin_walker/Detach(datum/source)
+ . = ..()
+ UnregisterSignal(source, COMSIG_MOVABLE_MOVED)
+
+/datum/element/resin_walker/proc/on_moved(mob/living/source)
+ SIGNAL_HANDLER
+
+ var/obj/structure/alien/weeds/resin = locate() in get_turf(source)
+ if(resin)
+ source.add_movespeed_modifier(on_resin_modifier)
+ else
+ source.remove_movespeed_modifier(on_resin_modifier)
+
+
+/datum/movespeed_modifier/resin_speedup
+ multiplicative_slowdown = -0.5
diff --git a/tff_modular/modules/tgmc_xenos/code/misc/rouny_mode.dm b/tff_modular/modules/tgmc_xenos/code/misc/rouny_mode.dm
new file mode 100644
index 00000000000..189692db549
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/misc/rouny_mode.dm
@@ -0,0 +1,18 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+GLOBAL_VAR_INIT(xeno_rounymode, FALSE)
+#define ROUNY_ICON_FILE 'tff_modular/modules/tgmc_xenos/icons/rouny.dmi'
+
+/mob/living/carbon/alien/adult/tgmc/update_icon(updates)
+ if(GLOB.xeno_rounymode && icon_exists(ROUNY_ICON_FILE, icon_state))
+ icon = ROUNY_ICON_FILE
+ else if(icon == ROUNY_ICON_FILE)
+ icon = initial(icon)
+ return ..()
+
+/proc/toggle_rouny_mode()
+ GLOB.xeno_rounymode = !GLOB.xeno_rounymode
+ for(var/mob/living/carbon/alien/adult/tgmc/xeno in GLOB.alive_mob_list)
+ xeno.update_icon()
+
+#undef ROUNY_ICON_FILE
diff --git a/tff_modular/modules/tgmc_xenos/code/misc/tgmc_alien_event.dm b/tff_modular/modules/tgmc_xenos/code/misc/tgmc_alien_event.dm
new file mode 100644
index 00000000000..7685301efee
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/misc/tgmc_alien_event.dm
@@ -0,0 +1,12 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/tgmc
+ name = "TGMC Alien Infestation"
+ config_tag = "XenomorphTGMC"
+ ruleset_flags = parent_type::ruleset_flags | RULESET_VARIATION
+
+/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/tgmc/create_ruleset_body()
+ return new /mob/living/carbon/alien/larva/tgmc
+
+/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/tgmc/announce_xenos()
+ priority_announce("Unusual, highly active unidentified biological signatures detected boarding [station_name()]. All personnel must report irregular movement through maintenance corridors and environmental systems. Maintain vigilance and monitor for breaches.", "Lifesign Alert", ANNOUNCER_ALIENS)
diff --git a/tff_modular/modules/tgmc_xenos/code/misc/xeno_hud.dm b/tff_modular/modules/tgmc_xenos/code/misc/xeno_hud.dm
new file mode 100644
index 00000000000..657a4a0be44
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/misc/xeno_hud.dm
@@ -0,0 +1,35 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+/datum/atom_hud/data/xeno
+ hud_icons = list(XENO_HUD, XENOPLASMA_HUD)
+
+
+/mob/living/carbon/alien/adult/tgmc/med_hud_set_health()
+ xeno_hud_set_health()
+
+/mob/living/carbon/alien/adult/tgmc/adjustPlasma(amount)
+ . = ..()
+ xeno_hud_set_plasma()
+
+
+/mob/living/carbon/alien/adult/tgmc/proc/xeno_hud_set_health()
+ if(QDELETED(src))
+ return
+
+ var/amount = 0
+ if(stat != DEAD)
+ if(health < 0)
+ amount = round((health / (HEALTH_THRESHOLD_DEAD)) * -100, 10)
+ else
+ amount = CEILING((health / maxHealth) * 100, 10)
+ if(amount == 0)
+ amount = -1 //don't want the 'zero health' icon when we are crit
+
+ set_hud_image_state(XENO_HUD, "xenohealth[amount]", 32, -32)
+
+/mob/living/carbon/alien/adult/tgmc/proc/xeno_hud_set_plasma()
+ var/amount = 0
+ if((stat != DEAD) && (get_max_plasma() > 0))
+ amount = round(getPlasma() * 100 / get_max_plasma(), 10)
+
+ set_hud_image_state(XENOPLASMA_HUD, "plasma[amount]", 32, -32)
diff --git a/tff_modular/modules/tgmc_xenos/code/misc/xeno_shuttle.dm b/tff_modular/modules/tgmc_xenos/code/misc/xeno_shuttle.dm
new file mode 100644
index 00000000000..f338e1f09e7
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/misc/xeno_shuttle.dm
@@ -0,0 +1,4 @@
+/datum/map_template/shuttle/whiteship/xeno
+ name = "Abandoned Mining Shuttle"
+ prefix = "_maps/shuttles/fluffy/"
+ suffix = "xeno"
diff --git a/tff_modular/modules/tgmc_xenos/code/powers/acid_spit.dm b/tff_modular/modules/tgmc_xenos/code/powers/acid_spit.dm
new file mode 100644
index 00000000000..f8bb34e51e2
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/powers/acid_spit.dm
@@ -0,0 +1,178 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+// Наши личные нейротоксичные гланды, большую часть мехаана которых по хорошему бы на ТГ перенести, ведь у этих куда большая возможность настройки без боли
+/datum/action/cooldown/alien/acid/tgmc
+ name = "Spit Neurotoxin"
+ desc = "Spits neurotoxin at someone, exhausting them."
+ button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
+ button_icon_state = "neurospit_0"
+ shared_cooldown = MOB_SHARED_COOLDOWN_3
+ cooldown_time = 3 SECONDS
+ plasma_cost = 40
+ ranged_mousepointer = 'icons/effects/mouse_pointers/weapon_pointer.dmi'
+
+ /// A singular projectile? Use this one and leave acid_casing null
+ var/acid_projectile = /obj/projectile/neurotoxin/tgmc
+ /// You want it to be more like a shotgun style attack? Use this one and make acid_projectile null
+ var/acid_casing
+ /// Used in to_chat messages to the owner
+ var/projectile_name = "neurotoxin"
+ /// The base icon for the ability, so a red box can be put on it using _0 or _1
+ var/button_base_icon = "neurospit"
+ /// The sound that should be played when the xeno actually spits
+ var/spit_sound = 'tff_modular/modules/tgmc_xenos/sound/alien_spitacid.ogg'
+
+ // Костыль, чтобы выключать способность не сразу, а только при многократных нажатиях
+ var/too_much_clicks = 0
+
+/datum/action/cooldown/alien/acid/tgmc/IsAvailable(feedback = FALSE)
+ return ..() && isturf(owner.loc)
+
+/datum/action/cooldown/alien/acid/tgmc/set_click_ability(mob/on_who)
+ . = ..()
+ if(!.)
+ return
+
+ to_chat(on_who, span_notice("You prepare your [projectile_name] gland. Left-click to fire at a target!"))
+
+ button_icon_state = "[button_base_icon]_1"
+ build_all_button_icons()
+ on_who.update_icons()
+
+/datum/action/cooldown/alien/acid/tgmc/unset_click_ability(mob/on_who, refund_cooldown = TRUE)
+ . = ..()
+ if(!.)
+ return
+
+ if(refund_cooldown)
+ to_chat(on_who, span_notice("You empty your [projectile_name] gland."))
+
+ button_icon_state = "[button_base_icon]_0"
+ build_all_button_icons()
+ on_who.update_icons()
+
+/datum/action/cooldown/alien/acid/tgmc/InterceptClickOn(mob/living/clicker, params, atom/target)
+ . = ..()
+ if(!.)
+ if(too_much_clicks >= 2)
+ unset_click_ability(clicker, refund_cooldown = FALSE)
+ too_much_clicks = 0
+ else
+ too_much_clicks += 1
+ clicker.balloon_alert(clicker, "Not ready!")
+ return FALSE
+
+ too_much_clicks = 0
+ var/turf/user_turf = clicker.loc
+ var/turf/target_turf = get_step(clicker, target.dir)
+ if(!isturf(target_turf))
+ return FALSE
+
+ var/modifiers = params2list(params)
+ clicker.visible_message(
+ span_danger("[clicker] spits [projectile_name]!"),
+ span_alertalien("You spit [projectile_name]."),
+ )
+
+ if(acid_projectile)
+ var/obj/projectile/spit_projectile = new acid_projectile(clicker.loc)
+ spit_projectile.aim_projectile(target, clicker, modifiers)
+ spit_projectile.firer = clicker
+ spit_projectile.fire()
+ playsound(clicker, spit_sound, 100, TRUE, 5, 0.9)
+ clicker.newtonian_move(get_dir(target_turf, user_turf))
+ StartCooldown()
+ return TRUE
+
+ if(acid_casing)
+ var/obj/item/ammo_casing/casing = new acid_casing(clicker.loc)
+ playsound(clicker, spit_sound, 100, TRUE, 5, 0.9)
+ casing.fire_casing(target, clicker, null, null, null, ran_zone(), 0, clicker)
+ clicker.newtonian_move(get_dir(target_turf, user_turf))
+ StartCooldown()
+ return TRUE
+
+ CRASH("Neither acid_projectile or acid_casing are set on [clicker]'s spit attack!")
+
+/datum/action/cooldown/alien/acid/tgmc/Activate(atom/target)
+ return TRUE
+
+
+// Летальная версия плевка
+/datum/action/cooldown/alien/acid/tgmc/lethal
+ name = "Spit Acid"
+ desc = "Spits neurotoxin at someone, burning them."
+ acid_projectile = /obj/projectile/neurotoxin/tgmc/acid
+ button_icon_state = "acidspit_0"
+ projectile_name = "acid"
+ button_base_icon = "acidspit"
+
+
+// Королевские версии плевков нейротоксина
+/datum/action/cooldown/alien/acid/tgmc/queen
+ acid_projectile = /obj/projectile/neurotoxin/tgmc/queen
+ cooldown_time = 6 SECONDS
+
+/datum/action/cooldown/alien/acid/tgmc/lethal/queen
+ acid_projectile = /obj/projectile/neurotoxin/tgmc/acid/queen
+
+
+// Версия плевка нейротоксина, который работает как дробовик
+/datum/action/cooldown/alien/acid/tgmc/spread
+ name = "Spit Neurotoxin Spread"
+ desc = "Spits a spread neurotoxin at someone, exhausting them."
+ plasma_cost = 50
+ acid_projectile = null
+ acid_casing = /obj/item/ammo_casing/xenospit
+ spit_sound = 'tff_modular/modules/tgmc_xenos/sound/alien_spitacid2.ogg'
+ cooldown_time = 5 SECONDS
+
+// Немного хренового кода, но блин, какой же прошлый кодер крутой, что нашел такой забавный способ)
+/obj/item/ammo_casing/xenospit //This is probably really bad, however I couldn't find any other nice way to do this
+ name = "big glob of neurotoxin"
+ projectile_type = /obj/projectile/neurotoxin/tgmc/spitter_spread
+ pellets = 3
+ variance = 20
+
+/obj/item/ammo_casing/xenospit/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/caseless)
+
+/obj/item/ammo_casing/xenospit/tk_firing(mob/living/user, atom/fired_from)
+ return FALSE
+
+
+// Летальная версия дробовик-плевка
+/datum/action/cooldown/alien/acid/tgmc/spread/lethal
+ name = "Spit Acid Spread"
+ desc = "Spits a spread of acid at someone, burning them."
+ acid_projectile = null
+ acid_casing = /obj/item/ammo_casing/xenospit/spread/lethal
+ button_icon_state = "acidspit_0"
+ projectile_name = "acid"
+ button_base_icon = "acidspit"
+
+/obj/item/ammo_casing/xenospit/spread/lethal
+ name = "big glob of acid"
+ projectile_type = /obj/projectile/neurotoxin/tgmc/acid/spitter_spread
+ pellets = 4
+ variance = 30
+
+
+// Плевок кислоты
+/datum/action/cooldown/alien/acid/corrosion/tgmc
+ name = "Corrosive Acid (150)"
+ desc = "Drench an object in acid, destroying it over time."
+ button_icon_state = "alien_acid"
+ plasma_cost = 150
+ corrosion_acid_power = 100
+ corrosion_acid_volume = 500
+
+/datum/action/cooldown/alien/acid/corrosion/tgmc/strong
+ name = "Corrosive Acid (200)"
+ desc = "Drench an object in acid, destroying it over time."
+ button_icon_state = "alien_acid"
+ plasma_cost = 200
+ corrosion_acid_power = 400
+ corrosion_acid_volume = 1000
+
diff --git a/tff_modular/modules/tgmc_xenos/code/powers/xeno_charge.dm b/tff_modular/modules/tgmc_xenos/code/powers/xeno_charge.dm
new file mode 100644
index 00000000000..b0bf6ef85ea
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/powers/xeno_charge.dm
@@ -0,0 +1,183 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+// Чардж крашера
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge
+ name = "Charge Attack (125)"
+ desc = "Allows you to charge at a position, trampling anything in your path."
+ check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED | AB_CHECK_LYING
+ cooldown_time = 2 SECONDS
+ charge_delay = 0.3 SECONDS
+ charge_distance = 7
+ destroy_objects = FALSE
+ button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
+ button_icon_state = "crusher_charge"
+ unset_after_click = TRUE
+
+ var/living_damage = 40
+ var/living_paralyze_time = 5 SECONDS
+ var/sharpness = FALSE
+
+ var/obj_damage = 50
+ var/mecha_damage = 75
+ var/mecha_occupants_stun_time = 5 SECONDS
+ var/throw_mecha = TRUE
+
+ var/crush_walls = TRUE
+ var/crush_reinforced_walls = TRUE
+
+ var/plasma_cost = 125
+
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge/Grant(mob/granted_to)
+ . = ..()
+ RegisterSignal(granted_to, COMSIG_XENO_PLASMA_ADJUSTED, PROC_REF(on_owner_plasma_change))
+
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge/Remove(mob/removed_from)
+ . = ..()
+ UnregisterSignal(removed_from, COMSIG_XENO_PLASMA_ADJUSTED)
+
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge/proc/on_owner_plasma_change()
+ SIGNAL_HANDLER
+
+ build_all_button_icons()
+
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge/Activate(atom/target_atom)
+ var/mob/living/carbon/carbon_owner = owner
+ carbon_owner.adjustPlasma(-plasma_cost)
+ return ..()
+
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge/IsAvailable(feedback)
+ . = ..()
+ if(!.)
+ return FALSE
+ if(!istgmcalien(owner))
+ return FALSE
+ var/mob/living/carbon/carbon_owner = owner
+ if(carbon_owner.getPlasma() < plasma_cost)
+ return FALSE
+
+ return TRUE
+
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge/do_charge_indicator(atom/charger, atom/charge_target)
+ . = ..()
+ playsound(charger, 'tff_modular/modules/tgmc_xenos/sound/alien_roar1.ogg', 75, TRUE, 8, 0.9)
+
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge/on_moved(atom/source)
+ playsound(source, 'tff_modular/modules/tgmc_xenos/sound/alien_footstep_charge1.ogg', 100, TRUE, 2, TRUE)
+
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge/hit_target(atom/movable/source, atom/target, damage_dealt)
+ var/mob/living/carbon/alien/adult/tgmc/charger = owner
+
+ // Столокновение с существами
+ if(isliving(target))
+ var/mob/living/crushed_living = target
+ if(crushed_living.buckled)
+ crushed_living.buckled.unbuckle_mob(crushed_living)
+
+ log_combat(charger, crushed_living, "xeno charged")
+ var/damage = living_damage
+ crushed_living.apply_damage(damage, BRUTE, BODY_ZONE_CHEST, sharpness = sharpness)
+
+ if(crushed_living.density && (crushed_living.mob_size >= charger.mob_size))
+ charger.visible_message(span_danger("[charger] rams into [target] and skids to a halt!"), span_alertalien("We ram into [target] and skid to a halt!"))
+ do_stop()
+ return
+
+ var/fling_dir = pick((charger.dir & (NORTH|SOUTH)) ? list(WEST, EAST, charger.dir|WEST, charger.dir|EAST) : list(NORTH, SOUTH, charger.dir|NORTH, charger.dir|SOUTH))
+ var/fling_dist = rand(1, 3)
+ var/turf/destination = crushed_living.loc
+ var/turf/temp
+
+ for(var/i in 1 to fling_dist)
+ temp = get_step(destination, fling_dir)
+ if(!temp)
+ break
+ destination = temp
+
+ if(destination != crushed_living.loc)
+ crushed_living.throw_at(destination, fling_dist, 1, charger, TRUE)
+
+ crushed_living.Paralyze(living_paralyze_time)
+ charger.visible_message(span_danger("[charger] rams [target]!"), span_alertalien("We ram [target]!"))
+ return
+
+ // Столокновение с объектами
+ else if(isobj(target))
+ var/obj/crushed_obj = target
+ if(istype(crushed_obj, /obj/structure/alien))
+ return
+
+ var/damage = obj_damage
+ if(ismecha(target))
+ damage = mecha_damage
+ var/obj/vehicle/sealed/mecha/target_mecha = target
+ if(target_mecha.defense_mode)
+ damage /= 2
+ else if(istype(target, /obj/machinery/door/airlock))
+ damage = 1000 // Нужно сломать за 1 раз
+ do_stop()
+ else if(istype(target, /obj/structure/window))
+ damage = 1000 // Так же нужно сломать за 1 раз
+
+ crushed_obj.take_damage(damage, BRUTE)
+ if(QDELETED(crushed_obj))
+ charger.visible_message(span_danger("[charger] crushes [target]!"), span_alertalien("We crush [target]!"))
+ return
+
+ if(ismecha(target))
+ var/obj/vehicle/sealed/mecha/target_mecha = target
+
+ for(var/mob/living/occupant in target_mecha.occupants)
+ occupant.Stun(mecha_occupants_stun_time)
+
+ charger.visible_message(span_danger("[charger] rams into [target] and skids to a halt!"), span_alertalien("We ram into [target] and skid to a halt!"))
+ do_stop()
+
+ var/turf/throwtarget = get_edge_target_turf(source, get_dir(source, get_step_away(target, source)))
+ var/dist_from_source = get_dist(target, source)
+ if(throw_mecha && (target.max_integrity < 400) && (dist_from_source <= 1))
+ target_mecha.safe_throw_at(throwtarget, 1, 1, source, spin = FALSE, force = MOVE_FORCE_EXTREMELY_STRONG)
+
+ if(target_mecha.defense_mode)
+ target_mecha.use_energy(damage * (STANDARD_CELL_CHARGE / 50))
+ for(var/O in target_mecha.occupants)
+ var/mob/living/occupant = O
+ var/datum/action/vehicle/sealed/mecha/mech_defense_mode/action = LAZYACCESSASSOC(target_mecha.occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/mech_defense_mode)
+ if(isnull(action))
+ continue
+ action.Trigger(TRIGGER_FORCE_AVAILABLE, forced_state = TRUE)
+ break
+
+ return
+
+ if(crushed_obj.anchored)
+ charger.visible_message(span_danger("[charger] rams into [target] and skids to a halt!"), span_alertalien("We ram into [target] and skid to a halt!"))
+ do_stop()
+ return
+
+ charger.visible_message("[span_warning("[charger] knocks [target] aside.")]!", span_alertalien("We knock [target] aside."))
+ return
+
+ // Столокновение с турфами
+ else if(isturf(target))
+ var/turf/crushed_turf = target
+ if(crush_walls)
+ if(!isclosedturf(crushed_turf) || isindestructiblewall(crushed_turf))
+ return
+ if(!crush_reinforced_walls && istype(crushed_turf, /turf/closed/wall/r_wall))
+ return
+
+ crushed_turf.AddComponent(/datum/component/torn_wall)
+ if(!QDELETED(crushed_turf) && !istype(crushed_turf, /turf/closed/wall/r_wall))
+ crushed_turf.AddComponent(/datum/component/torn_wall)
+
+ if(QDELETED(crushed_turf))
+ charger.visible_message(span_danger("[charger] plows straight through [crushed_turf]!"), span_alertalien("We plow straight through [crushed_turf]!"))
+ return
+
+ charger.visible_message(span_danger("[charger] rams into [crushed_turf] and skids to a halt!"), span_alertalien("We ram into [crushed_turf] and skid to a halt!"))
+ do_stop()
+ return
+
+// Останавливает движение чарджера
+/datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge/proc/do_stop()
+ GLOB.move_manager.stop_looping(owner)
diff --git a/tff_modular/modules/tgmc_xenos/code/powers/xeno_powers.dm b/tff_modular/modules/tgmc_xenos/code/powers/xeno_powers.dm
new file mode 100644
index 00000000000..10be0adab2d
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/powers/xeno_powers.dm
@@ -0,0 +1,237 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+/datum/action/cooldown/alien/tgmc
+ button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
+ /// Some xeno abilities block other abilities from being used, this allows them to get around that in cases where it is needed
+ var/can_be_used_always = FALSE
+
+/datum/action/cooldown/alien/tgmc/IsAvailable(feedback = FALSE)
+ . = ..()
+ if(!.)
+ return FALSE
+
+ if(can_be_used_always)
+ return TRUE
+
+ var/mob/living/carbon/alien/adult/tgmc/owner_alien = owner
+ if(!istype(owner_alien) || owner_alien.unable_to_use_abilities)
+ return FALSE
+
+
+// Хил-аура дрона
+/datum/action/cooldown/alien/tgmc/heal_aura
+ name = "Healing Aura"
+ desc = "Friendly xenomorphs in a short range around yourself will receive passive healing."
+ button_icon_state = "healaura"
+ plasma_cost = 100
+ cooldown_time = 60 SECONDS
+ /// Is the healing aura currently active or not
+ var/aura_active = FALSE
+ /// How long the healing aura should last
+ var/aura_duration = 30 SECONDS
+ /// How far away the healing aura should reach
+ var/aura_range = 5
+ /// How much brute/burn individually the healing aura should heal each time it fires
+ var/aura_healing_amount = 5
+ /// What color should the + particles caused by the healing aura be
+ var/aura_healing_color = COLOR_BLUE_LIGHT
+ /// The healing aura component itself that the ability uses
+ var/datum/component/aura_healing/aura_healing_component
+
+/datum/action/cooldown/alien/tgmc/heal_aura/Activate()
+ . = ..()
+ if(aura_active)
+ owner.balloon_alert(owner, "already healing")
+ return FALSE
+ owner.balloon_alert(owner, "healing aura started")
+ to_chat(owner, span_danger("We emit pheromones that encourage sisters near us to heal themselves for the next [aura_duration / 10] seconds."))
+ addtimer(CALLBACK(src, PROC_REF(aura_deactivate)), aura_duration)
+ aura_active = TRUE
+ aura_healing_component = owner.AddComponent( \
+ /datum/component/aura_healing, \
+ range = aura_range, \
+ requires_visibility = TRUE, \
+ brute_heal = aura_healing_amount, \
+ burn_heal = aura_healing_amount, \
+ limit_to_trait = TRAIT_XENO_HEAL_AURA, \
+ healing_color = aura_healing_color, \
+ )
+ return TRUE
+
+/datum/action/cooldown/alien/tgmc/heal_aura/proc/aura_deactivate()
+ if(!aura_active)
+ return
+ aura_active = FALSE
+ QDEL_NULL(aura_healing_component)
+ owner.balloon_alert(owner, "healing aura ended")
+
+
+// Чуть более сильная хил-аура преторианца
+/datum/action/cooldown/alien/tgmc/heal_aura/juiced
+ name = "Strong Healing Aura"
+ desc = "Friendly xenomorphs in a longer range around yourself will receive passive healing."
+ button_icon_state = "healaura_juiced"
+ plasma_cost = 100
+ aura_range = 7
+ aura_healing_amount = 10
+ aura_healing_color = COLOR_RED_LIGHT
+
+
+// Все сказано в названии подтипа. Только равагер имеет такое
+#define RAVAGER_OUTLINE_EFFECT "ravager_endure_outline"
+
+/datum/action/cooldown/alien/tgmc/literally_too_angry_to_die
+ name = "Endure"
+ desc = "Imbue your body with unimaginable amounts of rage (and plasma) to allow yourself to ignore all pain for a short time."
+ button_icon_state = "literally_too_angry"
+ plasma_cost = 250 //This requires full plasma to do, so there can be some time between armstrong moments
+ /// If the endure ability is currently active or not
+ var/endure_active = FALSE
+ /// How long the endure ability should last when activated
+ var/endure_duration = 20 SECONDS
+
+/datum/action/cooldown/alien/tgmc/literally_too_angry_to_die/Activate()
+ . = ..()
+ if(endure_active)
+ owner.balloon_alert(owner, "already enduring")
+ return FALSE
+ owner.balloon_alert(owner, "endure began")
+ playsound(owner, 'tff_modular/modules/tgmc_xenos/sound/alien_roar1.ogg', 100, TRUE, 8, 0.9)
+ to_chat(owner, span_danger("We numb our ability to feel pain, allowing us to fight until the very last for the next [endure_duration/10] seconds."))
+ addtimer(CALLBACK(src, PROC_REF(endure_deactivate)), endure_duration)
+ owner.add_filter(RAVAGER_OUTLINE_EFFECT, 4, outline_filter(1, COLOR_RED_LIGHT))
+ ADD_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_XENO_ABILITY_GIVEN)
+ ADD_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAIT_XENO_ABILITY_GIVEN)
+ ADD_TRAIT(owner, TRAIT_NOHARDCRIT, TRAIT_XENO_ABILITY_GIVEN)
+ endure_active = TRUE
+ return TRUE
+
+/datum/action/cooldown/alien/tgmc/literally_too_angry_to_die/proc/endure_deactivate()
+ endure_active = FALSE
+ owner.balloon_alert(owner, "endure ended")
+ owner.remove_filter(RAVAGER_OUTLINE_EFFECT)
+ REMOVE_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_XENO_ABILITY_GIVEN)
+ REMOVE_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAIT_XENO_ABILITY_GIVEN)
+ REMOVE_TRAIT(owner, TRAIT_NOHARDCRIT, TRAIT_XENO_ABILITY_GIVEN)
+
+#undef RAVAGER_OUTLINE_EFFECT
+
+
+#define EVASION_VENTCRAWL_INABILTY_CD_PERCENTAGE 0.8
+#define RUNNER_BLUR_EFFECT "runner_evasion"
+
+/datum/action/cooldown/alien/tgmc/evade
+ name = "Evade"
+ desc = "Allows you to evade any projectile that would hit you for a few seconds."
+ button_icon_state = "evade"
+ plasma_cost = 50
+ cooldown_time = 60 SECONDS
+ /// If the evade ability is currently active or not
+ var/evade_active = FALSE
+ /// How long evasion should last
+ var/evasion_duration = 10 SECONDS
+
+/datum/action/cooldown/alien/tgmc/evade/Activate()
+ . = ..()
+ if(evade_active) //Can't evade while we're already evading.
+ owner.balloon_alert(owner, "already evading")
+ return FALSE
+
+ owner.balloon_alert(owner, "evasive movements began")
+ playsound(owner, 'tff_modular/modules/tgmc_xenos/sound/alien_hiss.ogg', 100, TRUE, 8, 0.9)
+ to_chat(owner, span_danger("We take evasive action, making us impossible to hit with projectiles for the next [evasion_duration / 10] seconds."))
+ addtimer(CALLBACK(src, PROC_REF(evasion_deactivate)), evasion_duration)
+ evade_active = TRUE
+ RegisterSignal(owner, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(on_projectile_hit))
+ REMOVE_TRAIT(owner, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+ addtimer(CALLBACK(src, PROC_REF(give_back_ventcrawl)), (cooldown_time * EVASION_VENTCRAWL_INABILTY_CD_PERCENTAGE)) //They cannot ventcrawl until the defined percent of the cooldown has passed
+ to_chat(owner, span_warning("We will be unable to crawl through vents for the next [(cooldown_time * EVASION_VENTCRAWL_INABILTY_CD_PERCENTAGE) / 10] seconds."))
+ return TRUE
+
+/// Handles deactivation of the xeno evasion ability, mainly unregistering the signal and giving a balloon alert
+/datum/action/cooldown/alien/tgmc/evade/proc/evasion_deactivate()
+ evade_active = FALSE
+ owner.balloon_alert(owner, "evasion ended")
+ UnregisterSignal(owner, COMSIG_ATOM_PRE_BULLET_ACT)
+
+/datum/action/cooldown/alien/tgmc/evade/proc/give_back_ventcrawl()
+ ADD_TRAIT(owner, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+ to_chat(owner, span_notice("We are rested enough to crawl through vents again."))
+
+/// Handles if either BULLET_ACT_HIT or BULLET_ACT_FORCE_PIERCE happens to something using the xeno evade ability
+/datum/action/cooldown/alien/tgmc/evade/proc/on_projectile_hit()
+ SIGNAL_HANDLER
+
+ if(owner.build_incapacitated(INCAPABLE_GRAB) || !isturf(owner.loc) || !evade_active)
+ return
+
+ owner.visible_message(span_danger("[owner] effortlessly dodges the projectile!"), span_userdanger("You dodge the projectile!"))
+ playsound(get_turf(owner), pick('sound/items/weapons/bulletflyby.ogg', 'sound/items/weapons/bulletflyby2.ogg', 'sound/items/weapons/bulletflyby3.ogg'), 75, TRUE)
+ owner.add_filter(RUNNER_BLUR_EFFECT, 2, gauss_blur_filter(5))
+ addtimer(CALLBACK(owner, TYPE_PROC_REF(/datum, remove_filter), RUNNER_BLUR_EFFECT), 0.5 SECONDS)
+ return COMPONENT_BULLET_PIERCED
+
+#undef EVASION_VENTCRAWL_INABILTY_CD_PERCENTAGE
+#undef RUNNER_BLUR_EFFECT
+
+
+// Способность дефендера становиться настоящей крепостью
+/datum/action/cooldown/alien/fortify
+ name = "Fortify"
+ desc = "Plant yourself for a large defensive boost."
+ check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED
+ cooldown_time = 2 SECONDS
+ button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
+ button_icon_state = "fortify"
+ active_overlay_icon_state = "ab_goldborder"
+
+ var/mob/living/carbon/alien/adult/tgmc/xeno_owner
+ var/datum/armor/fortify_armor_type = /datum/armor/fortify_armor
+
+/datum/armor/fortify_armor
+ bomb = 40
+ bullet = 75
+ laser = 75
+ fire = 75
+ melee = 50
+
+/datum/action/cooldown/alien/fortify/Destroy()
+ set_fortify(FALSE)
+ return ..()
+
+/datum/action/cooldown/alien/fortify/Grant(mob/granted_to)
+ . = ..()
+ xeno_owner = owner
+
+/datum/action/cooldown/alien/fortify/Activate(atom/target)
+ . = ..()
+ if(xeno_owner.fortify)
+ set_fortify(FALSE)
+ return
+
+ set_fortify(TRUE)
+
+/datum/action/cooldown/alien/fortify/is_action_active(atom/movable/screen/movable/action_button/current_button)
+ return (xeno_owner && xeno_owner.fortify)
+
+/datum/action/cooldown/alien/fortify/proc/set_fortify(on)
+ if(xeno_owner.fortify == on)
+ return
+ if(on && xeno_owner.body_position == LYING_DOWN)
+ xeno_owner.set_resting(FALSE, instant = TRUE)
+
+ if(on)
+ ADD_TRAIT(xeno_owner, TRAIT_IMMOBILIZED, TRAIT_XENO_FORTIFY)
+ to_chat(xeno_owner, span_alertalien("We tuck ourselves into a defensive stance."))
+ xeno_owner.set_armor(xeno_owner.get_armor().add_other_armor(fortify_armor_type))
+ else
+ REMOVE_TRAIT(xeno_owner, TRAIT_IMMOBILIZED, TRAIT_XENO_FORTIFY)
+ to_chat(xeno_owner, span_alertalien("We resume our normal stance."))
+ xeno_owner.set_armor(xeno_owner.get_armor().subtract_other_armor(fortify_armor_type))
+
+ xeno_owner.anchored = on
+ xeno_owner.fortify = on
+ xeno_owner.resist_heavy_hits = on
+ playsound(xeno_owner, 'sound/effects/stonedoor_openclose.ogg', 30, TRUE)
+ build_all_button_icons(UPDATE_BUTTON_OVERLAY)
+ xeno_owner.update_icons()
diff --git a/tff_modular/modules/tgmc_xenos/code/powers/xeno_tailsweep.dm b/tff_modular/modules/tgmc_xenos/code/powers/xeno_tailsweep.dm
new file mode 100644
index 00000000000..794afab302b
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/powers/xeno_tailsweep.dm
@@ -0,0 +1,150 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+// Взмах хвоста дефендера + является базовым для взмахов хвоста королевы и равагера
+/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep
+ name = "Crushing Tail Sweep"
+ desc = "Throw back attackers with a sweep of your tail, likely breaking some bones in the process."
+ check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED | AB_CHECK_LYING
+ cooldown_time = 60 SECONDS
+ aoe_radius = 1
+ button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
+ button_icon_state = "crush_tail"
+ sparkle_path = /obj/effect/temp_visual/dir_setting/tailsweep/defender
+
+ /// The sound that the tail sweep will make upon hitting something
+ var/impact_sound = 'sound/effects/clang.ogg'
+ /// How long mobs hit by the tailsweep should be knocked down for
+ var/knockdown_time = 4 SECONDS
+ /// How much damage tail sweep impacts should do to a mob
+ var/impact_damage = 30
+ /// What wound bonus should the tai sweep impact have
+ var/impact_wound_bonus = 20
+ /// What type of sharpness should this tail sweep have
+ var/impact_sharpness = FALSE
+ /// What type of damage should the tail sweep do
+ var/impact_damage_type = BRUTE
+ // Урон по мехам
+ var/vehicle_damage = 20
+ // Можем ли откинуть мех ударом хвоста
+ var/vehicle_throwing = TRUE
+ // Время стана оператора меха
+ var/mecha_occupant_stun_duration
+
+/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/Grant(mob/granted_to)
+ . = ..()
+ RegisterSignal(granted_to, COMSIG_XENO_PLASMA_ADJUSTED, PROC_REF(on_owner_plasma_change))
+
+/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/Remove(mob/removed_from)
+ UnregisterSignal(removed_from, COMSIG_XENO_PLASMA_ADJUSTED)
+ return ..()
+
+/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/proc/on_owner_plasma_change()
+ SIGNAL_HANDLER
+
+ build_all_button_icons()
+
+/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/IsAvailable(feedback = FALSE)
+ . = ..()
+ if(!.)
+ return FALSE
+
+ var/mob/living/carbon/alien/adult/tgmc/owner_alien = owner
+ if(!istype(owner_alien) || owner_alien.unable_to_use_abilities)
+ return FALSE
+
+/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/cast_on_thing_in_aoe(atom/movable/victim, atom/caster)
+ if(!isliving(victim) && !ismecha(victim))
+ return
+
+ if(isalien(victim))
+ return
+
+ var/turf/throwtarget = get_edge_target_turf(caster, get_dir(caster, get_step_away(victim, caster)))
+ var/dist_from_caster = get_dist(victim, caster)
+ if(isliving(victim))
+ var/mob/living/victim_living = victim
+ if(dist_from_caster <= 0)
+ victim_living.Knockdown(knockdown_time)
+ if(sparkle_path)
+ new sparkle_path(get_turf(victim_living), get_dir(caster, victim_living))
+ else
+ victim_living.Knockdown(knockdown_time * 2) //They are on the same turf as us, or... somewhere else, I'm not sure how but they are getting smacked down
+
+ victim_living.apply_damage(impact_damage, impact_damage_type, BODY_ZONE_CHEST, wound_bonus = impact_wound_bonus, sharpness = impact_sharpness)
+ shake_camera(victim_living, 4, 3)
+ playsound(victim_living, impact_sound, 100, TRUE, 8, 0.9)
+ victim.visible_message(span_danger("[caster]'s tail slams into [victim], throwing them back!"), span_userdanger("[caster]'s tail slams into you, throwing you back!"))
+
+ victim_living.safe_throw_at(throwtarget, ((clamp((max_throw - (clamp(dist_from_caster - 2, 0, dist_from_caster))), 3, max_throw))), 1, caster, force = repulse_force)
+
+ else if(ismecha(victim))
+ var/obj/vehicle/sealed/mecha/victim_mecha = victim
+ var/list/mob/occupants = victim_mecha.return_occupants()
+
+ for(var/mob/living/occupant in occupants)
+ if(!isliving(occupant))
+ continue
+ if(!isnull(mecha_occupant_stun_duration))
+ occupant.Stun(mecha_occupant_stun_duration)
+ shake_camera(occupant, 4, 3)
+ playsound(occupant, impact_sound, 100, TRUE, 8, 0.9)
+
+ victim_mecha.take_damage(vehicle_damage, impact_damage_type)
+ victim_mecha.visible_message(span_danger("[caster]'s tail slams into [victim], throwing them back!"), span_userdanger("[caster]'s tail slams into you, throwing you back!"))
+
+ if(vehicle_throwing)
+ if((victim_mecha.max_integrity < 400) && (dist_from_caster <= 1))
+ victim_mecha.safe_throw_at(throwtarget, 1, 1, caster, spin = FALSE, force = repulse_force)
+
+/obj/effect/temp_visual/dir_setting/tailsweep/defender
+ icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
+ icon_state = "crush_tail_anim"
+
+
+// Взмах хвоста преторианца
+/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/hard_throwing
+ name = "Flinging Tail Sweep"
+ desc = "Throw back attackers with a sweep of your tail that is much stronger than other aliens."
+
+ aoe_radius = 2
+ repulse_force = MOVE_FORCE_OVERPOWERING //Fuck everyone who gets hit by this tail in particular
+
+ button_icon_state = "throw_tail"
+
+ sparkle_path = /obj/effect/temp_visual/dir_setting/tailsweep/praetorian
+
+ impact_sound = 'sound/items/weapons/slap.ogg'
+ impact_damage = 20
+ impact_wound_bonus = 10
+
+ mecha_occupant_stun_duration = 1.2 SECONDS
+
+/obj/effect/temp_visual/dir_setting/tailsweep/praetorian
+ icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
+ icon_state = "throw_tail_anim"
+
+
+// Взмах хвоста равагера
+/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/slicing
+ name = "Slicing Tail Sweep"
+ desc = "Throw back attackers with a swipe of your tail, slicing them with its sharpened tip."
+
+ aoe_radius = 2
+
+ button_icon_state = "slice_tail"
+
+ sparkle_path = /obj/effect/temp_visual/dir_setting/tailsweep/ravager
+
+ sound = 'tff_modular/modules/tgmc_xenos/sound/alien_tail_swipe.ogg' //The defender's tail sound isn't changed because its big and heavy, this isn't
+
+ impact_sound = 'modular_nova/master_files/sound/weapons/bloodyslice.ogg'
+ impact_damage = 40
+ impact_sharpness = SHARP_EDGED
+
+ vehicle_damage = 10
+ mecha_occupant_stun_duration = null
+ vehicle_throwing = FALSE
+
+/obj/effect/temp_visual/dir_setting/tailsweep/ravager
+ icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
+ icon_state = "slice_tail_anim"
diff --git a/tff_modular/modules/tgmc_xenos/code/structures/alien_structures.dm b/tff_modular/modules/tgmc_xenos/code/structures/alien_structures.dm
new file mode 100644
index 00000000000..d9a4b91fb0d
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/structures/alien_structures.dm
@@ -0,0 +1,48 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+/obj/structure/alien/egg/tgmc
+ child_path = /obj/item/clothing/mask/facehugger/tgmc
+
+ var/leap_range = 2
+ var/return_timer
+
+/obj/structure/alien/egg/tgmc/Grow()
+ . = ..()
+ proximity_monitor.set_range(leap_range - 1)
+
+/obj/structure/alien/egg/tgmc/finish_bursting(kill = TRUE)
+ if(child)
+ var/obj/item/clothing/mask/facehugger/tgmc/child_hugger = child
+ child_hugger.forceMove(get_turf(src))
+ if(istype(child_hugger, child_path))
+ if(kill)
+ child_hugger.Die()
+ else
+ if(!child_hugger.ProximityLeap(leap_range))
+ return_timer = addtimer(CALLBACK(src, PROC_REF(return_child)), 15 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_DELETE_ME)
+ return ..()
+
+/obj/structure/alien/egg/tgmc/proc/return_child(obj/item/clothing/mask/facehugger/hugger)
+ if(isnull(hugger))
+ hugger = locate(child_path) in loc
+
+ if(isnull(hugger) || !istype(hugger, child_path))
+ return FALSE
+
+ hugger.forceMove(src)
+ child = hugger
+ proximity_monitor.set_range(leap_range - 1)
+
+ status = "grown"
+ update_appearance()
+ return TRUE
+
+/obj/structure/alien/egg/tgmc/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(istype(tool, child_path))
+ return return_child(tool) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_FAILURE
+ return ..()
+
+
+/obj/structure/alien/weeds/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
+ // Мы подняли температуру, при которой начинает наноситься урон до ~72 градусов. Иначе на какой-нибудь серенити обычный атмос улицы будет убивать резину
+ return exposed_temperature > 345
diff --git a/tff_modular/modules/tgmc_xenos/code/tgmc_alien_event.dm b/tff_modular/modules/tgmc_xenos/code/tgmc_alien_event.dm
deleted file mode 100644
index 27057d90b2e..00000000000
--- a/tff_modular/modules/tgmc_xenos/code/tgmc_alien_event.dm
+++ /dev/null
@@ -1,9 +0,0 @@
-
-/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/tgmc
- name = "TGMC Alien Infestation"
- config_tag = "Xenomorph"
- pref_flag = null
- preview_antag_datum = null
-
-/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/tgmc/create_ruleset_body()
- return new /mob/living/carbon/alien/larva/tgmc
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_bodyparts.dm b/tff_modular/modules/tgmc_xenos/code/xeno_bodyparts.dm
new file mode 100644
index 00000000000..2bfb32077ae
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_bodyparts.dm
@@ -0,0 +1,44 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+#define TGMC_ALIEN_BODYPART_BURN_MODIFIER 1.5
+
+
+/obj/item/bodypart/head/alien/tgmc
+ burn_modifier = TGMC_ALIEN_BODYPART_BURN_MODIFIER
+
+/obj/item/bodypart/chest/alien/tgmc
+ burn_modifier = TGMC_ALIEN_BODYPART_BURN_MODIFIER
+
+/obj/item/bodypart/arm/left/alien/tgmc
+ burn_modifier = TGMC_ALIEN_BODYPART_BURN_MODIFIER
+
+/obj/item/bodypart/arm/right/alien/tgmc
+ burn_modifier = TGMC_ALIEN_BODYPART_BURN_MODIFIER
+
+/obj/item/bodypart/leg/left/alien/tgmc
+ burn_modifier = TGMC_ALIEN_BODYPART_BURN_MODIFIER
+
+/obj/item/bodypart/leg/right/alien/tgmc
+ burn_modifier = TGMC_ALIEN_BODYPART_BURN_MODIFIER
+
+
+/mob/living/carbon/alien/adult/tgmc/newBodyPart(zone)
+ var/obj/item/bodypart/new_bodypart
+ switch(zone)
+ if(BODY_ZONE_L_ARM)
+ new_bodypart = new /obj/item/bodypart/arm/left/alien/tgmc()
+ if(BODY_ZONE_R_ARM)
+ new_bodypart = new /obj/item/bodypart/arm/right/alien/tgmc()
+ if(BODY_ZONE_HEAD)
+ new_bodypart = new /obj/item/bodypart/head/alien/tgmc()
+ if(BODY_ZONE_L_LEG)
+ new_bodypart = new /obj/item/bodypart/leg/left/alien/tgmc()
+ if(BODY_ZONE_R_LEG)
+ new_bodypart = new /obj/item/bodypart/leg/right/alien/tgmc()
+ if(BODY_ZONE_CHEST)
+ new_bodypart = new /obj/item/bodypart/chest/alien/tgmc()
+ if(new_bodypart)
+ new_bodypart.update_limb(is_creating = TRUE)
+
+
+#undef TGMC_ALIEN_BODYPART_BURN_MODIFIER
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_evolve.dm b/tff_modular/modules/tgmc_xenos/code/xeno_evolve.dm
new file mode 100644
index 00000000000..528aba80a41
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_evolve.dm
@@ -0,0 +1,84 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+/datum/action/cooldown/alien/tgmc/generic_evolve
+ name = "Evolve"
+ desc = "Allows us to evolve to a higher caste of our type, if there is not one already."
+ button_icon_state = "evolution"
+ /// What type this ability will turn the owner into upon completion
+ var/type_to_evolve_into
+
+/datum/action/cooldown/alien/tgmc/generic_evolve/Grant(mob/grant_to)
+ . = ..()
+ if(!isalien(owner))
+ return
+ var/mob/living/carbon/alien/target_alien = owner
+ plasma_cost = target_alien.get_max_plasma() //This ability should always require that a xeno be at their max plasma capacity to use
+
+/datum/action/cooldown/alien/tgmc/generic_evolve/Activate()
+ var/mob/living/carbon/alien/adult/tgmc/evolver = owner
+
+ if(!istype(evolver))
+ to_chat(owner, span_warning("You aren't an alien, you can't evolve!"))
+ return FALSE
+
+ type_to_evolve_into = evolver.next_evolution
+ if(!type_to_evolve_into)
+ to_chat(evolver, span_bolddanger("Something is wrong... We can't evolve into anything? (This is broken report it on GitHub)"))
+ CRASH("Couldn't find an evolution for [owner] ([owner.type]).")
+
+ if(!isturf(evolver.loc))
+ return FALSE
+
+ if(get_alien_type(type_to_evolve_into))
+ evolver.balloon_alert(evolver, "too many of our evolution already")
+ return FALSE
+
+ var/obj/item/organ/alien/hivenode/node = evolver.get_organ_by_type(/obj/item/organ/alien/hivenode)
+ if(!node)
+ to_chat(evolver, span_bolddanger("We can't sense our node's connection to the hive... We can't evolve!"))
+ return FALSE
+
+ if(node.recent_queen_death)
+ to_chat(evolver, span_bolddanger("The death of our queen... We can't seem to gather the mental energy required to evolve..."))
+ return FALSE
+
+ if(evolver.has_evolved_recently)
+ evolver.balloon_alert(evolver, "can evolve in 1.5 minutes") //Make that 1.5 variable later, but it keeps fucking up for me :(
+ return FALSE
+
+ var/new_beno = new type_to_evolve_into(evolver.loc)
+ evolver.alien_evolve(new_beno)
+ return TRUE
+
+
+/mob/living/carbon/alien/adult/tgmc/alien_evolve(mob/living/carbon/alien/adult/tgmc/new_xeno, is_it_a_larva)
+ visible_message(
+ span_alertalien("[src] begins to twist and contort!"),
+ span_noticealien("You begin to evolve!"),
+ )
+
+ new_xeno.setDir(dir)
+ new_xeno.identifier = identifier
+ new_xeno.name = new_xeno.real_name
+ new_xeno.set_name()
+
+ if(!islarva(new_xeno))
+ new_xeno.has_just_evolved()
+ if(mind)
+ mind.name = new_xeno.real_name
+ mind.transfer_to(new_xeno)
+ drop_all_held_items()
+ qdel(src)
+
+/// Called when a larva or xeno evolves, adds a configurable timer on evolving again to the xeno
+/mob/living/carbon/alien/adult/tgmc/proc/has_just_evolved()
+ if(has_evolved_recently)
+ return
+ has_evolved_recently = TRUE
+ addtimer(CALLBACK(src, PROC_REF(can_evolve_once_again)), evolution_cooldown_time)
+
+/// Allows xenos to evolve again if they are currently unable to
+/mob/living/carbon/alien/adult/tgmc/proc/can_evolve_once_again()
+ if(!has_evolved_recently)
+ return
+ has_evolved_recently = FALSE
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_organs.dm b/tff_modular/modules/tgmc_xenos/code/xeno_organs.dm
new file mode 100644
index 00000000000..bb544d92f43
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_organs.dm
@@ -0,0 +1,144 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+// Глазки ксенусей
+/obj/item/organ/eyes/alien/tgmc
+
+/obj/item/organ/eyes/alien/tgmc/apply_scar(side)
+ return // Нам не нужны слепые ксеносы из-за шрамов на глазах
+
+
+// Сосуды плазмы
+/obj/item/organ/alien/plasmavessel/tgmc
+ name = "plasma vessel"
+ icon_state = "plasma"
+ w_class = WEIGHT_CLASS_NORMAL
+ zone = BODY_ZONE_CHEST
+ slot = ORGAN_SLOT_XENO_PLASMAVESSEL
+ actions_types = list(
+ /datum/action/cooldown/alien/transfer,
+ )
+
+ stored_plasma = 100
+ max_plasma = 250
+ heal_rate = 1
+ plasma_rate = 5
+
+ var/resting_mult = 8
+
+/obj/item/organ/alien/plasmavessel/tgmc/on_life(seconds_per_tick, times_fired)
+ var/delta_time = DELTA_WORLD_TIME(SSmobs)
+ //Instantly healing to max health in a single tick would be silly. If it takes 8 seconds to fire, then something's fucked.
+ var/delta_time_capped = min(delta_time, 8)
+ //If there are alien weeds on the ground then heal if needed or give some plasma
+ if(locate(/obj/structure/alien/weeds) in owner.loc)
+ if(owner.health >= owner.maxHealth)
+ owner.adjustPlasma(plasma_rate * delta_time)
+ else
+ var/heal_amt = heal_rate
+ if(!isalien(owner))
+ heal_amt *= 0.2
+ if(owner.resting)
+ heal_amt *= resting_mult
+ heal_amt *= delta_time_capped
+
+ owner.adjustPlasma(0.5 * plasma_rate * delta_time_capped)
+ owner.adjust_brute_loss(-heal_amt)
+ owner.adjust_fire_loss(-heal_amt)
+ owner.adjust_oxy_loss(-heal_amt)
+ heal_owner_organs(heal_amt / 20)
+ else
+ owner.adjustPlasma(0.1 * plasma_rate * delta_time)
+
+/obj/item/organ/alien/plasmavessel/tgmc/proc/heal_owner_organs(heal_amount)
+ var/list/slots_to_heal = list(ORGAN_SLOT_BRAIN, ORGAN_SLOT_EYES, ORGAN_SLOT_LIVER, ORGAN_SLOT_EARS, ORGAN_SLOT_STOMACH)
+ for(var/slot in slots_to_heal)
+ owner.adjust_organ_loss(slot, -heal_amount)
+
+/obj/item/organ/alien/plasmavessel/tgmc/large
+ name = "large plasma vessel"
+ icon_state = "plasma_large"
+ w_class = WEIGHT_CLASS_BULKY
+ actions_types = list(
+ /datum/action/cooldown/alien/make_structure/plant_weeds,
+ /datum/action/cooldown/alien/transfer,
+ )
+ stored_plasma = 200
+ max_plasma = 500
+ plasma_rate = 7.5
+
+/obj/item/organ/alien/plasmavessel/tgmc/large/queen
+ plasma_rate = 10
+
+/obj/item/organ/alien/plasmavessel/tgmc/small
+ name = "small plasma vessel"
+ icon_state = "plasma_small"
+ w_class = WEIGHT_CLASS_SMALL
+ stored_plasma = 100
+ max_plasma = 150
+ plasma_rate = 2.5
+
+/obj/item/organ/alien/plasmavessel/tgmc/small/tiny
+ name = "tiny plasma vessel"
+ icon_state = "plasma_tiny"
+ w_class = WEIGHT_CLASS_TINY
+ max_plasma = 100
+ actions_types = list(/datum/action/cooldown/alien/transfer)
+
+
+// Яйцеклад королевы
+/obj/item/organ/alien/eggsac/tgmc
+ actions_types = list(/datum/action/cooldown/alien/make_structure/lay_egg/tgmc)
+
+/datum/action/cooldown/alien/make_structure/lay_egg/tgmc
+ plasma_cost = 150
+ made_structure_type = /obj/structure/alien/egg/tgmc
+
+
+// Ставилка резины
+/obj/item/organ/alien/resinspinner/tgmc
+ actions_types = list(/datum/action/cooldown/alien/make_structure/resin/tgmc)
+
+/datum/action/cooldown/alien/make_structure/resin/tgmc
+ build_duration = 1.5 SECONDS
+
+
+// Плевалка нейротоксина сентинела
+/obj/item/organ/alien/neurotoxin/tgmc
+ name = "neurotoxin gland"
+ icon_state = "neurotox"
+ zone = BODY_ZONE_PRECISE_MOUTH
+ slot = ORGAN_SLOT_XENO_NEUROTOXINGLAND
+ actions_types = list(
+ /datum/action/cooldown/alien/acid/tgmc,
+ /datum/action/cooldown/alien/acid/tgmc/lethal,
+ )
+
+// Плевалка нейротоксина у спиттера и претора
+/obj/item/organ/alien/neurotoxin/tgmc/large
+ name = "large neurotoxin gland"
+ actions_types = list(
+ /datum/action/cooldown/alien/acid/tgmc/spread,
+ /datum/action/cooldown/alien/acid/tgmc/spread/lethal,
+ )
+
+// Личная плевалка нейротоксина королевы
+/obj/item/organ/alien/neurotoxin/tgmc/queen
+ name = "abnormal neurotoxin gland"
+ actions_types = list(
+ /datum/action/cooldown/alien/acid/tgmc/queen,
+ /datum/action/cooldown/alien/acid/tgmc/lethal/queen,
+ )
+
+
+// Плевалка кислоты сентинела
+/obj/item/organ/alien/acid/tgmc
+ name = "acid gland"
+ icon_state = "acid"
+ zone = BODY_ZONE_PRECISE_MOUTH
+ slot = ORGAN_SLOT_XENO_ACIDGLAND
+ actions_types = list(/datum/action/cooldown/alien/acid/corrosion/tgmc)
+
+// Плевалка кислоты у спиттера, королевы и претора
+/obj/item/organ/alien/acid/tgmc/large
+ name = "large acid gland"
+ actions_types = list(/datum/action/cooldown/alien/acid/corrosion/tgmc/strong)
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/crusher.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/crusher.dm
new file mode 100644
index 00000000000..df4137f78f1
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_types/crusher.dm
@@ -0,0 +1,39 @@
+/// TGMC_XENOS (old nova sector xenos)
+
+/mob/living/carbon/alien/adult/tgmc/crusher
+ name = "alien crusher"
+ desc = "A huge alien with an enormous armored crest."
+ icon_state = "aliencrusher"
+ caste = "crusher"
+ maxHealth = 300
+ health = 300
+ mob_size = MOB_SIZE_LARGE
+ melee_damage_lower = 30
+ melee_damage_upper = 35
+ alien_speed = 2
+
+ armor_type = /datum/armor/tgmc_xeno/crusher
+
+ additional_organ_types_by_slot = list(
+ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/tgmc,
+ )
+
+ mecha_armor_penetration = 35
+ resist_heavy_hits = TRUE
+
+/mob/living/carbon/alien/adult/tgmc/crusher/Initialize(mapload)
+ . = ..()
+ var/static/list/innate_actions = list(
+ /datum/action/cooldown/mob_cooldown/charge/basic_charge/xeno_charge,
+ )
+ grant_actions_by_list(innate_actions)
+
+ REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+
+/datum/armor/tgmc_xeno/crusher
+ bomb = 20
+ bullet = 75
+ energy = 40
+ laser = 40
+ fire = 10
+ melee = 90
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/defender.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/defender.dm
index 42212974232..a7dd6ea3e81 100644
--- a/tff_modular/modules/tgmc_xenos/code/xeno_types/defender.dm
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_types/defender.dm
@@ -3,112 +3,47 @@
/mob/living/carbon/alien/adult/tgmc/defender
name = "alien defender"
desc = "A heavy looking alien with a wrecking ball-like tail that'd probably hurt to get hit by."
- caste = "defender"
- maxHealth = 300
- health = 300
icon_state = "aliendefender"
+ caste = "defender"
+ maxHealth = 225
+ health = 225
mob_size = MOB_SIZE_LARGE
melee_damage_lower = 25
melee_damage_upper = 30
- next_evolution = /mob/living/carbon/alien/adult/tgmc/warrior
+ alien_speed = 1.5
+ next_evolution = /mob/living/carbon/alien/adult/tgmc/crusher
+
+ armor_type = /datum/armor/tgmc_xeno/defender
additional_organ_types_by_slot = list(
- ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/small,
+ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/tgmc/small,
)
/mob/living/carbon/alien/adult/tgmc/defender/Initialize(mapload)
. = ..()
var/static/list/innate_actions = list(
/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep,
- /datum/action/cooldown/mob_cooldown/charge/basic_charge/defender,
+ /datum/action/cooldown/alien/fortify,
)
grant_actions_by_list(innate_actions)
REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
- add_movespeed_modifier(/datum/movespeed_modifier/alien_heavy)
-
-/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep
- name = "Crushing Tail Sweep"
- desc = "Throw back attackers with a sweep of your tail, likely breaking some bones in the process."
-
- cooldown_time = 60 SECONDS
-
- aoe_radius = 1
-
- button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
- button_icon_state = "crush_tail"
-
- sparkle_path = /obj/effect/temp_visual/dir_setting/tailsweep/defender
-
- /// The sound that the tail sweep will make upon hitting something
- var/impact_sound = 'sound/effects/clang.ogg'
- /// How long mobs hit by the tailsweep should be knocked down for
- var/knockdown_time = 4 SECONDS
- /// How much damage tail sweep impacts should do to a mob
- var/impact_damage = 30
- /// What wound bonus should the tai sweep impact have
- var/impact_wound_bonus = 20
- /// What type of sharpness should this tail sweep have
- var/impact_sharpness = FALSE
- /// What type of damage should the tail sweep do
- var/impact_damage_type = BRUTE
-
-/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/IsAvailable(feedback = FALSE)
- . = ..()
- if(!.)
- return FALSE
-
- var/mob/living/carbon/alien/adult/tgmc/owner_alien = owner
- if(!istype(owner_alien) || owner_alien.unable_to_use_abilities)
- return FALSE
-
-/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/cast_on_thing_in_aoe(atom/movable/victim, atom/caster)
- if(!isliving(victim))
- return
-
- if(isalien(victim))
- return
-
- var/turf/throwtarget = get_edge_target_turf(caster, get_dir(caster, get_step_away(victim, caster)))
- var/dist_from_caster = get_dist(victim, caster)
- var/mob/living/victim_living = victim
-
- if(dist_from_caster <= 0)
- victim_living.Knockdown(knockdown_time)
- if(sparkle_path)
- new sparkle_path(get_turf(victim_living), get_dir(caster, victim_living))
-
- else
- victim_living.Knockdown(knockdown_time * 2) //They are on the same turf as us, or... somewhere else, I'm not sure how but they are getting smacked down
-
- victim_living.apply_damage(impact_damage, impact_damage_type, BODY_ZONE_CHEST, wound_bonus = impact_wound_bonus, sharpness = impact_sharpness)
- shake_camera(victim_living, 4, 3)
- playsound(victim_living, impact_sound, 100, TRUE, 8, 0.9)
- to_chat(victim_living, span_userdanger("[caster]'s tail slams into you, throwing you back!"))
-
- victim_living.safe_throw_at(throwtarget, ((clamp((max_throw - (clamp(dist_from_caster - 2, 0, dist_from_caster))), 3, max_throw))), 1, caster, force = repulse_force)
-
-/obj/effect/temp_visual/dir_setting/tailsweep/defender
- icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
- icon_state = "crush_tail_anim"
-
-/datum/action/cooldown/mob_cooldown/charge/basic_charge/defender
- name = "Charge Attack"
- desc = "Allows you to charge at a position, trampling anything in your path."
- cooldown_time = 15 SECONDS
- charge_delay = 0.3 SECONDS
- charge_distance = 5
- destroy_objects = FALSE
- charge_damage = 50
- button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
- button_icon_state = "defender_charge"
- unset_after_click = TRUE
-
-/datum/action/cooldown/mob_cooldown/charge/basic_charge/defender/do_charge_indicator(atom/charger, atom/charge_target)
+/mob/living/carbon/alien/adult/tgmc/defender/update_icons()
. = ..()
- playsound(charger, 'tff_modular/modules/tgmc_xenos/sound/alien_roar1.ogg', 100, TRUE, 8, 0.9)
+ if(fortify)
+ icon_state = "alien[caste]_fortify"
-/datum/action/cooldown/mob_cooldown/charge/basic_charge/defender/Activate(atom/target_atom)
+/mob/living/carbon/alien/adult/tgmc/defender/set_stat()
. = ..()
- return TRUE
+ if(. == CONSCIOUS && fortify)
+ var/datum/action/cooldown/alien/fortify/fortify_action = locate() in actions
+ fortify_action.set_fortify(FALSE)
+
+/datum/armor/tgmc_xeno/defender
+ bomb = 30
+ bullet = 45
+ energy = 30
+ laser = 30
+ fire = 40
+ melee = 45
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/drone.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/drone.dm
index 865293f9682..df5ae317a3f 100644
--- a/tff_modular/modules/tgmc_xenos/code/xeno_types/drone.dm
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_types/drone.dm
@@ -3,60 +3,36 @@
/mob/living/carbon/alien/adult/tgmc/drone
name = "alien drone"
desc = "As plain looking as you could call an alien with armored black chitin and large claws."
- caste = "drone"
- maxHealth = 200
- health = 200
icon_state = "aliendrone"
+ caste = "drone"
+ maxHealth = 150
+ health = 150
melee_damage_lower = 15
melee_damage_upper = 20
next_evolution = /mob/living/carbon/alien/adult/tgmc/praetorian
+ armor_type = /datum/armor/tgmc_xeno/ravager
+
additional_organ_types_by_slot = list(
- ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/large,
- ORGAN_SLOT_XENO_RESINSPINNER = /obj/item/organ/alien/resinspinner,
+ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/tgmc/large,
+ ORGAN_SLOT_XENO_RESINSPINNER = /obj/item/organ/alien/resinspinner/tgmc,
ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid,
)
-/mob/living/carbon/alien/adult/tgmc/drone/Initialize(mapload)
- . = ..()
- GRANT_ACTION(/datum/action/cooldown/alien/tgmc/heal_aura)
-
-/datum/action/cooldown/alien/tgmc/heal_aura
- name = "Healing Aura"
- desc = "Friendly xenomorphs in a short range around yourself will receive passive healing."
- button_icon_state = "healaura"
- plasma_cost = 100
- cooldown_time = 90 SECONDS
- /// Is the healing aura currently active or not
- var/aura_active = FALSE
- /// How long the healing aura should last
- var/aura_duration = 30 SECONDS
- /// How far away the healing aura should reach
- var/aura_range = 5
- /// How much brute/burn individually the healing aura should heal each time it fires
- var/aura_healing_amount = 5
- /// What color should the + particles caused by the healing aura be
- var/aura_healing_color = COLOR_BLUE_LIGHT
- /// The healing aura component itself that the ability uses
- var/datum/component/aura_healing/aura_healing_component
+ maptext_height = 32
+ maptext_width = 32
-/datum/action/cooldown/alien/tgmc/heal_aura/Activate()
+/mob/living/carbon/alien/adult/tgmc/drone/Initialize(mapload)
. = ..()
- if(aura_active)
- owner.balloon_alert(owner, "already healing")
- return FALSE
- owner.balloon_alert(owner, "healing aura started")
- to_chat(owner, span_danger("We emit pheromones that encourage sisters near us to heal themselves for the next [aura_duration / 10] seconds."))
- addtimer(CALLBACK(src, PROC_REF(aura_deactivate)), aura_duration)
- aura_active = TRUE
- aura_healing_component = owner.AddComponent(/datum/component/aura_healing, range = aura_range, requires_visibility = TRUE, brute_heal = aura_healing_amount, burn_heal = aura_healing_amount, limit_to_trait = TRAIT_XENO_HEAL_AURA, healing_color = aura_healing_color)
- return TRUE
-
-/datum/action/cooldown/alien/tgmc/heal_aura/proc/aura_deactivate()
- if(!aura_active)
- return
- aura_active = FALSE
- QDEL_NULL(aura_healing_component)
- owner.balloon_alert(owner, "healing aura ended")
-
-
+ var/static/list/innate_actions = list(
+ /datum/action/cooldown/alien/tgmc/heal_aura,
+ )
+ grant_actions_by_list(innate_actions)
+
+/datum/armor/tgmc_xeno/ravager
+ bomb = 10
+ bullet = 30
+ energy = 30
+ laser = 30
+ fire = 30
+ melee = 30
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/praetorian.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/praetorian.dm
index 949b6eb54af..d080271696a 100644
--- a/tff_modular/modules/tgmc_xenos/code/xeno_types/praetorian.dm
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_types/praetorian.dm
@@ -3,22 +3,28 @@
/mob/living/carbon/alien/adult/tgmc/praetorian
name = "alien praetorian"
desc = "An alien that looks like the awkward half-way point between a queen and a drone, in fact that's likely what it is."
- caste = "praetorian"
- maxHealth = 400
- health = 400
icon_state = "alienpraetorian"
+ caste = "praetorian"
+ maxHealth = 250
+ health = 250
mob_size = MOB_SIZE_LARGE
melee_damage_lower = 25
melee_damage_upper = 30
+ alien_speed = 1.5
next_evolution = /mob/living/carbon/alien/adult/tgmc/queen
+ armor_type = /datum/armor/tgmc_xeno/praetorian
+
additional_organ_types_by_slot = list(
- ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/large,
- ORGAN_SLOT_XENO_RESINSPINNER = /obj/item/organ/alien/resinspinner,
- ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid,
- ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin/spitter,
+ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/tgmc/large,
+ ORGAN_SLOT_XENO_RESINSPINNER = /obj/item/organ/alien/resinspinner/tgmc,
+ ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid/tgmc/large,
+ ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin/tgmc/large,
)
+ mecha_armor_penetration = 30
+ resist_heavy_hits = TRUE
+
/mob/living/carbon/alien/adult/tgmc/praetorian/Initialize(mapload)
. = ..()
var/static/list/innate_actions = list(
@@ -29,92 +35,10 @@
REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
- add_movespeed_modifier(/datum/movespeed_modifier/alien_big)
-
-/datum/action/cooldown/alien/tgmc/heal_aura/juiced
- name = "Strong Healing Aura"
- desc = "Friendly xenomorphs in a longer range around yourself will receive passive healing."
- button_icon_state = "healaura_juiced"
- plasma_cost = 100
- cooldown_time = 90 SECONDS
- aura_range = 7
- aura_healing_amount = 10
- aura_healing_color = COLOR_RED_LIGHT
-
-/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/hard_throwing
- name = "Flinging Tail Sweep"
- desc = "Throw back attackers with a sweep of your tail that is much stronger than other aliens."
-
- aoe_radius = 2
- repulse_force = MOVE_FORCE_OVERPOWERING //Fuck everyone who gets hit by this tail in particular
-
- button_icon_state = "throw_tail"
-
- sparkle_path = /obj/effect/temp_visual/dir_setting/tailsweep/praetorian
-
- impact_sound = 'sound/items/weapons/slap.ogg'
- impact_damage = 20
- impact_wound_bonus = 10
-
-/obj/effect/temp_visual/dir_setting/tailsweep/praetorian
- icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
- icon_state = "throw_tail_anim"
-
-/datum/action/cooldown/alien/acid/tgmc/spread
- name = "Spit Neurotoxin Spread"
- desc = "Spits a spread neurotoxin at someone, exhausting them."
- plasma_cost = 50
- acid_projectile = null
- acid_casing = /obj/item/ammo_casing/xenospit
- spit_sound = 'tff_modular/modules/tgmc_xenos/sound/alien_spitacid2.ogg'
- cooldown_time = 10 SECONDS
-
-/obj/item/ammo_casing/xenospit //This is probably really bad, however I couldn't find any other nice way to do this
- name = "big glob of neurotoxin"
- projectile_type = /obj/projectile/neurotoxin/tgmc/spitter_spread
- pellets = 3
- variance = 20
-
-/obj/item/ammo_casing/xenospit/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/caseless)
-
-/obj/item/ammo_casing/xenospit/tk_firing(mob/living/user, atom/fired_from)
- return FALSE
-
-/obj/projectile/neurotoxin/tgmc/spitter_spread //Slightly nerfed because its a shotgun spread of these
- name = "neurotoxin spit"
- icon_state = "neurotoxin"
- damage = 25
-
-/datum/action/cooldown/alien/acid/tgmc/spread/lethal
- name = "Spit Acid Spread"
- desc = "Spits a spread of acid at someone, burning them."
- acid_projectile = null
- acid_casing = /obj/item/ammo_casing/xenospit/spread/lethal
- button_icon_state = "acidspit_0"
- projectile_name = "acid"
- button_base_icon = "acidspit"
-
-/obj/item/ammo_casing/xenospit/spread/lethal
- name = "big glob of acid"
- projectile_type = /obj/projectile/neurotoxin/tgmc/acid/spitter_spread
- pellets = 4
- variance = 30
-
-/obj/projectile/neurotoxin/tgmc/acid/spitter_spread
- name = "acid spit"
- icon_state = "toxin"
- damage = 15
- damage_type = BURN
-
-/obj/item/organ/alien/neurotoxin/spitter
- name = "large neurotoxin gland"
- icon_state = "neurotox"
- zone = BODY_ZONE_PRECISE_MOUTH
- slot = ORGAN_SLOT_XENO_NEUROTOXINGLAND
- actions_types = list(
- /datum/action/cooldown/alien/acid/tgmc/spread,
- /datum/action/cooldown/alien/acid/tgmc/spread/lethal,
- /datum/action/cooldown/alien/acid/corrosion,
- )
+/datum/armor/tgmc_xeno/praetorian
+ bomb = 10
+ bullet = 20
+ energy = 50
+ laser = 50
+ fire = 50
+ melee = 45
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/queen.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/queen.dm
index 4830659f5f2..b2bef7403d8 100644
--- a/tff_modular/modules/tgmc_xenos/code/xeno_types/queen.dm
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_types/queen.dm
@@ -3,26 +3,32 @@
/mob/living/carbon/alien/adult/tgmc/queen
name = "alien queen"
desc = "A hulking beast of an alien, for some reason this one seems more important than the others, you should probably quit staring at it and do something."
- caste = "queen"
- maxHealth = 500
- health = 500
icon_state = "alienqueen"
+ caste = "queen"
+ maxHealth = 300
+ health = 300
mob_size = MOB_SIZE_LARGE
melee_damage_lower = 30
melee_damage_upper = 35
+ alien_speed = 3
+
+ armor_type = /datum/armor/tgmc_xeno/queen
additional_organ_types_by_slot = list(
- ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/large/queen,
- ORGAN_SLOT_XENO_RESINSPINNER = /obj/item/organ/alien/resinspinner,
- ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid,
- ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin/queen,
+ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/tgmc/large/queen,
+ ORGAN_SLOT_XENO_RESINSPINNER = /obj/item/organ/alien/resinspinner/tgmc,
+ ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid/tgmc/large,
+ ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin/tgmc/queen,
ORGAN_SLOT_XENO_EGGSAC = /obj/item/organ/alien/eggsac/tgmc,
)
+ mecha_armor_penetration = 45
+ resist_heavy_hits = TRUE
+
+ can_hold_facehuggers = TRUE
+
/mob/living/carbon/alien/adult/tgmc/queen/Initialize(mapload)
. = ..()
- AddComponent(/datum/component/seethrough_mob) // Люркеров у нас нету (слава богу), но выдать такую штуку кому-то хочется... Будет у королевы, как на обычном ТГ
-
var/static/list/innate_actions = list(
/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/hard_throwing,
/datum/action/cooldown/alien/tgmc/queen_screech,
@@ -31,21 +37,16 @@
REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
- add_movespeed_modifier(/datum/movespeed_modifier/alien_big)
+/datum/armor/tgmc_xeno/queen
+ bomb = 30
+ bullet = 40
+ energy = 65
+ laser = 65
+ fire = 60
+ melee = 60
-/mob/living/carbon/alien/adult/tgmc/queen/alien_talk(message, shown_name = name)
- ..(message, shown_name, TRUE)
-
-/obj/item/organ/alien/neurotoxin/queen
- name = "neurotoxin gland"
- icon_state = "neurotox"
- zone = BODY_ZONE_PRECISE_MOUTH
- slot = ORGAN_SLOT_XENO_NEUROTOXINGLAND
- actions_types = list(
- /datum/action/cooldown/alien/acid/tgmc,
- /datum/action/cooldown/alien/acid/tgmc/lethal,
- /datum/action/cooldown/alien/acid/corrosion,
- )
+/mob/living/carbon/alien/adult/tgmc/queen/alien_talk(message, list/spans = list(), list/message_mods = list(), shown_name = name, big_voice = TRUE)
+ ..(message, spans, message_mods, shown_name, TRUE)
/mob/living/carbon/alien/adult/tgmc/queen/death(gibbed)
if(stat == DEAD)
@@ -66,7 +67,7 @@
name = "Deafening Screech"
desc = "Let out a screech so deafeningly loud that anything with the ability to hear around you will likely be incapacitated for a short time."
button_icon_state = "screech"
- cooldown_time = 5 MINUTES
+ cooldown_time = 3 MINUTES
/datum/action/cooldown/alien/tgmc/queen_screech/Activate()
. = ..()
@@ -75,10 +76,23 @@
queenie.create_shriekwave()
shake_camera(owner, 2, 2)
- for(var/mob/living/carbon/human/screech_target in get_hearers_in_view(7, get_turf(queenie)))
- screech_target.soundbang_act(intensity = 5, stun_pwr = 50, damage_pwr = 10, deafen_pwr = 30) //Only being deaf will save you from the screech
- shake_camera(screech_target, 4, 3)
- to_chat(screech_target, span_doyourjobidiot("[queenie] lets out a deafening screech!"))
+ owner.visible_message(span_doyourjobidiot("[queenie] lets out a deafening screech!"), self_message = span_revenbignotice("You emits an ear-splitting guttural roar!"))
+
+ for(var/mob/living/carbon/screech_target in get_hearers_in_range(9, get_turf(queenie)))
+
+ if(isalien(screech_target))
+ shake_camera(screech_target, 10, 1)
+ continue
+ else
+ shake_camera(screech_target, 30, 1)
+
+ var/distance_to_target = get_dist(queenie, screech_target)
+ if(distance_to_target <= 4)
+ to_chat(src, span_danger("An ear-splitting guttural roar shakes the ground beneath your feet!"))
+ screech_target.AdjustParalyzed(80)
+ else if(distance_to_target >= 5 && distance_to_target < 7)
+ to_chat(src, span_danger("The roar shakes your body to the core, freezing you in place!"))
+ screech_target.AdjustStun(40)
return TRUE
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/ravager.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/ravager.dm
index 041048c52fd..54a2a53c5c2 100644
--- a/tff_modular/modules/tgmc_xenos/code/xeno_types/ravager.dm
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_types/ravager.dm
@@ -1,105 +1,41 @@
/// TGMC_XENOS (old nova sector xenos)
-#define RAVAGER_OUTLINE_EFFECT "ravager_endure_outline"
-
/mob/living/carbon/alien/adult/tgmc/ravager
name = "alien ravager"
desc = "An alien with angry red chitin, with equally intimidating looking blade-like claws in place of normal hands. That sharp tail looks like it'd probably hurt."
- caste = "ravager"
- maxHealth = 350
- health = 350
icon_state = "alienravager"
+ caste = "ravager"
+ maxHealth = 200
+ health = 200
mob_size = MOB_SIZE_LARGE
melee_damage_lower = 30
melee_damage_upper = 35
+ alien_speed = 1.5
+
+ armor_type = /datum/armor/tgmc_xeno/ravager
additional_organ_types_by_slot = list(
- ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel
+ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/tgmc,
)
+ mecha_armor_penetration = 35
+ resist_heavy_hits = TRUE
+
/mob/living/carbon/alien/adult/tgmc/ravager/Initialize(mapload)
. = ..()
var/static/list/innate_actions = list(
/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/slicing,
/datum/action/cooldown/alien/tgmc/literally_too_angry_to_die,
- /datum/action/cooldown/mob_cooldown/charge/triple_charge/ravager,
)
grant_actions_by_list(innate_actions)
REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
-
-/datum/action/cooldown/mob_cooldown/charge/triple_charge/ravager
- name = "Triple Charge Attack"
- desc = "Allows you to charge thrice at a location, trampling any in your path."
- cooldown_time = 30 SECONDS
- charge_delay = 0.3 SECONDS
- charge_distance = 7
- charge_past = 3
- destroy_objects = FALSE
- charge_damage = 25
- button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
- button_icon_state = "ravager_charge"
- unset_after_click = TRUE
-
-/datum/action/cooldown/mob_cooldown/charge/triple_charge/ravager/do_charge_indicator(atom/charger, atom/charge_target)
- playsound(charger, 'tff_modular/modules/tgmc_xenos/sound/alien_roar2.ogg', 100, TRUE, 8, 0.9)
-
-/datum/action/cooldown/mob_cooldown/charge/triple_charge/ravager/Activate(atom/target_atom)
- . = ..()
- return TRUE
-
-/datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep/slicing
- name = "Slicing Tail Sweep"
- desc = "Throw back attackers with a swipe of your tail, slicing them with its sharpened tip."
-
- aoe_radius = 2
-
- button_icon_state = "slice_tail"
-
- sparkle_path = /obj/effect/temp_visual/dir_setting/tailsweep/ravager
-
- sound = 'tff_modular/modules/tgmc_xenos/sound/alien_tail_swipe.ogg' //The defender's tail sound isn't changed because its big and heavy, this isn't
-
- impact_sound = 'modular_nova/master_files/sound/weapons/bloodyslice.ogg'
- impact_damage = 40
- impact_sharpness = SHARP_EDGED
-
-/obj/effect/temp_visual/dir_setting/tailsweep/ravager
- icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
- icon_state = "slice_tail_anim"
-
-/datum/action/cooldown/alien/tgmc/literally_too_angry_to_die
- name = "Endure"
- desc = "Imbue your body with unimaginable amounts of rage (and plasma) to allow yourself to ignore all pain for a short time."
- button_icon_state = "literally_too_angry"
- plasma_cost = 250 //This requires full plasma to do, so there can be some time between armstrong moments
- /// If the endure ability is currently active or not
- var/endure_active = FALSE
- /// How long the endure ability should last when activated
- var/endure_duration = 20 SECONDS
-
-/datum/action/cooldown/alien/tgmc/literally_too_angry_to_die/Activate()
- . = ..()
- if(endure_active)
- owner.balloon_alert(owner, "already enduring")
- return FALSE
- owner.balloon_alert(owner, "endure began")
- playsound(owner, 'tff_modular/modules/tgmc_xenos/sound/alien_roar1.ogg', 100, TRUE, 8, 0.9)
- to_chat(owner, span_danger("We numb our ability to feel pain, allowing us to fight until the very last for the next [endure_duration/10] seconds."))
- addtimer(CALLBACK(src, PROC_REF(endure_deactivate)), endure_duration)
- owner.add_filter(RAVAGER_OUTLINE_EFFECT, 4, outline_filter(1, COLOR_RED_LIGHT))
- ADD_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_XENO_ABILITY_GIVEN)
- ADD_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAIT_XENO_ABILITY_GIVEN)
- ADD_TRAIT(owner, TRAIT_NOHARDCRIT, TRAIT_XENO_ABILITY_GIVEN)
- endure_active = TRUE
- return TRUE
-
-/datum/action/cooldown/alien/tgmc/literally_too_angry_to_die/proc/endure_deactivate()
- endure_active = FALSE
- owner.balloon_alert(owner, "endure ended")
- owner.remove_filter(RAVAGER_OUTLINE_EFFECT)
- REMOVE_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_XENO_ABILITY_GIVEN)
- REMOVE_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAIT_XENO_ABILITY_GIVEN)
- REMOVE_TRAIT(owner, TRAIT_NOHARDCRIT, TRAIT_XENO_ABILITY_GIVEN)
-
-#undef RAVAGER_OUTLINE_EFFECT
+ AddComponent(/datum/component/tackler, stamina_cost = 0, base_knockdown = 0, range = 6, speed = 2, skill_mod = 9, min_distance = 0)
+
+/datum/armor/tgmc_xeno/ravager
+ bomb = 10
+ bullet = 50
+ energy = 50
+ laser = 50
+ fire = 30
+ melee = 50
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/rouny.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/rouny.dm
index 8be26c1037a..e2fca1d2832 100644
--- a/tff_modular/modules/tgmc_xenos/code/xeno_types/rouny.dm
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_types/rouny.dm
@@ -1,89 +1,40 @@
/// TGMC_XENOS (old nova sector xenos)
-#define EVASION_VENTCRAWL_INABILTY_CD_PERCENTAGE 0.8
-#define RUNNER_BLUR_EFFECT "runner_evasion"
-
/mob/living/carbon/alien/adult/tgmc/runner
name = "alien runner"
desc = "A short alien with sleek red chitin, clearly abiding by the 'red ones go faster' theorem and almost always running on all fours."
- caste = "runner"
- maxHealth = 150
- health = 150
icon_state = "alienrunner"
- /// Holds the evade ability to be granted to the runner later
- var/datum/action/cooldown/alien/tgmc/evade/evade_ability
+ caste = "runner"
+ maxHealth = 125
+ health = 125
melee_damage_lower = 15
melee_damage_upper = 20
+ alien_speed = -0.5
next_evolution = /mob/living/carbon/alien/adult/tgmc/ravager
- on_fire_pixel_y = 0
+
+ armor_type = /datum/armor/tgmc_xeno/rouny
additional_organ_types_by_slot = list(
- ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/small/tiny,
+ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/tgmc/small/tiny,
)
+ maptext_height = 32
+ maptext_width = 32
+
+ /// Holds the evade ability to be granted to the runner later
+ var/datum/action/cooldown/alien/tgmc/evade/evade_ability
+
/mob/living/carbon/alien/adult/tgmc/runner/Initialize(mapload)
. = ..()
- AddComponent(/datum/component/tackler, stamina_cost = 0, base_knockdown = 2, range = 10, speed = 2, skill_mod = 7, min_distance = 0)
evade_ability = new(src)
evade_ability.Grant(src)
- add_movespeed_modifier(/datum/movespeed_modifier/alien_quick)
-
-/datum/action/cooldown/alien/tgmc/evade
- name = "Evade"
- desc = "Allows you to evade any projectile that would hit you for a few seconds."
- button_icon_state = "evade"
- plasma_cost = 50
- cooldown_time = 60 SECONDS
- /// If the evade ability is currently active or not
- var/evade_active = FALSE
- /// How long evasion should last
- var/evasion_duration = 10 SECONDS
-
-/datum/action/cooldown/alien/tgmc/evade/Activate()
- . = ..()
- if(evade_active) //Can't evade while we're already evading.
- owner.balloon_alert(owner, "already evading")
- return FALSE
-
- owner.balloon_alert(owner, "evasive movements began")
- playsound(owner, 'tff_modular/modules/tgmc_xenos/sound/alien_hiss.ogg', 100, TRUE, 8, 0.9)
- to_chat(owner, span_danger("We take evasive action, making us impossible to hit with projectiles for the next [evasion_duration / 10] seconds."))
- addtimer(CALLBACK(src, PROC_REF(evasion_deactivate)), evasion_duration)
- evade_active = TRUE
- RegisterSignal(owner, COMSIG_PROJECTILE_ON_HIT, PROC_REF(on_projectile_hit))
- REMOVE_TRAIT(owner, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
- addtimer(CALLBACK(src, PROC_REF(give_back_ventcrawl)), (cooldown_time * EVASION_VENTCRAWL_INABILTY_CD_PERCENTAGE)) //They cannot ventcrawl until the defined percent of the cooldown has passed
- to_chat(owner, span_warning("We will be unable to crawl through vents for the next [(cooldown_time * EVASION_VENTCRAWL_INABILTY_CD_PERCENTAGE) / 10] seconds."))
- return TRUE
-
-/// Handles deactivation of the xeno evasion ability, mainly unregistering the signal and giving a balloon alert
-/datum/action/cooldown/alien/tgmc/evade/proc/evasion_deactivate()
- evade_active = FALSE
- owner.balloon_alert(owner, "evasion ended")
- UnregisterSignal(owner, COMSIG_PROJECTILE_ON_HIT)
-
-/datum/action/cooldown/alien/tgmc/evade/proc/give_back_ventcrawl()
- ADD_TRAIT(owner, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
- to_chat(owner, span_notice("We are rested enough to crawl through vents again."))
-
-/// Handles if either BULLET_ACT_HIT or BULLET_ACT_FORCE_PIERCE happens to something using the xeno evade ability
-/datum/action/cooldown/alien/tgmc/evade/proc/on_projectile_hit()
- if(owner.build_incapacitated(INCAPABLE_GRAB) || !isturf(owner.loc) || !evade_active)
- return BULLET_ACT_HIT
-
- owner.visible_message(span_danger("[owner] effortlessly dodges the projectile!"), span_userdanger("You dodge the projectile!"))
- playsound(get_turf(owner), pick('sound/items/weapons/bulletflyby.ogg', 'sound/items/weapons/bulletflyby2.ogg', 'sound/items/weapons/bulletflyby3.ogg'), 75, TRUE)
- owner.add_filter(RUNNER_BLUR_EFFECT, 2, gauss_blur_filter(5))
- addtimer(CALLBACK(owner, TYPE_PROC_REF(/datum, remove_filter), RUNNER_BLUR_EFFECT), 0.5 SECONDS)
- return BULLET_ACT_FORCE_PIERCE
-
-/mob/living/carbon/alien/adult/tgmc/runner/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit = FALSE)
- if(evade_ability)
- var/evade_result = evade_ability.on_projectile_hit()
- if(!(evade_result == BULLET_ACT_HIT))
- return evade_result
- return ..()
+ AddComponent(/datum/component/tackler, stamina_cost = 0, base_knockdown = 2, range = 8, speed = 2, skill_mod = 4, min_distance = 0)
-#undef EVASION_VENTCRAWL_INABILTY_CD_PERCENTAGE
-#undef RUNNER_BLUR_EFFECT
+/datum/armor/tgmc_xeno/rouny
+ bomb = 0
+ bullet = 30
+ energy = 30
+ laser = 30
+ fire = 20
+ melee = 30
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/sentinel.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/sentinel.dm
index 92853ece5ae..85d3f08e52f 100644
--- a/tff_modular/modules/tgmc_xenos/code/xeno_types/sentinel.dm
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_types/sentinel.dm
@@ -3,142 +3,37 @@
/mob/living/carbon/alien/adult/tgmc/sentinel
name = "alien sentinel"
desc = "An alien that'd be unremarkable if not for the bright coloring and visible acid glands that cover it."
- caste = "sentinel"
- maxHealth = 200
- health = 200
icon_state = "aliensentinel"
+ caste = "sentinel"
+ maxHealth = 150
+ health = 150
melee_damage_lower = 10
melee_damage_upper = 15
+ alien_speed = 0.5
next_evolution = /mob/living/carbon/alien/adult/tgmc/spitter
+ armor_type = /datum/armor/tgmc_xeno/sentinel
+
additional_organ_types_by_slot = list(
- ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel,
- ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid,
- ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin/sentinel,
+ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/tgmc,
+ ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid/tgmc,
+ ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin/tgmc,
)
-/mob/living/carbon/alien/adult/tgmc/sentinel/Initialize(mapload)
- . = ..()
-
- add_movespeed_modifier(/datum/movespeed_modifier/alien_slow)
-
-/datum/action/cooldown/alien/acid/tgmc
- name = "Spit Neurotoxin"
- desc = "Spits neurotoxin at someone, exhausting them."
- button_icon = 'tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi'
- button_icon_state = "neurospit_0"
- plasma_cost = 40
- /// A singular projectile? Use this one and leave acid_casing null
- var/acid_projectile = /obj/projectile/neurotoxin/tgmc
- /// You want it to be more like a shotgun style attack? Use this one and make acid_projectile null
- var/acid_casing
- /// Used in to_chat messages to the owner
- var/projectile_name = "neurotoxin"
- /// The base icon for the ability, so a red box can be put on it using _0 or _1
- var/button_base_icon = "neurospit"
- /// The sound that should be played when the xeno actually spits
- var/spit_sound = 'tff_modular/modules/tgmc_xenos/sound/alien_spitacid.ogg'
- shared_cooldown = MOB_SHARED_COOLDOWN_3
- cooldown_time = 5 SECONDS
-
-/datum/action/cooldown/alien/acid/tgmc/IsAvailable(feedback = FALSE)
- return ..() && isturf(owner.loc)
-
-/datum/action/cooldown/alien/acid/tgmc/set_click_ability(mob/on_who)
- . = ..()
- if(!.)
- return
-
- to_chat(on_who, span_notice("You prepare your [projectile_name] gland. Left-click to fire at a target!"))
-
- button_icon_state = "[button_base_icon]_1"
- build_all_button_icons()
- on_who.update_icons()
-
-/datum/action/cooldown/alien/acid/tgmc/unset_click_ability(mob/on_who, refund_cooldown = TRUE)
- . = ..()
- if(!.)
- return
-
- if(refund_cooldown)
- to_chat(on_who, span_notice("You empty your [projectile_name] gland."))
+ maptext_height = 32
+ maptext_width = 32
- button_icon_state = "[button_base_icon]_0"
- build_all_button_icons()
- on_who.update_icons()
-
-/datum/action/cooldown/alien/acid/tgmc/InterceptClickOn(mob/living/clicker, params, atom/target)
+/mob/living/carbon/alien/adult/tgmc/sentinel/Initialize(mapload)
. = ..()
- if(!.)
- unset_click_ability(clicker, refund_cooldown = FALSE)
- return FALSE
-
- var/turf/user_turf = clicker.loc
- var/turf/target_turf = get_step(clicker, target.dir)
- if(!isturf(target_turf))
- return FALSE
-
- var/modifiers = params2list(params)
- clicker.visible_message(
- span_danger("[clicker] spits [projectile_name]!"),
- span_alertalien("You spit [projectile_name]."),
- )
-
- if(acid_projectile)
- var/obj/projectile/spit_projectile = new acid_projectile(clicker.loc)
- spit_projectile.aim_projectile(target, clicker, modifiers)
- spit_projectile.firer = clicker
- spit_projectile.fire()
- playsound(clicker, spit_sound, 100, TRUE, 5, 0.9)
- clicker.newtonian_move(get_dir(target_turf, user_turf))
- return TRUE
-
- if(acid_casing)
- var/obj/item/ammo_casing/casing = new acid_casing(clicker.loc)
- playsound(clicker, spit_sound, 100, TRUE, 5, 0.9)
- casing.fire_casing(target, clicker, null, null, null, ran_zone(), 0, clicker)
- clicker.newtonian_move(get_dir(target_turf, user_turf))
- return TRUE
-
- CRASH("Neither acid_projectile or acid_casing are set on [clicker]'s spit attack!")
-
-/datum/action/cooldown/alien/acid/tgmc/Activate(atom/target)
- return TRUE
-
-/obj/projectile/neurotoxin/tgmc
- name = "neurotoxin spit"
- icon_state = "neurotoxin"
- damage = 30
- paralyze = 0
- damage_type = STAMINA
- armor_flag = BIO
-
-/obj/projectile/neurotoxin/on_hit(atom/target, blocked = 0, pierce_hit)
- if(isalien(target))
- damage = 0
- return ..()
-
-/datum/action/cooldown/alien/acid/tgmc/lethal
- name = "Spit Acid"
- desc = "Spits neurotoxin at someone, burning them."
- acid_projectile = /obj/projectile/neurotoxin/tgmc/acid
- button_icon_state = "acidspit_0"
- projectile_name = "acid"
- button_base_icon = "acidspit"
-
-/obj/projectile/neurotoxin/tgmc/acid
- name = "acid spit"
- icon_state = "toxin"
- damage = 20
- paralyze = 0
- damage_type = BURN
-
-/obj/item/organ/alien/neurotoxin/sentinel
- name = "neurotoxin gland"
- icon_state = "neurotox"
- zone = BODY_ZONE_PRECISE_MOUTH
- slot = ORGAN_SLOT_XENO_NEUROTOXINGLAND
- actions_types = list(
- /datum/action/cooldown/alien/acid/tgmc,
- /datum/action/cooldown/alien/acid/tgmc/lethal,
+ var/static/list/innate_actions = list(
+ /datum/action/cooldown/mob_cooldown/sneak/alien,
)
+ grant_actions_by_list(innate_actions)
+
+/datum/armor/tgmc_xeno/sentinel
+ bomb = 10
+ bullet = 30
+ energy = 30
+ laser = 30
+ fire = 30
+ melee = 30
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/spitter.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/spitter.dm
index 84f7a086e04..66c562e6817 100644
--- a/tff_modular/modules/tgmc_xenos/code/xeno_types/spitter.dm
+++ b/tff_modular/modules/tgmc_xenos/code/xeno_types/spitter.dm
@@ -3,22 +3,35 @@
/mob/living/carbon/alien/adult/tgmc/spitter
name = "alien spitter"
desc = "A fairly heavy looking alien with prominent acid glands, it's mouth dripping with... some kind of toxin or acid."
- caste = "spitter"
- maxHealth = 300
- health = 300
icon_state = "alienspitter"
+ caste = "spitter"
+ maxHealth = 200
+ health = 200
mob_size = MOB_SIZE_LARGE
melee_damage_lower = 15
melee_damage_upper = 20
+ alien_speed = 1
+
+ armor_type = /datum/armor/tgmc_xeno/spitter
additional_organ_types_by_slot = list(
- ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel,
- ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin/spitter,
+ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/tgmc,
+ ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid/tgmc/large,
+ ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin/tgmc/large,
)
-/mob/living/carbon/alien/adult/tgmc/spitter/Initialize(mapload)
- . = ..()
+ resist_heavy_hits = TRUE
- add_movespeed_modifier(/datum/movespeed_modifier/alien_heavy)
+ can_hold_facehuggers = TRUE
+/mob/living/carbon/alien/adult/tgmc/spitter/Initialize(mapload)
+ . = ..()
REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+
+/datum/armor/tgmc_xeno/spitter
+ bomb = 0
+ bullet = 35
+ energy = 35
+ laser = 35
+ fire = 35
+ melee = 25
diff --git a/tff_modular/modules/tgmc_xenos/code/xeno_types/warrior.dm b/tff_modular/modules/tgmc_xenos/code/xeno_types/warrior.dm
deleted file mode 100644
index 754651165e9..00000000000
--- a/tff_modular/modules/tgmc_xenos/code/xeno_types/warrior.dm
+++ /dev/null
@@ -1,79 +0,0 @@
-/// TGMC_XENOS (old nova sector xenos)
-
-/mob/living/carbon/alien/adult/tgmc/warrior
- name = "alien warrior"
- desc = "If there are aliens to call walking tanks, this would be one of them, with both the heavy armor and strong arms to back that claim up."
- caste = "warrior"
- maxHealth = 400
- health = 400
- icon_state = "alienwarrior"
- mob_size = MOB_SIZE_LARGE
- melee_damage_lower = 30
- melee_damage_upper = 35
-
- additional_organ_types_by_slot = list(
- ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel
- )
-
-/mob/living/carbon/alien/adult/tgmc/warrior/Initialize(mapload)
- . = ..()
- var/static/list/innate_actions = list(
- /datum/action/cooldown/spell/aoe/repulse/xeno/tgmc_tailsweep,
- /datum/action/cooldown/mob_cooldown/charge/basic_charge/defender,
- /datum/action/cooldown/alien/tgmc/warrior_agility,
- )
- grant_actions_by_list(innate_actions)
-
- REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
-
- add_movespeed_modifier(/datum/movespeed_modifier/alien_big)
-
-/datum/action/cooldown/alien/tgmc/warrior_agility
- name = "Agility Mode"
- desc = "Drop onto all fours, increasing your speed at the cost of damage and being unable to use most abilities."
- button_icon_state = "the_speed_is_alot"
- cooldown_time = 1 SECONDS
- can_be_used_always = TRUE
- /// Is the warrior currently running around on all fours?
- var/being_agile = FALSE
-
-/datum/action/cooldown/alien/tgmc/warrior_agility/Activate()
- . = ..()
- if(!being_agile)
- begin_agility()
- return TRUE
- if(being_agile)
- end_agility()
- return TRUE
-
-/// Handles the visual indication and code activation of the warrior agility ability (say that five times fast)
-/datum/action/cooldown/alien/tgmc/warrior_agility/proc/begin_agility()
- var/mob/living/carbon/alien/adult/tgmc/agility_target = owner
- agility_target.balloon_alert(agility_target, "agility active")
- to_chat(agility_target, span_danger("We drop onto all fours, allowing us to move at much greater speed at expense of being able to use most abilities."))
- playsound(agility_target, 'tff_modular/modules/tgmc_xenos/sound/alien_hiss.ogg', 100, TRUE, 8, 0.9)
- agility_target.icon_state = "alien[agility_target.caste]_mobility"
-
- being_agile = TRUE
- agility_target.add_movespeed_modifier(/datum/movespeed_modifier/warrior_agility)
- agility_target.unable_to_use_abilities = TRUE
-
- agility_target.melee_damage_lower = 15
- agility_target.melee_damage_upper = 20
-
-/// Handles the visual indicators and code side of deactivating the agility ability
-/datum/action/cooldown/alien/tgmc/warrior_agility/proc/end_agility()
- var/mob/living/carbon/alien/adult/tgmc/agility_target = owner
- agility_target.balloon_alert(agility_target, "agility ended")
- playsound(agility_target, 'tff_modular/modules/tgmc_xenos/sound/alien_roar2.ogg', 100, TRUE, 8, 0.9) //Warrior runs up on all fours, stands upright, screams at you
- agility_target.icon_state = "alien[agility_target.caste]"
-
- being_agile = FALSE
- agility_target.remove_movespeed_modifier(/datum/movespeed_modifier/warrior_agility)
- agility_target.unable_to_use_abilities = FALSE
-
- agility_target.melee_damage_lower = initial(agility_target.melee_damage_lower)
- agility_target.melee_damage_upper = initial(agility_target.melee_damage_upper)
-
-/datum/movespeed_modifier/warrior_agility
- multiplicative_slowdown = -2
diff --git a/tff_modular/modules/tgmc_xenos/icons/big_xenos.dmi b/tff_modular/modules/tgmc_xenos/icons/big_xenos.dmi
index 2f1c5bb0022..3c7145742f5 100644
Binary files a/tff_modular/modules/tgmc_xenos/icons/big_xenos.dmi and b/tff_modular/modules/tgmc_xenos/icons/big_xenos.dmi differ
diff --git a/tff_modular/modules/tgmc_xenos/icons/rouny.dmi b/tff_modular/modules/tgmc_xenos/icons/rouny.dmi
new file mode 100644
index 00000000000..1ad615b4753
Binary files /dev/null and b/tff_modular/modules/tgmc_xenos/icons/rouny.dmi differ
diff --git a/tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi b/tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi
index 56b6273cbfe..e0a353375b5 100644
Binary files a/tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi and b/tff_modular/modules/tgmc_xenos/icons/xeno_actions.dmi differ
diff --git a/tff_modular/modules/tgmc_xenos/icons/xeno_hud.dmi b/tff_modular/modules/tgmc_xenos/icons/xeno_hud.dmi
new file mode 100644
index 00000000000..cffa55a943c
Binary files /dev/null and b/tff_modular/modules/tgmc_xenos/icons/xeno_hud.dmi differ
diff --git a/tff_modular/modules/tgmc_xenos/readme.md b/tff_modular/modules/tgmc_xenos/readme.md
new file mode 100644
index 00000000000..3be8b61a1f2
--- /dev/null
+++ b/tff_modular/modules/tgmc_xenos/readme.md
@@ -0,0 +1,55 @@
+# TGMC_ALIENS
+
+## Описание
+
+Модуль, добавляющий новых ксеноморфов. В прошлом эти ксеносы были на нове, до новы на скайрате, а те в свою очередь были портом ксеноморфов с ТГМС.
+
+## TG File Changes
+
+- MOVED:
+ code\modules\mob\living\carbon\human\human_defense.dm: `/mob/living/carbon/human/attack_alien`
+ TO:
+ tff_modular\modules\tgmc_xenos\code\defense\human_defense.dm
+- OVERRIDE: code\game\objects\structures\aliens.dm: `/obj/structure/alien/weeds/should_atmos_process`
+ IN:
+ tff_modular\modules\tgmc_xenos\code\structures\alien_structures.dm
+
+Additions:
+
+- code\game\objects\structures\aliens.dm: `/obj/structure/alien/egg` && `/obj/structure/alien/egg/Initialize()`
+- code\modules\mob\living\carbon\alien\special\alien_embryo.dm: `/obj/item/organ/body_egg/alien_embryo` && `/obj/item/organ/body_egg/alien_embryo/proc/on_poll_concluded()`
+- code\modules\mob\living\carbon\alien\special\facehugger.dm: `/obj/item/clothing/mask/facehugger` && `/obj/item/clothing/mask/facehugger/proc/Impregnate()`
+- code/modules/vehicles/mecha/\_mecha.dm: `/obj/vehicle/sealed/mecha/proc/melee_attack_effect()`
+
+## Defines
+
+IN: code/\_\_DEFINES/~ff_defines/\_globalvars/traits/declarations.dm
+
+Traits:
+
+- `TRAIT_XENO_INNATE`
+- `TRAIT_XENO_ABILITY_GIVEN`
+- `TRAIT_XENO_HEAL_AURA`
+- `TRAIT_XENO_FORTIFY`
+
+Global Vars:
+
+- `xeno_rounymode`
+
+## Helpers
+
+IN: code/\_\_HELPERS/~ff_helpers/is_helpers.dm
+
+- istgmcalien
+- istgmcalienqueen
+- istgmcalienpraetorian
+- istgmcalienravager
+- istgmcaliencrusher
+- istgmcalienspitter
+- istgmcalientier2
+
+## Credits
+
+TGMC & CM - Where the sprites, sound, and ideas for abilities came from
+
+Original developer of these xenos (apparently it's @Paxilmaniac) - Porting the xenos from TGMC and adopting their code to work with tg-skyrat build
diff --git a/tff_modular/modules/tgmc_xenos/sound/alien_footstep_charge1.ogg b/tff_modular/modules/tgmc_xenos/sound/alien_footstep_charge1.ogg
new file mode 100644
index 00000000000..e402b8bad46
Binary files /dev/null and b/tff_modular/modules/tgmc_xenos/sound/alien_footstep_charge1.ogg differ
diff --git a/tff_modular/modules/tgmc_xenos/sound/alien_help1.ogg b/tff_modular/modules/tgmc_xenos/sound/alien_help1.ogg
new file mode 100644
index 00000000000..9948030670f
Binary files /dev/null and b/tff_modular/modules/tgmc_xenos/sound/alien_help1.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index 90121272e88..c948fb126ee 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -422,13 +422,14 @@
#include "code\__DEFINES\~ff_defines\food_defines.dm"
#include "code\__DEFINES\~ff_defines\nabber_clothes_pathes.dm"
#include "code\__DEFINES\~ff_defines\say.dm"
+#include "code\__DEFINES\~ff_defines\signals.dm"
#include "code\__DEFINES\~ff_defines\span.dm"
#include "code\__DEFINES\~ff_defines\techweb_nodes.dm"
#include "code\__DEFINES\~ff_defines\text.dm"
#include "code\__DEFINES\~ff_defines\vv.dm"
#include "code\__DEFINES\~ff_defines\_globalvars\logging.dm"
#include "code\__DEFINES\~ff_defines\_globalvars\lists\blooper.dm"
-#include "code\__DEFINES\~ff_defines\_globalvars\traits\declarations.dm"
+#include "code\__DEFINES\~ff_defines\traits\declarations.dm"
#include "code\__DEFINES\~nova_defines\_flags.dm"
#include "code\__DEFINES\~nova_defines\_organ_defines.dm"
#include "code\__DEFINES\~nova_defines\access.dm"
@@ -9565,6 +9566,7 @@
#include "tff_modular\modules\cqd_holsters\code\holster_storage.dm"
#include "tff_modular\modules\cqd_holsters\code\utility.dm"
#include "tff_modular\modules\custom_huds\code\huds.dm"
+#include "tff_modular\modules\custom_huds\code\huds_for_ghosts.dm"
#include "tff_modular\modules\custom_objectives\code\custom_objectives.dm"
#include "tff_modular\modules\custom_revolution\code\rev_convert_item.dm"
#include "tff_modular\modules\custom_revolution\code\rev_custom_hud.dm"
@@ -9676,11 +9678,28 @@
#include "tff_modular\modules\species\scream_and_laugh.dm"
#include "tff_modular\modules\splurt_genitals\genitals.dm"
#include "tff_modular\modules\streletz\code\clothing.dm"
-#include "tff_modular\modules\tgmc_xenos\code\alien_egg.dm"
-#include "tff_modular\modules\tgmc_xenos\code\base_nova_xeno.dm"
-#include "tff_modular\modules\tgmc_xenos\code\human_defense.dm"
-#include "tff_modular\modules\tgmc_xenos\code\larva.dm"
-#include "tff_modular\modules\tgmc_xenos\code\tgmc_alien_event.dm"
+#include "tff_modular\modules\tgmc_xenos\code\base_alien.dm"
+#include "tff_modular\modules\tgmc_xenos\code\xeno_bodyparts.dm"
+#include "tff_modular\modules\tgmc_xenos\code\xeno_evolve.dm"
+#include "tff_modular\modules\tgmc_xenos\code\xeno_organs.dm"
+#include "tff_modular\modules\tgmc_xenos\code\defense\alien_defense.dm"
+#include "tff_modular\modules\tgmc_xenos\code\defense\human_defense.dm"
+#include "tff_modular\modules\tgmc_xenos\code\defense\mecha_defense.dm"
+#include "tff_modular\modules\tgmc_xenos\code\misc\attack_prevent_element.dm"
+#include "tff_modular\modules\tgmc_xenos\code\misc\larva.dm"
+#include "tff_modular\modules\tgmc_xenos\code\misc\projectiles.dm"
+#include "tff_modular\modules\tgmc_xenos\code\misc\queen_finder.dm"
+#include "tff_modular\modules\tgmc_xenos\code\misc\resin_walker.dm"
+#include "tff_modular\modules\tgmc_xenos\code\misc\rouny_mode.dm"
+#include "tff_modular\modules\tgmc_xenos\code\misc\tgmc_alien_event.dm"
+#include "tff_modular\modules\tgmc_xenos\code\misc\xeno_hud.dm"
+#include "tff_modular\modules\tgmc_xenos\code\misc\xeno_shuttle.dm"
+#include "tff_modular\modules\tgmc_xenos\code\powers\acid_spit.dm"
+#include "tff_modular\modules\tgmc_xenos\code\powers\xeno_charge.dm"
+#include "tff_modular\modules\tgmc_xenos\code\powers\xeno_powers.dm"
+#include "tff_modular\modules\tgmc_xenos\code\powers\xeno_tailsweep.dm"
+#include "tff_modular\modules\tgmc_xenos\code\structures\alien_structures.dm"
+#include "tff_modular\modules\tgmc_xenos\code\xeno_types\crusher.dm"
#include "tff_modular\modules\tgmc_xenos\code\xeno_types\defender.dm"
#include "tff_modular\modules\tgmc_xenos\code\xeno_types\drone.dm"
#include "tff_modular\modules\tgmc_xenos\code\xeno_types\praetorian.dm"
@@ -9689,7 +9708,6 @@
#include "tff_modular\modules\tgmc_xenos\code\xeno_types\rouny.dm"
#include "tff_modular\modules\tgmc_xenos\code\xeno_types\sentinel.dm"
#include "tff_modular\modules\tgmc_xenos\code\xeno_types\spitter.dm"
-#include "tff_modular\modules\tgmc_xenos\code\xeno_types\warrior.dm"
#include "tff_modular\modules\timed_citations\crime.dm"
#include "tff_modular\modules\title_screen\code\title_screen_html.dm"
#include "tff_modular\modules\toys\code\loadout_datum_toys.dm"