diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index a5993035d49..b9022006c5e 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -82,12 +82,6 @@ /obj/item/clothing/glasses/meson, /turf/open/floor/iron/dark, /area/mine/storage/public) -"as" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "av" = ( /obj/machinery/computer/arcade/orion_trail{ dir = 4 @@ -99,16 +93,14 @@ /obj/structure/cable, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"aF" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) -"aH" = ( -/obj/structure/railing{ - dir = 10 +"aI" = ( +/obj/effect/turf_decal/sand/plating/volcanic, +/obj/structure/railing/corner/end/flip{ + dir = 4 }, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) +/obj/structure/marker_beacon/purple, +/turf/open/floor/plating/lavaland_atmos, +/area/lavaland/surface/outdoors) "aM" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "lavaland_living_east_maint" @@ -153,20 +145,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/mine/maintenance/service) -"aX" = ( -/obj/effect/turf_decal/sand/plating/volcanic, -/obj/structure/railing{ - dir = 9 - }, -/turf/open/floor/plating/lavaland_atmos, -/area/lavaland/surface/outdoors) -"ba" = ( -/obj/structure/chair/sofa/middle{ - dir = 1; - color = "#AA4A44" - }, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "bb" = ( /obj/structure/closet/crate/internals, /obj/item/tank/internals/emergency_oxygen, @@ -184,13 +162,6 @@ dir = 4 }, /area/mine/laborcamp/production) -"be" = ( -/obj/machinery/door/airlock/external/glass{ - name = "Raptor Ranch External Airlock" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/turf/open/floor/plating/lavaland_atmos, -/area/mine/lobby/raptor) "bf" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth_large, @@ -220,6 +191,13 @@ }, /turf/open/floor/iron/edge, /area/mine/lounge) +"bx" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/item/flashlight/lantern/on, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "by" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/siding/wideplating_new{ @@ -234,10 +212,10 @@ }, /turf/open/floor/plating, /area/mine/maintenance/production) -"bE" = ( -/obj/structure/table/wood, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) +"bD" = ( +/obj/structure/railing/corner, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "bH" = ( /obj/structure/table, /obj/item/book/manual/chef_recipes{ @@ -296,6 +274,10 @@ /obj/machinery/mining_weather_monitor/directional/north, /turf/open/floor/iron/dark/smooth_edge, /area/mine/production) +"bY" = ( +/obj/effect/spawner/random/lavaland_mob/raptor/young, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "cb" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -470,6 +452,10 @@ dir = 4 }, /area/mine/lounge) +"cO" = ( +/obj/effect/spawner/random/lavaland_mob/raptor/young, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "cQ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/airalarm/directional/south, @@ -629,19 +615,6 @@ /obj/structure/lattice/catwalk/mining, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) -"dF" = ( -/obj/structure/table/wood, -/obj/item/food/meat/slab, -/obj/item/food/meat/slab{ - pixel_x = 6; - pixel_y = 5 - }, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) -"dI" = ( -/obj/machinery/light/small/directional/east, -/turf/open/floor/plating/lavaland_atmos, -/area/mine/lobby/raptor) "dJ" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -682,6 +655,10 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"eb" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/lavaland/surface/outdoors) "ee" = ( /obj/machinery/shower/directional/south, /obj/machinery/door/window/right/directional/south, @@ -712,6 +689,13 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"ev" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/structure/ore_container/food_trough/raptor_trough, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "ey" = ( /obj/structure/lattice/catwalk/mining, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -781,12 +765,6 @@ dir = 8 }, /area/mine/cafeteria) -"eL" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "eN" = ( /obj/structure/chair/wood{ dir = 1 @@ -834,9 +812,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/mine/laborcamp/security/maintenance) -"fa" = ( -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "fb" = ( /obj/structure/railing/corner{ dir = 4 @@ -899,6 +874,24 @@ }, /turf/open/floor/iron/checker, /area/mine/cafeteria) +"fw" = ( +/obj/effect/turf_decal/trimline/yellow/filled/arrow_cw{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/red/filled/arrow_cw{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/filled/mid_joiner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/red/filled/mid_joiner{ + dir = 4 + }, +/obj/structure/tank_holder/extinguisher, +/turf/open/floor/iron/dark/textured_corner{ + dir = 8 + }, +/area/mine/production) "fx" = ( /obj/structure/railing, /obj/effect/turf_decal/stripes/line{ @@ -917,6 +910,13 @@ /obj/item/radio/intercom/directional/west, /turf/open/floor/iron/dark, /area/mine/production) +"fB" = ( +/obj/structure/lattice/catwalk/mining, +/obj/structure/railing{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors) "fD" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -1288,10 +1288,6 @@ /obj/structure/sign/poster/official/cleanliness/directional/north, /turf/open/floor/iron/freezer, /area/mine/living_quarters) -"hl" = ( -/obj/structure/tank_holder/extinguisher, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "hn" = ( /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 9 @@ -1345,6 +1341,12 @@ /obj/structure/lattice/catwalk, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"hA" = ( +/obj/structure/railing{ + dir = 8 + }, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "hB" = ( /obj/structure/cable, /obj/machinery/light/directional/north, @@ -1410,13 +1412,6 @@ /obj/structure/stone_tile, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"hM" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/machinery/light/directional/south, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "hR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1516,10 +1511,6 @@ /obj/item/clothing/glasses/meson, /turf/open/floor/iron/dark, /area/mine/storage/public) -"il" = ( -/obj/item/flashlight/lantern/on, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "io" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1592,6 +1583,16 @@ }, /turf/open/floor/iron/checker, /area/mine/cafeteria) +"iL" = ( +/obj/item/reagent_containers/cup/bucket/wooden{ + pixel_y = 12; + pixel_x = 10 + }, +/obj/structure/chair/plastic{ + dir = 4 + }, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "iN" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1713,10 +1714,6 @@ }, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) -"jt" = ( -/obj/structure/fireplace, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "jw" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -1761,11 +1758,6 @@ }, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) -"jJ" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "jL" = ( /obj/structure/stone_tile/surrounding_tile, /obj/structure/stone_tile/surrounding_tile{ @@ -1815,13 +1807,6 @@ dir = 8 }, /area/mine/production) -"jX" = ( -/obj/effect/turf_decal/siding/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) "ka" = ( /obj/structure/table, /obj/machinery/newscaster/directional/north, @@ -1832,19 +1817,9 @@ }, /turf/open/floor/iron/checker, /area/mine/cafeteria) -"kf" = ( -/obj/structure/railing{ - dir = 9 - }, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "kg" = ( /turf/closed/wall/r_wall, /area/mine/laborcamp) -"ki" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating/lavaland_atmos, -/area/mine/lobby/raptor) "kk" = ( /obj/structure/stone_tile/block{ dir = 8 @@ -1883,6 +1858,11 @@ /obj/structure/cable, /turf/open/floor/plating, /area/mine/maintenance/living/north) +"kz" = ( +/obj/structure/lattice/catwalk/mining, +/obj/structure/railing, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors) "kB" = ( /obj/structure/stone_tile/surrounding_tile, /obj/structure/stone_tile/surrounding_tile{ @@ -2024,6 +2004,13 @@ /obj/effect/turf_decal/tile/brown/fourcorners, /turf/open/floor/iron/dark, /area/mine/production) +"lf" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/ore_container/food_trough/raptor_trough, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "lg" = ( /obj/machinery/computer/order_console/mining, /obj/effect/turf_decal/trimline/brown/filled/line{ @@ -2198,7 +2185,10 @@ name = "Mining Shuttle Airlock" }, /obj/effect/mapping_helpers/airlock/access/any/supply/mining, -/obj/effect/mapping_helpers/airlock/access/any/supply/mining, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/iron/dark/textured_large, /area/mine/production) "lN" = ( @@ -2328,17 +2318,6 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"mk" = ( -/obj/structure/table/wood, -/obj/item/raptor_dex{ - pixel_y = 13 - }, -/obj/item/raptor_dex{ - pixel_y = 7 - }, -/obj/item/raptor_dex, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "ml" = ( /obj/structure/stone_tile/block/cracked{ dir = 8 @@ -2752,12 +2731,6 @@ /obj/effect/spawner/random/trash/food_packaging, /turf/open/floor/iron/checker, /area/mine/laborcamp) -"nO" = ( -/obj/structure/railing{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "nP" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/portable_atmospherics/scrubber, @@ -2889,6 +2862,13 @@ /obj/effect/turf_decal/trimline/brown/filled/line, /turf/open/floor/iron/dark/textured_large, /area/mine/production) +"ow" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/structure/flora/ash/fireblossom, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "oy" = ( /obj/structure/lattice/catwalk/mining, /obj/structure/railing{ @@ -2935,15 +2915,6 @@ /obj/effect/turf_decal/trimline/green/filled/line, /turf/open/floor/iron/dark, /area/mine/laborcamp) -"oO" = ( -/obj/machinery/door/airlock/external/glass{ - name = "Mining External Airlock" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 - }, -/turf/open/floor/plating/lavaland_atmos, -/area/mine/lobby/raptor) "oS" = ( /obj/machinery/door/airlock/external/glass{ name = "Mining External Airlock" @@ -3090,12 +3061,6 @@ }, /turf/open/floor/plating, /area/mine/laborcamp) -"pF" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 - }, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "pH" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -3121,10 +3086,6 @@ /obj/structure/sign/poster/official/cleanliness/directional/north, /turf/open/floor/iron/freezer, /area/mine/laborcamp/quarters) -"pM" = ( -/obj/structure/bookcase/random/reference, -/turf/open/floor/wood, -/area/mine/lobby/raptor) "pO" = ( /obj/machinery/shower/directional/south, /obj/machinery/door/window/left/directional/south, @@ -3284,11 +3245,6 @@ }, /turf/open/floor/iron/dark, /area/mine/laborcamp/security) -"qB" = ( -/obj/machinery/smartfridge/drying/rack, -/obj/item/food/cheese/firm_cheese, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "qH" = ( /obj/machinery/door/airlock{ id_tag = "miningbathroomprivate"; @@ -3348,35 +3304,6 @@ }, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) -"rf" = ( -/obj/machinery/airalarm/directional/north, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) -"rj" = ( -/obj/item/food/grown/grass/fairy{ - name = "weird hay"; - desc = "Somehow, somewhere, this tells you it should increase your friendship level with your animals. Too bad that doesn't work, right?"; - pixel_y = -1; - pixel_x = 5 - }, -/obj/item/food/grown/grass/fairy{ - name = "weird hay"; - desc = "Somehow, somewhere, this tells you it should increase your friendship level with your animals. Too bad that doesn't work, right?"; - pixel_y = 9; - pixel_x = 8 - }, -/obj/item/food/grown/grass/fairy{ - name = "weird hay"; - desc = "Somehow, somewhere, this tells you it should increase your friendship level with your animals. Too bad that doesn't work, right?"; - pixel_y = 9; - pixel_x = 2 - }, -/obj/item/food/grown/grass/fairy{ - name = "weird hay"; - desc = "Somehow, somewhere, this tells you it should increase your friendship level with your animals. Too bad that doesn't work, right?" - }, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "rm" = ( /obj/structure/sign/warning/gas_mask/directional/west, /obj/effect/decal/cleanable/dirt, @@ -3390,6 +3317,10 @@ }, /turf/open/floor/iron/smooth, /area/mine/laborcamp) +"rt" = ( +/obj/structure/flora/ash/leaf_shroom, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "rv" = ( /obj/effect/turf_decal/trimline/brown/filled/line, /turf/open/floor/iron/dark/smooth_edge{ @@ -3418,13 +3349,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/mine/maintenance/service) -"rB" = ( -/obj/structure/chair/sofa/corner{ - dir = 1; - color = "#AA4A44" - }, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "rF" = ( /turf/closed/wall/r_wall, /area/mine/maintenance/labor) @@ -3495,11 +3419,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/mine/maintenance/service) -"sa" = ( -/obj/structure/table/wood, -/obj/item/flashlight/lantern/on, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "se" = ( /turf/open/floor/iron/dark/textured_large, /area/mine/eva) @@ -3596,10 +3515,6 @@ "sO" = ( /turf/open/floor/plating, /area/mine/maintenance/service) -"sQ" = ( -/obj/structure/ore_container/food_trough/raptor_trough, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "sR" = ( /obj/machinery/light/small/directional/west, /obj/effect/decal/cleanable/dirt, @@ -3662,6 +3577,12 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/carpet, /area/mine/living_quarters) +"td" = ( +/obj/structure/railing/corner/end{ + dir = 8 + }, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "te" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -3672,13 +3593,6 @@ dir = 4 }, /area/mine/cafeteria) -"tf" = ( -/obj/structure/chair/sofa/corner{ - dir = 8; - color = "#AA4A44" - }, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "tg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/door/airlock/maintenance{ @@ -3868,10 +3782,6 @@ }, /turf/open/floor/iron/white/smooth_edge, /area/mine/cafeteria) -"uw" = ( -/obj/effect/spawner/random/lavaland_mob/raptor, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "ux" = ( /obj/machinery/door/airlock{ id_tag = "miningdorm1"; @@ -3882,6 +3792,14 @@ /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron, /area/mine/living_quarters) +"uy" = ( +/obj/effect/turf_decal/sand/plating/volcanic, +/obj/structure/railing/corner/end{ + dir = 8 + }, +/obj/structure/marker_beacon/purple, +/turf/open/floor/plating/lavaland_atmos, +/area/lavaland/surface/outdoors) "uC" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/siding/wideplating_new{ @@ -4034,12 +3952,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/mine/hydroponics) -"vr" = ( -/obj/structure/railing{ - dir = 1 - }, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "vu" = ( /obj/structure/bed/medical/emergency, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -4071,6 +3983,21 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/mine/laborcamp/production) +"vC" = ( +/obj/effect/turf_decal/trimline/yellow/filled/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/red/filled/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/filled/mid_joiner{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/red/filled/mid_joiner{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_corner, +/area/mine/production) "vD" = ( /turf/closed/wall, /area/mine/laborcamp/security/maintenance) @@ -4108,14 +4035,6 @@ /obj/item/cigbutt, /turf/open/floor/iron/smooth, /area/mine/laborcamp) -"vM" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/obj/effect/turf_decal/siding/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) "vN" = ( /obj/machinery/computer/records/security, /obj/structure/cable, @@ -4167,12 +4086,6 @@ /obj/effect/turf_decal/siding/wideplating_new, /turf/open/floor/iron/checker, /area/mine/laborcamp) -"wa" = ( -/obj/machinery/camera/autoname/directional/north{ - network = list("mine") - }, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "wb" = ( /obj/structure/chair{ dir = 8 @@ -4304,6 +4217,14 @@ /obj/item/seeds/banana, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"wR" = ( +/obj/effect/turf_decal/sand/plating/volcanic, +/obj/structure/marker_beacon/purple, +/obj/structure/railing/corner/end/flip{ + dir = 8 + }, +/turf/open/floor/plating/lavaland_atmos, +/area/lavaland/surface/outdoors) "wT" = ( /obj/structure/cable, /obj/effect/turf_decal/loading_area{ @@ -4655,7 +4576,7 @@ /turf/open/floor/plating, /area/mine/maintenance/service) "ze" = ( -/turf/open/misc/ashplanet/rocky, +/turf/closed/mineral/random/high_chance, /area/lavaland/surface/outdoors) "zf" = ( /obj/machinery/door/airlock{ @@ -4810,13 +4731,6 @@ /obj/structure/cable, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"zX" = ( -/obj/structure/chair/wood{ - dir = 1 - }, -/obj/machinery/light/directional/south, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "Ae" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -4832,13 +4746,6 @@ }, /turf/open/floor/plating, /area/mine/laborcamp/production) -"Ah" = ( -/obj/machinery/microwave{ - pixel_y = 6 - }, -/obj/structure/table/wood, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "Ai" = ( /obj/structure/stone_tile/cracked{ dir = 1 @@ -4875,10 +4782,10 @@ /turf/open/floor/iron/dark/textured_large, /area/mine/production) "Av" = ( -/obj/structure/railing{ - dir = 9 +/obj/structure/railing/corner{ + dir = 8 }, -/turf/open/misc/asteroid/basalt/lava_land_surface, +/turf/open/misc/hay/lavaland, /area/lavaland/surface/outdoors) "Ax" = ( /obj/item/pickaxe, @@ -4902,13 +4809,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/mine/laborcamp) -"AF" = ( -/obj/structure/lattice/catwalk/mining, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors) "AI" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -4955,6 +4855,13 @@ "AX" = ( /turf/open/floor/plating, /area/mine/laborcamp/security/maintenance) +"AY" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/effect/spawner/random/lavaland_mob/raptor/baby, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "Bb" = ( /obj/machinery/camera/autoname/directional/east{ network = list("mine") @@ -5086,31 +4993,6 @@ }, /turf/open/floor/iron/checker, /area/mine/cafeteria) -"Cn" = ( -/obj/structure/table/wood, -/obj/item/plate{ - pixel_x = 6; - pixel_y = 7 - }, -/obj/item/plate{ - pixel_x = -6; - pixel_y = -6 - }, -/obj/item/reagent_containers/cup/glass/mug/tea{ - pixel_x = 8; - pixel_y = -3 - }, -/obj/effect/turf_decal/siding/wood/end{ - dir = 8 - }, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) -"Cv" = ( -/obj/effect/turf_decal/sand/plating/volcanic, -/obj/structure/marker_beacon/purple, -/obj/effect/turf_decal/sand/plating/volcanic, -/turf/open/floor/plating/lavaland_atmos, -/area/lavaland/surface/outdoors) "Cz" = ( /obj/machinery/door/airlock/medical/glass{ name = "Infirmary" @@ -5176,8 +5058,21 @@ }, /area/mine/living_quarters) "CM" = ( -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/iron/dark/textured_large, +/obj/effect/turf_decal/trimline/yellow/filled/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/red/filled/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/filled/mid_joiner{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/red/filled/mid_joiner{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_corner{ + dir = 4 + }, /area/mine/production) "CO" = ( /turf/open/floor/iron/textured_large, @@ -5209,9 +5104,6 @@ /obj/structure/curtain, /turf/open/floor/iron/freezer, /area/mine/living_quarters) -"CV" = ( -/turf/closed/wall/mineral/iron, -/area/mine/lobby/raptor) "CX" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -5225,6 +5117,19 @@ /obj/structure/lattice/catwalk/mining, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) +"Db" = ( +/obj/machinery/door/airlock/external/glass{ + name = "Mining Shuttle Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/any/supply/mining, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/lavaland/surface/outdoors) "Dd" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -5317,6 +5222,12 @@ /obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, /turf/open/floor/plating, /area/mine/maintenance/public/north) +"DT" = ( +/obj/structure/railing{ + dir = 5 + }, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "DV" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -5476,12 +5387,6 @@ dir = 1 }, /area/mine/production) -"EP" = ( -/obj/structure/railing{ - dir = 4 - }, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "EQ" = ( /turf/open/floor/iron/smooth_edge{ dir = 8 @@ -5536,12 +5441,6 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"Fo" = ( -/obj/effect/turf_decal/siding/wood/end{ - dir = 4 - }, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) "Fp" = ( /obj/structure/table, /obj/machinery/recharger, @@ -5551,11 +5450,17 @@ /turf/open/floor/iron/dark, /area/mine/laborcamp/security) "Fr" = ( -/obj/machinery/door/airlock/external/glass{ - name = "Mining Shuttle Airlock" +/obj/effect/turf_decal/trimline/yellow/filled/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/filled/corner, +/obj/effect/turf_decal/trimline/red/filled/corner, +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_edge{ + dir = 4 }, -/obj/effect/mapping_helpers/airlock/access/any/supply/mining, -/turf/open/floor/iron/dark/textured_large, /area/mine/production) "Fs" = ( /obj/effect/turf_decal/sand/plating/volcanic, @@ -5600,10 +5505,6 @@ "FH" = ( /turf/closed/wall, /area/lavaland/surface/outdoors) -"FI" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "FL" = ( /obj/structure/disposalpipe/segment, /obj/machinery/light/small/directional/west, @@ -5616,6 +5517,13 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"FP" = ( +/obj/effect/turf_decal/sand/plating/volcanic, +/obj/structure/railing{ + dir = 1 + }, +/turf/open/floor/plating/lavaland_atmos, +/area/lavaland/surface/outdoors) "FT" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -5731,9 +5639,6 @@ dir = 8 }, /area/mine/production) -"GG" = ( -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "GH" = ( /obj/machinery/door/airlock/glass{ name = "Arrival Lounge" @@ -5743,12 +5648,6 @@ /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron, /area/mine/lounge) -"GI" = ( -/obj/structure/rack, -/obj/item/stack/sheet/mineral/wood/fifty, -/obj/item/lighter, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "GL" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -5759,6 +5658,20 @@ dir = 4 }, /area/mine/production) +"GO" = ( +/obj/structure/railing{ + dir = 6 + }, +/obj/structure/table/wood, +/obj/item/raptor_dex, +/obj/item/raptor_dex{ + pixel_y = 7 + }, +/obj/item/raptor_dex{ + pixel_y = 13 + }, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "GR" = ( /obj/structure/stone_tile/block/cracked{ dir = 4 @@ -6144,9 +6057,10 @@ /area/mine/laborcamp) "Jg" = ( /obj/effect/turf_decal/sand/plating/volcanic, -/obj/structure/railing{ - dir = 10 +/obj/structure/railing/corner/end{ + dir = 4 }, +/obj/structure/marker_beacon/purple, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) "Jh" = ( @@ -6406,41 +6320,6 @@ /obj/structure/girder, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"Km" = ( -/obj/structure/rack, -/obj/item/food/grown/grass/fairy{ - name = "weird hay"; - desc = "Somehow, somewhere, this tells you it should increase your friendship level with your animals. Too bad that doesn't work, right?" - }, -/obj/item/food/grown/grass/fairy{ - name = "weird hay"; - desc = "Somehow, somewhere, this tells you it should increase your friendship level with your animals. Too bad that doesn't work, right?"; - pixel_y = 9 - }, -/obj/item/food/grown/grass/fairy{ - name = "weird hay"; - desc = "Somehow, somewhere, this tells you it should increase your friendship level with your animals. Too bad that doesn't work, right?"; - pixel_y = 9; - pixel_x = 2 - }, -/obj/item/food/grown/grass/fairy{ - name = "weird hay"; - desc = "Somehow, somewhere, this tells you it should increase your friendship level with your animals. Too bad that doesn't work, right?"; - pixel_y = 6 - }, -/obj/item/food/grown/grass/fairy{ - name = "weird hay"; - desc = "Somehow, somewhere, this tells you it should increase your friendship level with your animals. Too bad that doesn't work, right?"; - pixel_y = 6; - pixel_x = 9 - }, -/obj/item/crowbar/large, -/obj/effect/turf_decal/siding/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) "Kn" = ( /obj/machinery/telecomms/relay/preset/mining, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -6534,12 +6413,6 @@ }, /turf/open/floor/iron/checker, /area/mine/cafeteria) -"KO" = ( -/obj/structure/railing{ - dir = 8 - }, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "KV" = ( /obj/structure/table, /obj/machinery/light/directional/east, @@ -6560,6 +6433,12 @@ }, /turf/open/floor/iron, /area/mine/living_quarters) +"KY" = ( +/obj/structure/railing/corner/end/flip{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "KZ" = ( /obj/structure/stone_tile/slab/cracked{ dir = 4 @@ -6661,15 +6540,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/mine/storage) -"Lv" = ( -/obj/machinery/power/apc/auto_name/directional/south, -/obj/structure/cable, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/effect/turf_decal/siding/wood, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) "Lw" = ( /obj/effect/turf_decal/sand/plating/volcanic, /obj/effect/turf_decal/stripes/line{ @@ -6800,6 +6670,23 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"Mb" = ( +/obj/effect/turf_decal/trimline/yellow/filled/arrow_cw{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/red/filled/arrow_cw{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/filled/mid_joiner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/red/filled/mid_joiner{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_corner{ + dir = 1 + }, +/area/mine/production) "Mc" = ( /obj/structure/chair/wood/wings, /obj/machinery/light/small/directional/east, @@ -6827,10 +6714,6 @@ dir = 8 }, /area/mine/lounge) -"Mf" = ( -/obj/item/kirbyplants/random, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "Mr" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -7050,6 +6933,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth_large, /area/mine/laborcamp/production) +"NA" = ( +/obj/structure/railing, +/obj/structure/table/wood, +/obj/item/flashlight/lantern/on, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "NC" = ( /obj/structure/gulag_vent, /turf/open/misc/asteroid/basalt/lava_land_surface, @@ -7074,7 +6963,11 @@ /turf/open/floor/iron/dark, /area/mine/production) "NK" = ( -/turf/open/misc/ashplanet/ash, +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/railing/corner, +/turf/open/misc/hay/lavaland, /area/lavaland/surface/outdoors) "NL" = ( /obj/structure/railing, @@ -7085,13 +6978,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/mine/laborcamp/security/maintenance) -"NP" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable, -/turf/open/floor/plating/lavaland_atmos, -/area/mine/lobby/raptor) "NR" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -7101,9 +6987,6 @@ dir = 1 }, /area/mine/laborcamp/production) -"NS" = ( -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "NT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -7198,13 +7081,6 @@ }, /turf/open/floor/iron, /area/mine/lounge) -"Oo" = ( -/obj/structure/railing{ - dir = 5 - }, -/obj/item/reagent_containers/cup/bucket/wooden, -/turf/open/misc/hay/lavaland, -/area/lavaland/surface/outdoors) "Op" = ( /obj/structure/stone_tile/slab, /turf/open/misc/asteroid/basalt/lava_land_surface, @@ -7226,16 +7102,6 @@ dir = 4 }, /area/mine/laborcamp/security) -"OE" = ( -/obj/effect/turf_decal/siding/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/chair/wood{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) "OH" = ( /obj/item/storage/fancy/cigarettes/cigpack_robust{ pixel_x = -8; @@ -7251,6 +7117,10 @@ }, /turf/open/floor/iron/smooth, /area/mine/laborcamp) +"OL" = ( +/obj/structure/railing, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "OM" = ( /obj/structure/table, /obj/machinery/power/apc/auto_name/directional/east, @@ -7282,17 +7152,6 @@ /obj/structure/cable, /turf/open/floor/iron/white/textured_large, /area/mine/cafeteria) -"OW" = ( -/obj/structure/table/wood, -/obj/item/soap/deluxe{ - pixel_y = 11 - }, -/obj/item/soap/deluxe{ - pixel_y = 6 - }, -/obj/item/soap/deluxe, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "OZ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -7316,13 +7175,6 @@ /obj/effect/turf_decal/stripes/corner, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) -"Pe" = ( -/obj/structure/lattice/catwalk/mining, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/plating/lavaland_atmos, -/area/lavaland/surface/outdoors) "Pi" = ( /obj/machinery/light/small/directional/south, /obj/effect/turf_decal/trimline/red/filled/line, @@ -7361,12 +7213,6 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/mine/cafeteria) -"Pn" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/plating/lavaland_atmos, -/area/lavaland/surface/outdoors) "Po" = ( /obj/structure/table, /obj/item/paper/guides/jobs/security/labor_camp, @@ -7673,23 +7519,6 @@ /obj/structure/easel, /turf/open/misc/hay/lavaland, /area/lavaland/surface/outdoors) -"Rj" = ( -/obj/machinery/suit_storage_unit/mining, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/iron/dark/smooth_edge{ - dir = 8 - }, -/area/mine/eva) -"Rm" = ( -/obj/structure/bed, -/obj/effect/spawner/random/bedsheet, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "Ro" = ( /obj/effect/turf_decal/loading_area, /obj/effect/turf_decal/trimline/brown/filled/line{ @@ -7774,13 +7603,6 @@ /obj/structure/lattice/catwalk, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"RO" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/plating, -/area/mine/eva) "RV" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 @@ -7842,11 +7664,6 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"Sj" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "Sm" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/turf_decal/siding/yellow, @@ -7860,14 +7677,6 @@ }, /turf/open/floor/iron/dark, /area/mine/hydroponics) -"Sp" = ( -/obj/structure/easel, -/obj/item/canvas/fortyfive_twentyseven, -/obj/item/canvas/thirtysix_twentyfour, -/obj/item/canvas/twentythree_nineteen, -/obj/item/paint_palette, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "Sq" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/structure/cable, @@ -8013,6 +7822,12 @@ dir = 1 }, /area/mine/production) +"Tk" = ( +/obj/structure/railing{ + dir = 6 + }, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "To" = ( /obj/structure/table, /obj/machinery/reagentgrinder, @@ -8049,23 +7864,12 @@ dir = 4 }, /area/mine/production) -"Tt" = ( -/obj/item/kirbyplants/random, -/obj/effect/turf_decal/siding/wood/end{ - dir = 4 - }, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) "Tu" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/mine/laborcamp) -"Tw" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "Tx" = ( /obj/machinery/light/small/directional/north, /obj/effect/decal/cleanable/dirt, @@ -8203,6 +8007,10 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/mine/laborcamp/quarters) +"Um" = ( +/obj/structure/flora/ash/tall_shroom, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "Un" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -8245,10 +8053,6 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"Uz" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "UD" = ( /obj/structure/toilet{ dir = 8 @@ -8336,10 +8140,6 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"Vd" = ( -/obj/structure/railing, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "Ve" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark/textured_large, @@ -8351,6 +8151,10 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark/textured_large, /area/mine/laborcamp) +"Vg" = ( +/obj/structure/railing, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "Vh" = ( /obj/machinery/door/airlock/external/glass{ name = "Mining External Airlock" @@ -8461,15 +8265,6 @@ }, /turf/open/floor/iron/checker, /area/mine/laborcamp) -"VI" = ( -/obj/effect/spawner/random/food_or_drink/donkpockets, -/obj/effect/spawner/random/food_or_drink/donkpockets{ - pixel_x = 6; - pixel_y = 5 - }, -/obj/structure/table/wood, -/turf/open/floor/carpet/red, -/area/mine/lobby/raptor) "VJ" = ( /obj/structure/closet/crate, /obj/item/food/mint, @@ -8492,12 +8287,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/mine/maintenance/labor) -"VP" = ( -/obj/effect/turf_decal/siding/wood/end{ - dir = 8 - }, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) "VS" = ( /obj/machinery/hydroponics/constructable, /obj/effect/decal/cleanable/dirt, @@ -8507,12 +8296,6 @@ /obj/item/seeds/potato, /turf/open/floor/iron/dark, /area/mine/laborcamp) -"VU" = ( -/obj/structure/railing/corner/end{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "VX" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ @@ -8539,6 +8322,15 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/mine/storage) +"Wf" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/structure/railing/corner{ + dir = 8 + }, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "Wg" = ( /obj/structure/girder, /obj/effect/turf_decal/sand/plating/volcanic, @@ -8546,15 +8338,22 @@ /area/mine/lounge) "Wh" = ( /obj/structure/railing{ - dir = 8 + dir = 10 }, -/turf/open/misc/asteroid/basalt/lava_land_surface, +/obj/structure/table/wood, +/obj/item/soap/deluxe, +/obj/item/soap/deluxe{ + pixel_y = 6 + }, +/obj/item/soap/deluxe{ + pixel_y = 11 + }, +/turf/open/misc/hay/lavaland, /area/lavaland/surface/outdoors) "Wk" = ( -/obj/structure/railing{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, +/obj/structure/railing, +/obj/effect/spawner/random/lavaland_mob/raptor/young, +/turf/open/misc/hay/lavaland, /area/lavaland/surface/outdoors) "Wl" = ( /obj/machinery/door/airlock/external/glass{ @@ -8575,12 +8374,6 @@ dir = 1 }, /area/mine/laborcamp/security) -"Wq" = ( -/obj/structure/railing{ - dir = 5 - }, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) "Wt" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/structure/disposalpipe/segment, @@ -8746,9 +8539,12 @@ dir = 4 }, /area/mine/production) -"Xk" = ( -/obj/effect/spawner/random/lavaland_mob/raptor, -/turf/open/misc/hay/lavaland, +"Xl" = ( +/obj/structure/railing{ + dir = 9 + }, +/obj/effect/turf_decal/sand/plating/volcanic, +/turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) "Xp" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -8822,6 +8618,12 @@ dir = 1 }, /area/mine/lounge) +"XG" = ( +/obj/structure/railing{ + dir = 10 + }, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "XH" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -8844,7 +8646,21 @@ pixel_x = -32; pixel_y = 0 }, -/turf/open/floor/iron/dark/textured_large, +/obj/effect/turf_decal/trimline/yellow/filled/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/red/filled/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/filled/mid_joiner{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/red/filled/mid_joiner{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_edge{ + dir = 8 + }, /area/mine/production) "XP" = ( /obj/structure/stone_tile/cracked, @@ -8936,8 +8752,6 @@ /area/mine/lounge) "Yg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, /turf/open/floor/iron/dark/textured_large, /area/mine/eva) "Yk" = ( @@ -9023,14 +8837,6 @@ /obj/structure/barricade/wooden, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"YP" = ( -/obj/structure/bookcase/random/reference, -/obj/effect/turf_decal/siding/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) "YR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -9114,10 +8920,6 @@ }, /turf/open/floor/iron/smooth, /area/mine/laborcamp/production) -"Zs" = ( -/obj/structure/closet/secure_closet/personal/cabinet, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "Zt" = ( /turf/closed/wall, /area/mine/laborcamp) @@ -9143,6 +8945,12 @@ /obj/effect/turf_decal/sand/plating/volcanic, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) +"Zy" = ( +/obj/structure/railing/corner/end/flip{ + dir = 4 + }, +/turf/open/misc/hay/lavaland, +/area/lavaland/surface/outdoors) "Zz" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -9157,18 +8965,6 @@ dir = 8 }, /area/mine/lounge) -"ZB" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/effect/turf_decal/siding/wood, -/turf/open/floor/wood/large, -/area/mine/lobby/raptor) -"ZF" = ( -/obj/effect/turf_decal/sand/plating/volcanic, -/obj/effect/turf_decal/sand/plating/volcanic, -/turf/open/floor/plating/lavaland_atmos, -/area/lavaland/surface/outdoors) "ZH" = ( /obj/structure/closet/secure_closet/labor_camp_security, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -9177,13 +8973,6 @@ /obj/structure/extinguisher_cabinet/directional/west, /turf/open/floor/iron/dark, /area/mine/laborcamp/security) -"ZL" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/chair/wood, -/obj/structure/cable, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "ZM" = ( /obj/structure/railing{ dir = 8 @@ -9215,17 +9004,6 @@ /obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, /turf/open/floor/plating, /area/mine/maintenance/public/north) -"ZU" = ( -/obj/structure/railing{ - dir = 6 - }, -/turf/open/misc/hay/lavaland, -/area/mine/lobby/raptor) -"ZX" = ( -/obj/structure/table/wood, -/obj/item/knife, -/turf/open/floor/wood/parquet, -/area/mine/lobby/raptor) "ZY" = ( /turf/closed/mineral/random/volcanic, /area/lavaland/surface/outdoors/unexplored) @@ -42633,8 +42411,8 @@ Hj pU BP pU -NK -ze +ai +ai pU pU aj @@ -42889,9 +42667,9 @@ EL EL pU pU -ze +ai BP -ze +ai pU pU aj @@ -43146,8 +42924,8 @@ pU pU pU pU -ze -ze +ai +ai pU pU aj @@ -44946,8 +44724,8 @@ aj aj aj aj -NK -NK +ze +ze pU aj aj @@ -45461,7 +45239,7 @@ aj aj pU BP -ze +ai pU pU aj @@ -45717,7 +45495,7 @@ aj aj aj pU -NK +ai pU pU pU @@ -47494,11 +47272,11 @@ WB wt jw fA -Le +NU Le NU Le -Le +NU BP BP BP @@ -47516,7 +47294,7 @@ aj aj pU pU -NK +ai BP ze pU @@ -47752,7 +47530,7 @@ Jl rv TJ RW -cc +vC XM CM lM @@ -47772,10 +47550,10 @@ aj aj aj pU +ai ze ze -ze -ze +ai aj aj aj @@ -48009,9 +47787,9 @@ GF lb Yl Le -Le +fw Fr -Le +Mb Le BP BP @@ -48031,7 +47809,7 @@ aj pU BP ze -NK +ze pU aj aj @@ -48266,10 +48044,10 @@ Ra oh pK NU -BP -BP -BP -JD +eb +Db +eb +FH BP BP BP @@ -48286,8 +48064,8 @@ pU aj aj pU -NK -NK +ai +ai pU pU aj @@ -48524,7 +48302,7 @@ mT pK pU BP -ZF +BP BP JD BP @@ -48780,9 +48558,9 @@ Yg li dK pU -Cv BP -Cv +aI +BP zk mc mc @@ -49037,8 +48815,8 @@ Yg TQ dK pU -aX -BP +pU +FP Jg pU pU @@ -49290,14 +49068,14 @@ YD pK Ob IL -Rj +IL KV pK aj +aj yV -BP fK -pU +aj pU pU pU @@ -49547,12 +49325,12 @@ NU pK pK dK -RO +dK pK pK aj +aj yV -tF NL aj aj @@ -49804,12 +49582,12 @@ NU ai pU pU -Pn +pU pU aj aj +aj yV -tF NL aj aj @@ -50061,12 +49839,12 @@ pU pU pU pU -AF +aj aj aj pU +aj yV -tF NL aj aj @@ -50318,12 +50096,12 @@ pU aj aj aj -AF +aj aj pU aj +aj yV -tF NL aj pU @@ -50340,7 +50118,7 @@ pU pU pU pU -ze +ai ze ze pU @@ -50575,13 +50353,13 @@ aj aj aj aj -AF aj aj aj -zs -tF -de +aj +aj +fB +kz aj aj aj @@ -50596,8 +50374,8 @@ aj pU pU pU +ai ze -NK ze BP pU @@ -50832,30 +50610,30 @@ aj aj aj aj -AF aj aj aj -ct +aj +aj +FP +wR +pU +aj +aj +aj +aj +aj +aj +aj +aj +aj +pU +pU +pU +ai BP -ct -pU -aj -aj -aj -aj -aj -aj -aj -aj -aj -pU -pU -pU -ze -BP -NK -ze +ai +ai pU pU pU @@ -51089,12 +50867,12 @@ ai ai pU pU -AF +pU +pU aj aj -aj -BP -BP +pU +uy BP pU pU @@ -51108,10 +50886,10 @@ aj pU pU pU +ai ze -ze -NK -ze +ai +ai lP pU pU @@ -51346,11 +51124,11 @@ ai ai ai ai -Pn -AF -AF -AF -Pe +pU +pU +pU +pU +pU BP BP BP @@ -51366,10 +51144,10 @@ lt Ri eN pU -ze -ze -ze -ze +ai +ai +ai +ai pU pU aj @@ -51607,10 +51385,8 @@ ai pU pU pU -AF -BP -BP -BP +pU +pU BP ct pU @@ -51618,6 +51394,8 @@ pU pU pU pU +pU +BP lt Ns lt @@ -51625,7 +51403,7 @@ pU pU pU pU -ze +ai pU pU aj @@ -51861,21 +51639,21 @@ aj aj ai ai -CV -CV -ki -NP -ki -CV -CV -CV -lt pU pU pU pU pU pU +pU +pU +pU +pU +pU +pU +pU +BP +BP lt pU lP @@ -52117,19 +51895,11 @@ aj aj aj aj -CV -CV -Km -qB -eL -Ah -VI -ZX -ki -Ns +aj +pU +pU lt pU -BP pU pU pU @@ -52138,6 +51908,14 @@ pU pU pU pU +rt +pU +pU +pU +pU +pU +pU +pU pU pU aj @@ -52374,25 +52152,25 @@ aj aj aj aj -CV -GG -jX -Tw -eL -aF -pF -dF -ki -lt -lt +aj +aj +pU +Ns lt pU +BP +pU +pU pU pU BP -NK -NK -ze +pU +lt +Ns +lt +UI +pU +pU pU pU pU @@ -52628,28 +52406,28 @@ pU ai ai ai -pU +ai +aj +aj aj aj -CV -Sp -OE -as -ZL -Cn -zX -CV -CV pU +pU +lt lt pU pU pU pU -ze -NK -ze BP +Xl +lf +XG +hA +lf +NK +FH +pU pU pU pU @@ -52887,27 +52665,24 @@ ai ai ai ai +ai +aj +aj pU -CV -GG -Tt -fa -eL -ZB -GG -CV +pU +lt pU pU pU +pU +pU +BP +AY +pU +OL lP -pU -BP -pU -ze -NK -pU -UI -pU +lt +Vg pU pU pU @@ -52919,6 +52694,9 @@ aj aj aj aj +aj +aj +aj "} (171,1,1) = {" aa @@ -53145,34 +52923,34 @@ aj ai ai ai -CV -wa -rB -fa -eL -Lv -CV -CV -CV -ct +ai pU pU pU pU +lP pU -ze +BP pU -pU -lt -lt -lt UI +ct +ow +Az +OL pU -aj +pU +Vg pU pU aj +aj +aj +aj +aj +aj +aj pU +aj pU aj aj @@ -53400,29 +53178,25 @@ aj aj aj aj -pU ai -CV -jt -ba -fa -jJ -ZB -be -dI -oO -BP -pU -BP -pU -pU +ai +ai pU +UI ct -BP +pU +pU +pU +pU +pU lt lt -Ns +up +UI +OL +bY lt +Vg lt pU pU @@ -53430,7 +53204,11 @@ pU pU pU pU -pU +aj +aj +aj +aj +aj aj aj "} @@ -53659,36 +53437,36 @@ aj aj aj aj -CV -GG -tf -fa -Sj -ZB -CV -CV -CV -ct -pU -pU pU pU pU BP +pU +pU +pU +pU +lt +lt +lt +td +pU +KY +lt +lt Av Wh -Wh -CV -ki -ki -CV -CV -ki -ki -CV -CV +lt pU pU +pU +pU +pU +aj +aj +pU +pU +aj +aj aj "} (174,1,1) = {" @@ -53916,37 +53694,37 @@ aj aj aj aj -CV -rf -VP -fa -Sj -ZB -Mf -CV -hl +aj +aj pU +pU +pU +BP +pU +pU +lt +Ns lt lt pU pU lt lt -up +lt +NA lt pU -vr -sQ -NS -Vd -NS -NS -sQ -NS -CV +pU +aj +aj pU pU aj +aj +aj +aj +aj +aj "} (175,1,1) = {" aa @@ -54173,37 +53951,37 @@ aj aj aj aj -CV -GI -vM -FI -jJ -Fo -hM -CV -CV -Ns -lt +aj +aj +pU +pU +pU +pU +pU +pU pU pU lt +Zy lt +xW +pU lt -up +bD +GO pU pU -vr -il -NS -Vd -NS -NS -il -NS -ki pU aj aj +aj +aj +aj +aj +aj +aj +aj +aj "} (176,1,1) = {" aa @@ -54430,36 +54208,36 @@ aj aj aj aj -CV -pM -YP -GG -Uz -Uz -Uz -Zs -ki -lt -lt +aj +pU +pU +pU +pU +pU +pU pU pU pU lt -pU +bx +lt +Vg +lt +lt Wk -UI -ct -vr -NS -NS -Vd -NS -NS -NS -NS -ki +lt pU pU +pU +pU +aj +aj +aj +aj +aj +aj +aj +aj aj "} (177,1,1) = {" @@ -54685,38 +54463,38 @@ pU pU pU pU -aj -aj -CV -CV -YP -GG -fa -fa -Rm -bE -ki +pU +pU +pU +pU +pU +pU +pU +pU +pU +pU +ct +lt +iL +up +cO +Vg +lt +lt +Vg lt pU pU pU pU +aj +aj +aj +aj +aj pU -pU -Wk -pU -lt -Wq -EP -NS -ZU -NS -NS -EP -EP -CV -CV -pU +aj +aj aj "} (178,1,1) = {" @@ -54943,36 +54721,36 @@ pU pU pU pU +pU +pU +pU +pU +pU +pU +pU +pU +pU +pU +lt +Pb +up +lt +Vg +Ns +Az +Vg +pU +pU +pU +pU +pU +aj +aj +aj +aj +aj aj aj -CV -CV -ki -ki -ki -CV -CV -CV -lt -pU -pU -lt -pU -pU -pU -VU -Xk -lt -NS -NS -NS -NS -NS -uw -NS -NS -NS -ki pU aj "} @@ -55201,9 +54979,6 @@ pU pU pU pU -aj -aj -aj pU pU pU @@ -55214,24 +54989,27 @@ pU pU pU Ns -Az +lt +DT +ev +Tk +ej +ev +Wf +FH +pU +pU pU pU -lt -lt -lt -NS -mk -sa -NS -NS -NS -OW -sa -NS -ki aj aj +pU +pU +pU +aj +aj +pU +aj "} (180,1,1) = {" aa @@ -55468,26 +55246,26 @@ pU pU pU pU -pU -pU -lt lt pU -xW lt lt lt -NS -NS -uw -NS -NS -NS -NS -NS -NS -ki +Um pU +pU +pU +pU +pU +aj +aj +pU +pU +pU +pU +pU +aj +aj aj "} (181,1,1) = {" @@ -55728,22 +55506,22 @@ pU pU pU pU -lt pU pU -Wk -lt -lt -kf -KO -NS -aH -NS -NS -KO -KO -CV -CV +pU +pU +pU +pU +pU +pU +aj +aj +aj +pU +pU +pU +aj +aj pU aj "} @@ -55980,6 +55758,7 @@ pU pU pU pU +UI pU pU pU @@ -55988,19 +55767,18 @@ pU pU pU pU -Wk pU -ct -vr -NS -rj -Vd -NS -NS -NS -NS -ki pU +pU +pU +aj +aj +pU +pU +pU +pU +pU +aj aj aj "} @@ -56243,23 +56021,23 @@ pU pU pU pU -lt -lt -Wk pU pU -vr -il -NS -Vd -NS -NS -il -NS -ki pU pU pU +pU +pU +pU +pU +pU +pU +aj +aj +aj +aj +aj +pU "} (184,1,1) = {" aa @@ -56499,23 +56277,23 @@ pU pU pU pU -lt -Ns -lt -up -Pb -pU -vr -sQ -NS -Vd -NS -NS -sQ -NS -CV pU pU +pU +pU +pU +pU +pU +pU +pU +pU +pU +pU +aj +aj +pU +pU +aj aj "} (185,1,1) = {" @@ -56756,22 +56534,22 @@ pU pU pU pU -lt -lt -BP -Oo -ej -nO -CV -ki -ki -CV -CV -ki -ki -CV -CV pU +pU +pU +pU +pU +pU +pU +pU +pU +pU +pU +pU +aj +pU +aj +aj aj aj "} @@ -57015,12 +56793,6 @@ pU pU pU pU -ct -BP -pU -pU -pU -lt pU pU pU @@ -57031,6 +56803,12 @@ pU pU pU aj +aj +aj +aj +aj +aj +aj "} (187,1,1) = {" aa @@ -57273,19 +57051,19 @@ pU pU pU pU -lt -pU -pU -lt -Ns -lt -lt pU pU pU pU pU pU +pU +pU +aj +aj +aj +aj +aj aj aj "} @@ -57529,17 +57307,17 @@ pU pU pU pU -lt -lt -lt -pU -lt -lt -lt -lt -lt pU pU +pU +pU +pU +pU +pU +pU +pU +aj +aj aj aj aj @@ -57787,15 +57565,15 @@ pU pU pU pU -Ns pU pU -UI -lt -lt -Ns -lt pU +pU +pU +pU +pU +pU +aj aj aj aj @@ -58049,8 +57827,8 @@ pU pU pU pU -lt -lt +pU +pU pU aj aj diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index ebcd71345ee..f8392dfc171 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -81,6 +81,7 @@ #define BB_BASIC_MOB_CURRENT_TARGET "BB_basic_current_target" #define BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION "BB_basic_current_target_hiding_location" #define BB_TARGETING_STRATEGY "targeting_strategy" +#define BB_HUNT_TARGETING_STRATEGY "hunt_targeting_strategy" ///some behaviors that check current_target also set this on deep crit mobs #define BB_BASIC_MOB_EXECUTION_TARGET "BB_basic_execution_target" ///Blackboard key for a whitelist typecache of "things we can target while trying to move" diff --git a/code/__DEFINES/basic_mobs.dm b/code/__DEFINES/basic_mobs.dm index a07997d40d2..5b1d0283c56 100644 --- a/code/__DEFINES/basic_mobs.dm +++ b/code/__DEFINES/basic_mobs.dm @@ -39,40 +39,83 @@ #define MOOK_ATTACK_ACTIVE 2 #define MOOK_ATTACK_STRIKE 3 -///keeps track of how many gutlunches are born +/// Keeps track of how many gutlunches are born GLOBAL_VAR_INIT(gutlunch_count, 0) -///Pet customization settings saved for every client +/// Pet customization settings saved for every client GLOBAL_LIST_EMPTY(customized_pets) -//raptor defines +// Raptor defines +/// Raptor chick, tiny and very frail +#define RAPTOR_BABY "baby" +/// Raptor youngling, cannot be ridden and has reduced stats, but can hunt by itself just fine +#define RAPTOR_YOUNG "young" +/// Fully grown adult raptor +#define RAPTOR_ADULT "adult" -#define RAPTOR_RED "Red" -#define RAPTOR_GREEN "Green" -#define RAPTOR_PURPLE "Purple" -#define RAPTOR_WHITE "White" -#define RAPTOR_YELLOW "Yellow" -#define RAPTOR_BLACK "Black" -#define RAPTOR_BLUE "Blue" +/// Innate raptor offsets +#define RAPTOR_INNATE_SOURCE "raptor_innate" +// Growth values +/// How much does meal complexity affect our growth? +#define RAPTOR_MEAL_COMPLEXITY_GROWTH_FACTOR 5 +/// Base value for raptor growth from meat +#define RAPTOR_GROWTH_BASE_MEAT 10 +/// Base value for raptor growth from ash flora +#define RAPTOR_GROWTH_BASE_PLANT 5 +/// How much growth progress raptors need to accumulate to fully grow into an adult +#define RAPTOR_GROWTH_REQUIRED 100 +/// Minimum random growth value a baby raptor can gain per second +#define RAPTOR_BABY_GROWTH_LOWER 0.5 +/// Maximum random growth value a baby raptor can gain per second +#define RAPTOR_BABY_GROWTH_UPPER 0.8 +/// How long it takes for a raptor egg to grow up, in seconds +#define RAPTOR_EGG_GROWTH_PROGRESS 100 +/// How much happiness percentage affects our growth speed +#define RAPTOR_GROWTH_HAPPINESS_MULTIPLIER 0.005 // Full happiness increases growth rate by 50% + +/// Damage boost per happiness percent +#define RAPTOR_HAPPINESS_DAMAGE_BOOST 0.05 + +// Raptor inheritance stats +/// Maximum amount of traits a raptor can inherit +#define RAPTOR_TRAIT_INHERIT_AMOUNT 2 +/// Minimum modifier to base attack values a raptor can get +#define RAPTOR_INHERIT_MIN_ATTACK -5 +/// Maximum modifier to base attack values a raptor can get #define RAPTOR_INHERIT_MAX_ATTACK 5 +/// Minimum modifier to the base health value a raptor can get +#define RAPTOR_INHERIT_MIN_HEALTH -30 +/// Maximum modifier to the base health value a raptor can get #define RAPTOR_INHERIT_MAX_HEALTH 30 +/// Minimum modifier to base speed values a raptor can get +#define RAPTOR_INHERIT_MIN_SPEED -0.66 +/// Maximum modifier to base speed values a raptor can get +#define RAPTOR_INHERIT_MAX_SPEED 0.66 +/// Minimum modifier a raptor can get to their modifiers, such as ability effect and growth speed +#define RAPTOR_INHERIT_MIN_MODIFIER -0.25 +/// Maximum modifier a raptor can get to their modifiers, such as ability effect and growth speed +#define RAPTOR_INHERIT_MAX_MODIFIER 0.25 +/// Genetic drift for raptors, aka min/max value from the cap that stats can receive when breeding +#define RAPTOR_GENETIC_DRIFT 0.2 -///this mob suffers depression +/// This mob suffers depression #define BB_BASIC_DEPRESSED "basic_depressed" -///this mob will care for its young +/// This mob will care for its young #define BB_RAPTOR_MOTHERLY "raptor_motherly" -///this mob will be playful around their owners +/// This mob will be playful around their owners #define BB_RAPTOR_PLAYFUL "raptor_playful" -///this mob will flee combat when it feels threatened +/// This mob will flee combat when it feels threatened #define BB_RAPTOR_COWARD "raptor_coward" -///our raptor baby target we will take care of +/// Our raptor baby target we will take care of #define BB_RAPTOR_BABY "raptor_baby" -///the raptor we will heal up +/// The raptor we will heal up #define BB_INJURED_RAPTOR "injured_raptor" -///the cooldown for next time we eat +/// The cooldown for next time we eat #define BB_RAPTOR_EAT_COOLDOWN "raptor_eat_cooldown" -///our trough target +/// Our trough target #define BB_RAPTOR_TROUGH_TARGET "raptor_trough_target" +/// HP level at which we'll flee from attackers +#define BB_RAPTOR_FLEE_THRESHOLD "raptor_flee_threshold" #define MAX_RAPTOR_POP 64 diff --git a/code/__DEFINES/dcs/signals/signals_food.dm b/code/__DEFINES/dcs/signals/signals_food.dm index 0041076802c..2122f57add8 100644 --- a/code/__DEFINES/dcs/signals/signals_food.dm +++ b/code/__DEFINES/dcs/signals/signals_food.dm @@ -74,6 +74,9 @@ ///Sent to the newly spawned object when it's baked in an oven. #define COMSIG_ITEM_BAKED_RESULT "item_baked_result" +/// From /datum/element/basic_eating/finish_eating() : (mob/living/eater, mob/living/feeder) +#define COMSIG_ITEM_EATEN_BY_BASIC_MOB "item_eaten_by_basic_mob" + ///Called on the result spawned during decomposition: (obj/decomposed) #define COMSIG_OBJ_DECOMPOSITION_RESULT "obj_decomposition_result" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_basic.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_basic.dm index 01df92ebcc2..83084005dd5 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_basic.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_basic.dm @@ -28,3 +28,8 @@ #define COMSIG_BASICMOB_MUTATED "basicmob_mutated" ///cancel further mutation modifications to the mob such as shiny mutation. #define MUTATED_NO_FURTHER_MUTATIONS (1 << 0) + +/// from /mob/living/basic/raptor/proc/change_growth_stage() : (new_stage, prev_stage) +#define COMSIG_RAPTOR_GROWTH_STAGE_CHANGE "raptor_growth_stage_change" + /// Cancel raptor growth + #define COMPONENT_CANCEL_RAPTOR_GROWTH (1<<0) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index 67d69dc5b05..fd57e4283da 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -182,3 +182,6 @@ //from base of [/obj/effect/particle_effect/fluid/smoke/proc/smoke_mob]: (seconds_per_tick) #define COMSIG_CARBON_EXPOSED_TO_SMOKE "carbon_exposed_to_smoke" + +/// From /mob/living/carbon/human/proc/update_mob_height() : (old_height) +#define COMSIG_HUMAN_HEIGHT_UPDATED "human_height_updated" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index e57699a34a9..40d0f1ae3bd 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -365,3 +365,6 @@ #define COMSIG_LIVING_DROP_LOOT "living_drop_loot" /// Prevent loot from being dropped #define COMPONENT_NO_LOOT_DROP (1<<0) + +/// From /mob/living/proc/mob_pickup() : (mob/living/user, obj/item/mob_holder/holder) +#define COMSIG_LIVING_SCOOPED_UP "living_scooped_up" diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 8c221d28d1d..1cceb5e624b 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -637,3 +637,9 @@ /// Sent from /obj/machinert/console/camera_advanced/attack_hand() : (mob/eye/camera/remote/new_camera) #define COMSIG_ADVANCED_CAMERA_EYE_CREATED "advanced_camera_eye_created" + +/// Sent from /obj/item/mob_holder/purple_raptor/proc/toggle_wings() : (mob/living/carbon/human/user) +#define COMSIG_RAPTOR_WINGS_OPENED "raptor_wings_opened" + +/// Sent from /obj/item/mob_holder/purple_raptor/proc/toggle_wings() : (mob/living/carbon/human/user) +#define COMSIG_RAPTOR_WINGS_CLOSED "raptor_wings_closed" diff --git a/code/__HELPERS/atoms.dm b/code/__HELPERS/atoms.dm index dfe731eddfe..bf304813b24 100644 --- a/code/__HELPERS/atoms.dm +++ b/code/__HELPERS/atoms.dm @@ -370,14 +370,14 @@ rough example of the "cone" made by the 3 dirs checked /// Returns an x and y value require to reverse the transformations made to center an oversized icon /atom/proc/get_oversized_icon_offsets() - if (pixel_x == 0 && pixel_y == 0) + if (!base_pixel_x && !base_pixel_y && !base_pixel_w && !base_pixel_z) return list("x" = 0, "y" = 0) var/list/icon_dimensions = get_icon_dimensions(icon) var/icon_width = icon_dimensions["width"] var/icon_height = icon_dimensions["height"] return list( - "x" = icon_width > ICON_SIZE_X && pixel_x != 0 ? (icon_width - ICON_SIZE_X) * 0.5 : 0, - "y" = icon_height > ICON_SIZE_Y && pixel_y != 0 ? (icon_height - ICON_SIZE_Y) * 0.5 : 0, + "x" = icon_width > ICON_SIZE_X && (base_pixel_x || base_pixel_w) ? (icon_width - ICON_SIZE_X) * 0.5 : 0, + "y" = icon_height > ICON_SIZE_Y && (base_pixel_y || base_pixel_z) ? (icon_height - ICON_SIZE_Y) * 0.5 : 0, ) /// Helper for easily adding blood from INSIDE a mob to an atom (NOT blood ON the mob) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index b1210932f47..a93f3d7402a 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -205,8 +205,10 @@ GLOBAL_LIST_INIT(skin_tone_names, list( * @param {icon} icon - The icon file of the cog. Default: 'icons/effects/progressbar.dmi' * * @param {iconstate} iconstate - The icon state of the cog. Default: "Cog" + * + * @param {mob} bar_override - Mob which should see the bar instead of the user */ -/proc/do_after(mob/user, delay, atom/target, timed_action_flags = NONE, progress = TRUE, datum/callback/extra_checks, interaction_key, max_interact_count = 1, hidden = FALSE, icon = 'icons/effects/progressbar.dmi', iconstate = "cog") +/proc/do_after(mob/user, delay, atom/target, timed_action_flags = NONE, progress = TRUE, datum/callback/extra_checks, interaction_key, max_interact_count = 1, hidden = FALSE, icon = 'icons/effects/progressbar.dmi', iconstate = "cog", mob/bar_override = null) if(!user) return FALSE if(!isnum(delay)) @@ -240,11 +242,11 @@ GLOBAL_LIST_INIT(skin_tone_names, list( var/datum/cogbar/cog if(progress) - if(user.client) - progbar = new(user, delay, target || user) + if(user.client || bar_override?.client) + progbar = new(bar_override || user, delay, target || user) if(!hidden && delay >= 1 SECONDS) - cog = new(user, icon, iconstate) + cog = new(bar_override || user, icon, iconstate) SEND_SIGNAL(user, COMSIG_DO_AFTER_BEGAN) diff --git a/code/datums/ai/babies/babies_subtrees.dm b/code/datums/ai/babies/babies_subtrees.dm index 60ca7dc8193..7cadd1e8c55 100644 --- a/code/datums/ai/babies/babies_subtrees.dm +++ b/code/datums/ai/babies/babies_subtrees.dm @@ -3,10 +3,12 @@ */ /datum/ai_planning_subtree/make_babies operational_datums = list(/datum/component/breed) - ///chance to make babies + /// Chance to make babies var/chance = 5 - ///make babies behavior we will use + /// Make babies behavior we will use var/datum/ai_behavior/reproduce_behavior = /datum/ai_behavior/make_babies + /// Find partner behavior we will use + var/datum/ai_behavior/partner_behavior = /datum/ai_behavior/find_partner /datum/ai_planning_subtree/make_babies/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() @@ -25,4 +27,4 @@ return // Find target - controller.queue_behavior(/datum/ai_behavior/find_partner, BB_BABIES_TARGET, BB_BABIES_PARTNER_TYPES, BB_BABIES_CHILD_TYPES) + controller.queue_behavior(partner_behavior, BB_BABIES_TARGET, BB_BABIES_PARTNER_TYPES, BB_BABIES_CHILD_TYPES) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm index 07b4845f027..31735f99231 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/find_parent.dm @@ -4,21 +4,32 @@ /datum/ai_behavior/find_mom/perform(seconds_per_tick, datum/ai_controller/controller, mom_key, ignore_mom_key, found_mom) var/mob/living_pawn = controller.pawn - var/list/mom_types = controller.blackboard[mom_key] var/list/all_moms = list() + var/list/mom_types = controller.blackboard[mom_key] var/list/ignore_types = controller.blackboard[ignore_mom_key] if(!length(mom_types)) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED for(var/mob/mother in oview(look_range, living_pawn)) - if(!is_type_in_list(mother, mom_types)) - continue - if(is_type_in_list(mother, ignore_types)) //so the not permanent baby and the permanent baby subtype dont followed each other - continue - all_moms += mother + if (is_possible_mom(mother, mom_types, ignore_types)) + all_moms += mother if(length(all_moms)) controller.set_blackboard_key(found_mom, pick(all_moms)) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + +/datum/ai_behavior/find_mom/proc/is_possible_mom(mob/mother, list/mom_types, list/ignore_types) + if(!is_type_in_list(mother, mom_types)) + return FALSE + if(is_type_in_list(mother, ignore_types)) // so the not permanent baby and the permanent baby subtype dont followed each other + return FALSE + return TRUE + +/datum/ai_behavior/find_mom/raptor/is_possible_mom(mob/mother, list/mom_types, list/ignore_types) + . = ..() + if (!. || !istype(mother, /mob/living/basic/raptor)) + return FALSE + var/mob/living/basic/raptor/raptor = mother + return raptor.growth_stage == RAPTOR_ADULT diff --git a/code/datums/ai/basic_mobs/basic_subtrees/find_parent.dm b/code/datums/ai/basic_mobs/basic_subtrees/find_parent.dm index ef44df82f78..7b35053ff38 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/find_parent.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/find_parent.dm @@ -7,7 +7,7 @@ var/mob/baby = controller.pawn if(QDELETED(target)) - controller.queue_behavior(/datum/ai_behavior/find_mom, BB_FIND_MOM_TYPES, BB_IGNORE_MOM_TYPES, BB_FOUND_MOM) + find_mom(controller) return if(get_dist(target, baby) > minimum_distance) @@ -23,3 +23,9 @@ controller.queue_behavior(/datum/ai_behavior/perform_emote, "dances around their parent!") return SUBTREE_RETURN_FINISH_PLANNING + +/datum/ai_planning_subtree/look_for_adult/proc/find_mom(datum/ai_controller/controller) + controller.queue_behavior(/datum/ai_behavior/find_mom, BB_FIND_MOM_TYPES, BB_IGNORE_MOM_TYPES, BB_FOUND_MOM) + +/datum/ai_planning_subtree/look_for_adult/raptor/find_mom(datum/ai_controller/controller) + controller.queue_behavior(/datum/ai_behavior/find_mom/raptor, BB_FIND_MOM_TYPES, BB_FOUND_MOM) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm index f80ffcc155e..52524852961 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm @@ -1,10 +1,12 @@ /datum/ai_planning_subtree/simple_find_target /// Variable to store target in var/target_key = BB_BASIC_MOB_CURRENT_TARGET + /// Targeting strategy key to use + var/strategy_key = BB_TARGETING_STRATEGY /datum/ai_planning_subtree/simple_find_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - controller.queue_behavior(/datum/ai_behavior/find_potential_targets, target_key, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(/datum/ai_behavior/find_potential_targets, target_key, strategy_key, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) // Prevents finding a target if a human is nearby /datum/ai_planning_subtree/simple_find_target/not_while_observed @@ -21,4 +23,7 @@ /datum/ai_planning_subtree/simple_find_target/increased_range /datum/ai_planning_subtree/simple_find_target/increased_range/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - controller.queue_behavior(/datum/ai_behavior/find_potential_targets/bigger_range, target_key, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(/datum/ai_behavior/find_potential_targets/bigger_range, target_key, strategy_key, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + +/datum/ai_planning_subtree/simple_find_target/hunt + strategy_key = BB_HUNT_TARGETING_STRATEGY diff --git a/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm b/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm index 6848d5d323d..227b4f2fc28 100644 --- a/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm +++ b/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm @@ -154,3 +154,6 @@ if(!istype(target) || target.has_status_effect(/datum/status_effect/gutted)) return FALSE return ..() + +/datum/targeting_strategy/basic/exact_match + check_factions_exactly = TRUE diff --git a/code/datums/ai/basic_mobs/targeting_strategies/dont_target_friends.dm b/code/datums/ai/basic_mobs/targeting_strategies/dont_target_friends.dm index 41c01ca9158..268b4ca8842 100644 --- a/code/datums/ai/basic_mobs/targeting_strategies/dont_target_friends.dm +++ b/code/datums/ai/basic_mobs/targeting_strategies/dont_target_friends.dm @@ -16,7 +16,7 @@ if(!(target.resistance_flags & INDESTRUCTIBLE)) return TRUE - if(target in living_mob.ai_controller.blackboard[BB_FRIENDS_LIST]) + if(isliving(target) && (target in living_mob.ai_controller.blackboard[BB_FRIENDS_LIST])) return FALSE return ..() diff --git a/code/datums/ai/dog/dog_controller.dm b/code/datums/ai/dog/dog_controller.dm index 0aaaede44cb..cb17546bfbb 100644 --- a/code/datums/ai/dog/dog_controller.dm +++ b/code/datums/ai/dog/dog_controller.dm @@ -25,7 +25,7 @@ // With tongs in hand! BB_TARGET_HELD_ITEM = /obj/item/kitchen/tongs, BB_BABIES_PARTNER_TYPES = list(/mob/living/basic/pet/dog), - BB_BABIES_CHILD_TYPES = list(/mob/living/basic/pet/dog/corgi), + BB_BABIES_CHILD_TYPES = list(/mob/living/basic/pet/dog/corgi/puppy), ) planning_subtrees = list( diff --git a/code/datums/components/breeding.dm b/code/datums/components/breeding.dm index 6c323ed835d..2ecb58d89be 100644 --- a/code/datums/components/breeding.dm +++ b/code/datums/components/breeding.dm @@ -2,17 +2,17 @@ * A component to allow us to breed */ /datum/component/breed - /// additional mobs we can breed with + /// Additional mobs we can breed with var/list/can_breed_with - ///weighted list of the possible baby types + /// Weighted list of the possible baby types var/list/baby_paths - ///time to wait after breeding + /// Time to wait after breeding var/breed_timer - ///AI key we set when we're ready to breed + /// AI key we set when we're ready to breed var/breed_key = BB_BREED_READY - ///are we ready to breed? + /// Are we ready to breed? var/ready_to_breed = TRUE - ///callback after we give birth to the child + /// Callback after we give birth to the child var/datum/callback/post_birth /datum/component/breed/Initialize(list/can_breed_with = list(), breed_timer = 40 SECONDS, baby_paths = list(), post_birth) @@ -44,7 +44,6 @@ REMOVE_TRAIT(parent, TRAIT_MOB_BREEDER, REF(src)) post_birth = null - /datum/component/breed/proc/breed_with_partner(mob/living/source, mob/living/target) SIGNAL_HANDLER diff --git a/code/datums/components/happiness.dm b/code/datums/components/happiness.dm index 95d3b0d1f42..791b9b32b7c 100644 --- a/code/datums/components/happiness.dm +++ b/code/datums/components/happiness.dm @@ -62,7 +62,7 @@ /datum/component/happiness/proc/on_eat(datum/source) SIGNAL_HANDLER - increase_happiness_level(on_eat_change) + change_happiness_level(on_eat_change) /datum/component/happiness/proc/on_clean(mob/living/source) SIGNAL_HANDLER @@ -74,7 +74,7 @@ return NONE COOLDOWN_START(src, groom_cooldown, GROOM_COOLDOWN) - increase_happiness_level(on_groom_change) + change_happiness_level(on_groom_change) return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP /datum/component/happiness/proc/on_petted(datum/source, mob/living/petter, list/modifiers) @@ -91,42 +91,55 @@ /datum/component/happiness/proc/pet_animal() if(!COOLDOWN_FINISHED(src, pet_cooldown)) return - increase_happiness_level(on_petted_change) + change_happiness_level(on_petted_change) COOLDOWN_START(src, pet_cooldown, PET_COOLDOWN) -/datum/component/happiness/proc/increase_happiness_level(amount) - happiness_level = min(happiness_level + amount, maximum_happiness) - if(!HAS_TRAIT(parent, TRAIT_MOB_HIDE_HAPPINESS)) - var/mob/living/living_parent = parent +/datum/component/happiness/proc/change_happiness_level(amount) + var/old_happiness = happiness_level + happiness_level = clamp(happiness_level + amount, 0, maximum_happiness) + var/happiness_percentage = happiness_level / maximum_happiness + var/old_percentage = old_happiness / maximum_happiness + + var/old_threshold = 0 + var/new_threshold = 0 + for(var/check_percentage in callback_percentages) + if (check_percentage <= old_percentage) + old_threshold = check_percentage + if (check_percentage <= happiness_percentage) + new_threshold = check_percentage + + if (old_threshold != new_threshold) + SEND_SIGNAL(parent, COMSIG_MOB_HAPPINESS_CHANGE, happiness_percentage) + happiness_callback?.Invoke(happiness_percentage) + + var/mob/living/living_parent = parent + living_parent.ai_controller?.set_blackboard_key(blackboard_key, happiness_percentage) + + if(!HAS_TRAIT(parent, TRAIT_MOB_HIDE_HAPPINESS) && amount > 0) new /obj/effect/temp_visual/heart(living_parent.loc) living_parent.spin(spintime = 2 SECONDS, speed = 1) - START_PROCESSING(SSprocessing, src) + + if (happiness_level > 0) + START_PROCESSING(SSprocessing, src) /datum/component/happiness/proc/view_happiness(mob/living/source, mob/living/clicker) if(HAS_TRAIT(source, TRAIT_MOB_HIDE_HAPPINESS) || !istype(clicker) || !COOLDOWN_FINISHED(src, happiness_inspect) || !source.IsReachableBy(clicker)) return var/y_position = source.get_cached_height() + 1 var/obj/effect/overlay/happiness_overlay/hearts = new + hearts.pixel_w -= source.base_pixel_x + source.base_pixel_w hearts.pixel_y = y_position - hearts.set_hearts(happiness_level/maximum_happiness) + hearts.set_hearts(happiness_level / maximum_happiness) source.vis_contents += hearts COOLDOWN_START(src, happiness_inspect, INSPECT_TIMER) - /datum/component/happiness/process() - var/mob/living/living_parent = parent - var/happiness_percentage = happiness_level/maximum_happiness - living_parent.ai_controller?.set_blackboard_key(blackboard_key, happiness_percentage) - var/check_percentage_in_list = round(happiness_percentage * 100, 1) - if(check_percentage_in_list in callback_percentages) - SEND_SIGNAL(parent, COMSIG_MOB_HAPPINESS_CHANGE, happiness_percentage) - happiness_callback?.Invoke(happiness_percentage) - if(happiness_level <= 0) return PROCESS_KILL + var/mob/living/living_parent = parent var/modifier = living_parent.ai_controller?.blackboard[BB_BASIC_DEPRESSED] ? 2 : 1 - happiness_level = max(0, happiness_level - modifier) + change_happiness_level(-modifier) /obj/effect/overlay/happiness_overlay mouse_opacity = MOUSE_OPACITY_TRANSPARENT diff --git a/code/datums/components/healing_touch.dm b/code/datums/components/healing_touch.dm index 07f04cba01d..bd611558b6e 100644 --- a/code/datums/components/healing_touch.dm +++ b/code/datums/components/healing_touch.dm @@ -45,6 +45,8 @@ var/required_modifier /// Callback to run after healing a mob var/datum/callback/after_healed + /// Callback to run to get a multiplier for our healing value + var/datum/callback/healing_multiplier /datum/component/healing_touch/Initialize( heal_brute = 20, @@ -65,6 +67,7 @@ heal_color = COLOR_HEALING_CYAN, required_modifier = null, datum/callback/after_healed = null, + datum/callback/healing_multiplier = null, ) if (!isliving(parent)) return COMPONENT_INCOMPATIBLE @@ -87,6 +90,7 @@ src.heal_color = heal_color src.required_modifier = required_modifier src.after_healed = after_healed + src.healing_multiplier = healing_multiplier RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(try_healing)) // Players RegisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(try_healing)) // NPCs @@ -190,15 +194,21 @@ if (complete_text) healer.visible_message(span_notice("[format_string(complete_text, healer, target)]")) + var/mult = 1 + if (healing_multiplier) + mult = healing_multiplier.Invoke(healer, target) + if (mult == 0) + return + var/healed = target.heal_overall_damage( - brute = heal_brute, - burn = heal_burn, - stamina = heal_stamina, + brute = heal_brute * mult, + burn = heal_burn * mult, + stamina = heal_stamina * mult, required_bodytype = required_bodytype, updating_health = FALSE, ) - healed += target.adjustOxyLoss(-heal_oxy, updating_health = FALSE, required_biotype = valid_biotypes) - healed += target.adjustToxLoss(-heal_tox, updating_health = FALSE, required_biotype = valid_biotypes) + healed += target.adjustOxyLoss(-heal_oxy * mult, updating_health = FALSE, required_biotype = valid_biotypes) + healed += target.adjustToxLoss(-heal_tox * mult, updating_health = FALSE, required_biotype = valid_biotypes) if (healed <= 0) return diff --git a/code/datums/components/proficient_miner.dm b/code/datums/components/proficient_miner.dm index cdc3b65871b..cd9d02b1bd5 100644 --- a/code/datums/components/proficient_miner.dm +++ b/code/datums/components/proficient_miner.dm @@ -1,11 +1,17 @@ /// Component given to mobs that can mine when moving /datum/component/proficient_miner + /// Toolspeed for mining, 0 will cause it to instamine rock + var/mining_speed = 0 + /// Should we pass the do_after visuals to our rider if we are a mob? + var/pass_driver = FALSE /// Last tick when we bumpmined. Prevents diagonal bumpnining being thrice as fast as normal var/last_bumpmine_tick = -1 -/datum/component/proficient_miner/Initialize() +/datum/component/proficient_miner/Initialize(mining_speed = 0, pass_driver = FALSE) if (!ismovable(parent)) return COMPONENT_INCOMPATIBLE + src.mining_speed = mining_speed + src.pass_driver = pass_driver /datum/component/proficient_miner/RegisterWithParent() RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(on_bump)) @@ -26,12 +32,37 @@ return var/turf/closed/mineral/mineral_wall = target - if(!istype(mineral_wall, /turf/closed/mineral/gibtonite)) - last_bumpmine_tick = world.time - mineral_wall.gets_drilled(source) + if(istype(mineral_wall, /turf/closed/mineral/gibtonite)) + var/turf/closed/mineral/gibtonite/gibtonite_wall = mineral_wall + if(gibtonite_wall.stage != GIBTONITE_UNSTRUCK) + return + + if(user && mining_speed > 0) + INVOKE_ASYNC(src, PROC_REF(slow_mine), user, target) return - var/turf/closed/mineral/gibtonite/gibtonite_wall = mineral_wall - if(gibtonite_wall.stage == GIBTONITE_UNSTRUCK) - last_bumpmine_tick = world.time - mineral_wall.gets_drilled(source) + last_bumpmine_tick = world.time + mineral_wall.gets_drilled(source) + +/datum/component/proficient_miner/proc/slow_mine(mob/living/user, turf/closed/mineral/mineral_wall) + if(TIMER_COOLDOWN_RUNNING(mineral_wall, REF(user))) //prevents mining turfs in progress + return + + var/mining_delay = mineral_wall.tool_mine_speed * mining_speed + TIMER_COOLDOWN_START(mineral_wall, REF(user), mining_delay) + var/static/list/mine_sounds = list('sound/effects/pickaxe/picaxe1.ogg', 'sound/effects/pickaxe/picaxe2.ogg', 'sound/effects/pickaxe/picaxe3.ogg') + playsound(user, pick(mine_sounds), 50) + + var/mob/living/driver = null + if (pass_driver && length(user.buckled_mobs)) + driver = user.buckled_mobs[1] + + if(!do_after(user, mining_delay, mineral_wall, bar_override = driver)) + TIMER_COOLDOWN_END(mineral_wall, REF(user)) //if we fail we can start again immediately + return + + if (mining_delay > MIN_TOOL_SOUND_DELAY) + playsound(user, pick(mine_sounds), 50) + + if(istype(mineral_wall)) + mineral_wall.gets_drilled(driver || user) diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index 45e2b789ba5..a27e05915a4 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -119,8 +119,7 @@ return COMPONENT_DRIVER_BLOCK_MOVE var/mob/living/living_parent = parent step(living_parent, direction) - var/datum/movespeed_modifier/slowdown = get_cached_movespeed_modifier(living_parent.get_move_intent_slowdown()) - var/modified_move_delay = uses_native_speed ? living_parent.cached_multiplicative_slowdown - slowdown?.multiplicative_slowdown : vehicle_move_delay + var/modified_move_delay = uses_native_speed ? living_parent.cached_multiplicative_slowdown : vehicle_move_delay if(HAS_TRAIT(user, TRAIT_ROUGHRIDER)) // YEEHAW! switch(HAS_TRAIT(user, TRAIT_PRIMITIVE) ? SANITY_LEVEL_GREAT : user.mob_mood?.sanity_level) if(SANITY_LEVEL_GREAT) @@ -133,6 +132,8 @@ modified_move_delay *= 1.1 if(SANITY_LEVEL_INSANE) modified_move_delay *= 1.2 + if(NSCOMPONENT(direction) && EWCOMPONENT(direction)) + modified_move_delay = FLOOR(modified_move_delay * sqrt(2), world.tick_lag) COOLDOWN_START(src, vehicle_move_cooldown, modified_move_delay) return ..() @@ -675,18 +676,11 @@ force_dismount(buckled_mob, throw_range = 2, gentle = TRUE) /datum/component/riding/creature/raptor/get_rider_offsets_and_layers(pass_index, mob/offsetter) - if(!SSmapping.is_planetary()) - return list( - TEXT_NORTH = list(-1, 7), - TEXT_SOUTH = list(2, 10), - TEXT_EAST = list(0, 7), - TEXT_WEST = list(0, 7), - ) return list( - TEXT_NORTH = list(0, 7), - TEXT_SOUTH = list(0, 10), - TEXT_EAST = list(-3, 9), - TEXT_WEST = list(3, 9), + TEXT_NORTH = list(-1, 7), + TEXT_SOUTH = list(2, 10), + TEXT_EAST = list(0, 7), + TEXT_WEST = list(0, 7), ) /datum/component/riding/creature/raptor/get_parent_offsets_and_layers() @@ -705,3 +699,43 @@ /datum/component/riding/creature/raptor/combat ai_behavior_while_ridden = RIDING_PAUSE_AI_MOVEMENT + +/datum/component/riding/creature/raptor/healer/vehicle_mob_buckle(mob/living/ridden, mob/living/rider, force) + RegisterSignal(rider, COMSIG_MOB_STATCHANGE, PROC_REF(on_buckled_stat_change)) + return ..() + +/datum/component/riding/creature/raptor/healer/vehicle_mob_unbuckle(mob/living/formerly_ridden, mob/living/former_rider, force) + UnregisterSignal(former_rider, COMSIG_MOB_STATCHANGE) + return ..() + +/datum/component/riding/creature/raptor/healer/proc/on_buckled_stat_change(mob/living/source, new_stat, old_stat) + SIGNAL_HANDLER + + var/mob/living/basic/raptor/raptor = source.buckled + if (!istype(raptor)) // what + UnregisterSignal(source, COMSIG_MOB_STATCHANGE) + return + + // Heal the owner and flee whatever might've attacked them + if (new_stat == CONSCIOUS || new_stat == DEAD || old_stat != CONSCIOUS || !raptor.ai_controller) + ADD_TRAIT(raptor, TRAIT_AI_PAUSED, REF(src)) + return + + REMOVE_TRAIT(raptor, TRAIT_AI_PAUSED, REF(src)) + // Rip bozo, but you're not our friend + if (source in raptor.ai_controller.blackboard[BB_FRIENDS_LIST]) + raptor.ai_controller.set_blackboard_key(BB_INJURED_RAPTOR, source) + + for (var/mob/living/possible_hostile in view(5, raptor)) + if (possible_hostile.stat || possible_hostile.invisibility > raptor.see_invisible || source.faction_check_atom(possible_hostile)) + continue + raptor.ai_controller.set_blackboard_key(BB_BASIC_MOB_FLEE_TARGET, possible_hostile) + break + +/datum/component/riding/creature/raptor/small/get_rider_offsets_and_layers(pass_index, mob/offsetter) + return list( + TEXT_NORTH = list(-1, 5), + TEXT_SOUTH = list(2, 8), + TEXT_EAST = list(0, 5), + TEXT_WEST = list(0, 5), + ) diff --git a/code/datums/components/riding/riding_vehicle.dm b/code/datums/components/riding/riding_vehicle.dm index 5f314dd36a6..91e282a14e8 100644 --- a/code/datums/components/riding/riding_vehicle.dm +++ b/code/datums/components/riding/riding_vehicle.dm @@ -97,7 +97,10 @@ return step(movable_parent, direction) - COOLDOWN_START(src, vehicle_move_cooldown, vehicle_move_delay) + var/move_delay = vehicle_move_delay + if(NSCOMPONENT(direction) && EWCOMPONENT(direction)) + move_delay = FLOOR(move_delay * sqrt(2), world.tick_lag) + COOLDOWN_START(src, vehicle_move_cooldown, move_delay) if(QDELETED(src)) return diff --git a/code/datums/elements/basic_eating.dm b/code/datums/elements/basic_eating.dm index a0f5a2cedef..8b011823e16 100644 --- a/code/datums/elements/basic_eating.dm +++ b/code/datums/elements/basic_eating.dm @@ -16,10 +16,12 @@ var/drinking /// If true, we put food in our tummy instead of deleting it var/add_to_contents - /// Types the animal can eat. + /// If true, when add_to_contents would put the item into contents but when used for healing, the item is consumed instead + var/consume_healing + /// Types the animal can eat. Can be an assoc list with amount to heal/damage the mob by var/list/food_types -/datum/element/basic_eating/Attach(datum/target, heal_amt = 0, damage_amount = 0, damage_type = null, drinking = FALSE, add_to_contents = FALSE, food_types = list()) +/datum/element/basic_eating/Attach(datum/target, heal_amt = 0, damage_amount = 0, damage_type = null, drinking = FALSE, add_to_contents = FALSE, consume_healing = TRUE, food_types = list()) . = ..() if(!isliving(target)) @@ -31,6 +33,7 @@ src.damage_type = damage_type src.drinking = drinking src.add_to_contents = add_to_contents + src.consume_healing = consume_healing src.food_types = food_types RegisterSignal(target, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(try_feed)) @@ -66,7 +69,8 @@ /datum/element/basic_eating/proc/try_eating(mob/living/eater, atom/target, mob/living/feeder) if(!is_type_in_list(target, food_types)) return FALSE - if(SEND_SIGNAL(eater, COMSIG_MOB_PRE_EAT, target, feeder) & COMSIG_MOB_CANCEL_EAT) + var/list/effect_mult = list() + if(SEND_SIGNAL(eater, COMSIG_MOB_PRE_EAT, target, feeder, effect_mult) & COMSIG_MOB_CANCEL_EAT) return FALSE if(add_to_contents && !ismovable(target)) return FALSE @@ -76,22 +80,44 @@ else eat_verb = pick("bite","chew","nibble","gnaw","gobble","chomp") - if (heal_amt > 0) - var/healed = heal_amt && eater.health < eater.maxHealth - eater.heal_overall_damage(heal_amt) + var/best_match = null + var/best_value = 0 + for (var/food_path in food_types) + // Not an assoc list + if (isnull(food_types[food_path])) + break + if (istype(target, food_path) && (!best_match || ispath(food_path, best_match))) + best_match = food_path + best_value = food_types[food_path] + + var/to_heal = heal_amt + var/to_damage = damage_amount + + if (best_match) + to_heal = 0 + to_damage = 0 + if (best_value > 0) + to_heal = best_value + else if (best_value < 0) + to_damage = -best_value + + for (var/mult in effect_mult) + to_heal *= mult + to_damage *= mult + + if (to_heal > 0) + var/healed = eater.heal_overall_damage(to_heal) eater.visible_message(span_notice("[eater] [eat_verb]s [target]."), span_notice("You [eat_verb] [target][healed ? ", restoring some health" : ""].")) - - else if (damage_amount > 0 && damage_type) - eater.apply_damage(damage_amount, damage_type) - eater.visible_message(span_notice("[eater] [eat_verb]s [target], and seems to hurt itself."), span_notice("You [eat_verb] [target], hurting yourself in the process.")) - + else if (to_damage > 0 && damage_type) + var/damaged = eater.apply_damage(to_damage, damage_type) + eater.visible_message(span_notice("[eater] [eat_verb]s [target][damaged ? ", and seems to hurt [eater.p_themselves()]!" : "."]"), span_notice("You [eat_verb] [target][damaged ? ", hurting yourself in the process" : ""].")) else eater.visible_message(span_notice("[eater] [eat_verb]s [target]."), span_notice("You [eat_verb] [target].")) - finish_eating(eater, target, feeder) + finish_eating(eater, target, feeder, to_heal) return TRUE -/datum/element/basic_eating/proc/finish_eating(mob/living/eater, atom/target, mob/living/feeder) +/datum/element/basic_eating/proc/finish_eating(mob/living/eater, atom/target, mob/living/feeder, to_heal) set waitfor = FALSE if(drinking) playsound(eater.loc,'sound/items/drink.ogg', rand(10,50), TRUE) @@ -104,10 +130,12 @@ var/obj/item/stack/food_stack = target final_target = food_stack.split_stack(1) - eater.log_message("has eaten [target], [add_to_contents ? "swallowing it" : "destroying it"]!", LOG_ATTACK) + var/devour = add_to_contents && !to_heal + eater.log_message("has eaten [target], [devour ? "swallowing it" : "destroying it"]!", LOG_ATTACK) - if (add_to_contents) + if (devour) var/atom/movable/movable_target = final_target movable_target.forceMove(eater) else qdel(final_target) + diff --git a/code/datums/elements/raptor_food.dm b/code/datums/elements/raptor_food.dm new file mode 100644 index 00000000000..514509eaaba --- /dev/null +++ b/code/datums/elements/raptor_food.dm @@ -0,0 +1,87 @@ +/// Element which influences raptor children upon owner's consumption as food +/datum/element/raptor_food + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// Flat damage modifier + var/attack_modifier = null + /// Flat health modifier + var/health_modifier = null + /// Speed modifier + var/speed_modifier = null + /// Primary ability stat modifier + /// Multiplier equates to 1 + this + var/ability_modifier = null + /// Growth rate modifier + /// Multiplier equates to 1 + this + var/growth_modifier = null + /// Personality traits the child may get + var/list/personality_traits = null + /// Offspring color probability modifiers + var/list/color_chances = null + +/datum/element/raptor_food/Attach(obj/item/target, attack_modifier, health_modifier, speed_modifier, ability_modifier, growth_modifier, list/personality_traits, list/color_chances) + . = ..() + if (!isitem(target)) + return ELEMENT_INCOMPATIBLE + src.attack_modifier = attack_modifier + src.health_modifier = health_modifier + src.speed_modifier = speed_modifier + src.ability_modifier = ability_modifier + src.growth_modifier = growth_modifier + src.personality_traits = personality_traits + src.color_chances = color_chances + RegisterSignal(target, COMSIG_ITEM_EATEN_BY_BASIC_MOB, PROC_REF(on_eaten)) + RegisterSignal(target, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(on_examine_more)) + +/datum/element/raptor_food/Detach(datum/source, ...) + UnregisterSignal(source, list(COMSIG_ITEM_EATEN_BY_BASIC_MOB, COMSIG_ATOM_EXAMINE_MORE)) + return ..() + +/datum/element/raptor_food/proc/on_examine_more(obj/item/source, mob/examiner, list/examine_list) + SIGNAL_HANDLER + + if (!istype(examiner.buckled, /mob/living/basic/raptor)) + return + + // Just to check for priority + var/strognest_effect = max(attack_modifier, health_modifier, speed_modifier, ability_modifier, growth_modifier, 0) + + // Only personality or color probability effects, or just pure negatives + if (strognest_effect == 0) + examine_list += span_notice("You reckon this would have unique effects on your raptor's offspring if you fed it to them...") + return + + if (strognest_effect == attack_modifier) + examine_list += span_notice("You reckon this would have make your raptor's offspring stronger if you fed it to them...") + else if (strognest_effect == health_modifier) + examine_list += span_notice("You reckon this would have make your raptor's offspring tougher if you fed it to them...") + else if (strognest_effect == speed_modifier) + examine_list += span_notice("You reckon this would have make your raptor's offspring faster if you fed it to them...") + else if (strognest_effect == ability_modifier) + examine_list += span_notice("You reckon this would have make your raptor's offspring more capable if you fed it to them...") + else if (strognest_effect == growth_modifier) + examine_list += span_notice("You reckon this would have make your raptor's offspring grow faster if you fed it to them...") + +/datum/element/raptor_food/proc/on_eaten(obj/item/source, mob/living/eater, mob/living/feeder) + SIGNAL_HANDLER + + if (!istype(eater, /mob/living/basic/raptor)) + return + + var/mob/living/basic/raptor/raptor = eater + var/list/our_food = raptor.inherited_stats.foods_eaten[source.type] + if (our_food) + our_food["amount"] += 1 + return + + raptor.inherited_stats.foods_eaten[source.type] = list( + "amount" = 1, + "attack" = attack_modifier, + "health" = health_modifier, + "speed" = speed_modifier, + "ability" = ability_modifier, + "growth" = growth_modifier, + "traits" = personality_traits?.Copy(), + "color_chances" = color_chances?.Copy(), + ) + diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index 51a6cd5e463..4c36ed6394f 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -791,8 +791,9 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) return NONE if(istype(over_object, /atom/movable/screen/inventory/hand)) - if(real_location.loc != user || !user.can_perform_action(parent, FORBID_TELEKINESIS_REACH | ALLOW_RESTING)) + if(parent.loc != user || !user.can_perform_action(parent, FORBID_TELEKINESIS_REACH | ALLOW_RESTING)) return NONE + if(isitem(parent)) var/obj/item/item_parent = parent if(!item_parent.can_mob_unequip(user)) @@ -803,15 +804,20 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) parent.add_fingerprint(user) return COMPONENT_CANCEL_MOUSEDROP_ONTO - if(ismob(over_object)) - if(over_object != user || !user.can_perform_action(parent, FORBID_TELEKINESIS_REACH | ALLOW_RESTING)) + if(over_object == user) + if(!user.can_perform_action(parent, FORBID_TELEKINESIS_REACH | ALLOW_RESTING)) return NONE + if(isliving(parent) && user.pulling == parent) + var/mob/living/as_living = parent + if(as_living.can_be_held) + return + parent.add_fingerprint(user) INVOKE_ASYNC(src, PROC_REF(open_storage), user) return COMPONENT_CANCEL_MOUSEDROP_ONTO - if(istype(over_object, /atom/movable/screen)) + if(istype(over_object, /atom/movable/screen) || ismob(over_object)) return NONE if(!user.can_perform_action(over_object, FORBID_TELEKINESIS_REACH)) diff --git a/code/game/objects/effects/spawners/random/lavaland_mobs.dm b/code/game/objects/effects/spawners/random/lavaland_mobs.dm index 4c6cf035324..4fa771c7d77 100644 --- a/code/game/objects/effects/spawners/random/lavaland_mobs.dm +++ b/code/game/objects/effects/spawners/random/lavaland_mobs.dm @@ -55,11 +55,41 @@ desc = "Chance to spawn a rare shiny version." icon = 'icons/mob/simple/lavaland/raptor_big.dmi' icon_state = "raptor_red" + pixel_x = -12 loot = list( - /mob/living/basic/raptor/red = 20, - /mob/living/basic/raptor/white = 20, - /mob/living/basic/raptor/purple = 20, - /mob/living/basic/raptor/green = 20, - /mob/living/basic/raptor/yellow = 20, + /mob/living/basic/raptor/red = 25, + /mob/living/basic/raptor/white = 25, + /mob/living/basic/raptor/purple = 25, + /mob/living/basic/raptor/green = 25, + /mob/living/basic/raptor/yellow = 25, + /mob/living/basic/raptor/blue = 25, /mob/living/basic/raptor/black = 1, ) + +/obj/effect/spawner/random/lavaland_mob/raptor/young + name = "random raptor youngling" + icon_state = "young_red" + loot = list( + /mob/living/basic/raptor/young/red = 25, + /mob/living/basic/raptor/young/white = 25, + /mob/living/basic/raptor/young/purple = 25, + /mob/living/basic/raptor/young/green = 25, + /mob/living/basic/raptor/young/yellow = 25, + /mob/living/basic/raptor/young/blue = 25, + /mob/living/basic/raptor/young/black = 1, + ) + +/obj/effect/spawner/random/lavaland_mob/raptor/baby + name = "random raptor chick" + icon = 'icons/mob/simple/lavaland/raptor_baby.dmi' + icon_state = "baby_red" + pixel_x = 0 + loot = list( + /mob/living/basic/raptor/baby/red = 25, + /mob/living/basic/raptor/baby/white = 25, + /mob/living/basic/raptor/baby/purple = 25, + /mob/living/basic/raptor/baby/green = 25, + /mob/living/basic/raptor/baby/yellow = 25, + /mob/living/basic/raptor/baby/blue = 25, + /mob/living/basic/raptor/baby/black = 1, + ) diff --git a/code/game/objects/items/food/meatslab.dm b/code/game/objects/items/food/meatslab.dm index 01c4c4b8f7a..55fa78c3295 100644 --- a/code/game/objects/items/food/meatslab.dm +++ b/code/game/objects/items/food/meatslab.dm @@ -211,6 +211,10 @@ foodtypes = RAW | MEAT | BUGS blood_decal_type = /obj/effect/decal/cleanable/insectguts +/obj/item/food/meat/slab/bugmeat/Initialize(mapload) + . = ..() + AddElement(/datum/element/raptor_food, health_modifier = 2, color_chances = string_list(list(/datum/raptor_color/green = 2))) + /obj/item/food/meat/slab/mouse name = "mouse meat" desc = "A slab of mouse meat. Best not eat it raw." @@ -337,6 +341,10 @@ tastes = list("meat" = 1) foodtypes = RAW | MEAT | TOXIC +/obj/item/food/meat/slab/goliath/Initialize(mapload) + . = ..() + AddElement(/datum/element/raptor_food, attack_modifier = 0.5, speed_modifier = -0.05, color_chances = string_list(list(/datum/raptor_color/red = 5))) + /obj/item/food/meat/slab/goliath/burn() visible_message(span_notice("[src] finishes cooking!")) new /obj/item/food/meat/steak/goliath(loc) @@ -569,6 +577,10 @@ trash_type = null tastes = list("meat" = 1, "rock" = 1) +/obj/item/food/meat/steak/goliath/Initialize(mapload) + . = ..() + AddElement(/datum/element/raptor_food, attack_modifier = 1, speed_modifier = -0.075, color_chances = string_list(list(/datum/raptor_color/red = 7))) + /obj/item/food/meat/steak/gondola name = "gondola steak" tastes = list("meat" = 1, "tranquility" = 1) diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm index 1082d682c4f..349316a2c8a 100644 --- a/code/game/objects/items/stacks/bscrystal.dm +++ b/code/game/objects/items/stacks/bscrystal.dm @@ -28,6 +28,7 @@ . = ..() pixel_x = rand(-5, 5) pixel_y = rand(-5, 5) + AddElement(/datum/element/raptor_food, ability_modifier = 0.05, attack_modifier = 0.5, color_chances = string_list(list(/datum/raptor_color/black = 1))) /obj/item/stack/ore/bluespace_crystal/get_part_rating() return 1 diff --git a/code/modules/fishing/fish/types/mining.dm b/code/modules/fishing/fish/types/mining.dm index 14e5ce9810b..c5b1f36b87f 100644 --- a/code/modules/fishing/fish/types/mining.dm +++ b/code/modules/fishing/fish/types/mining.dm @@ -205,6 +205,7 @@ sound_on_success = 'sound/items/weapons/parry.ogg',\ effect_on_success = /obj/effect/temp_visual/guardian/phase,\ ) + AddElement(/datum/element/raptor_food, attack_modifier = 1.5, growth_modifier = -0.075) /obj/item/fish/lavaloop/get_fish_taste() return list("chewy fish" = 2) diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm index d9e6b3c16c8..7242c24be29 100644 --- a/code/modules/mining/lavaland/ash_flora.dm +++ b/code/modules/mining/lavaland/ash_flora.dm @@ -230,6 +230,10 @@ wine_power = 50 foodtypes = FRUIT +/obj/item/food/grown/ash_flora/cactus_fruit/Initialize(mapload) + . = ..() + AddElement(/datum/element/raptor_food, growth_modifier = 0.1, ability_modifier = -0.05) + /obj/item/food/grown/ash_flora/seraka name = "seraka cap" desc = "Small, deeply flavourful mushrooms originally native to Tizira." @@ -237,6 +241,10 @@ seed = /obj/item/seeds/lavaland/seraka wine_power = 40 +/obj/item/food/grown/ash_flora/seraka/Initialize(mapload) + . = ..() + AddElement(/datum/element/raptor_food, ability_modifier = 0.1) + /obj/item/food/grown/ash_flora/fireblossom name = "fire blossom" desc = "A flower from a fire blossom." @@ -245,7 +253,12 @@ seed = /obj/item/seeds/lavaland/fireblossom wine_power = 40 -//SEEDS +/obj/item/food/grown/ash_flora/fireblossom/Initialize(mapload) + . = ..() + // Fire flowers make fireproof raptors + AddElement(/datum/element/raptor_food, color_chances = string_list(list(/datum/raptor_color/blue = 5))) + +// SEEDS /obj/item/seeds/lavaland name = "lavaland seeds" diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 159711837e9..621b516254b 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -215,6 +215,10 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ scan_state = "rock_diamond" merge_type = /obj/item/stack/ore/diamond +/obj/item/stack/ore/diamond/Initialize(mapload) + . = ..() + AddElement(/datum/element/raptor_food, speed_modifier = 0.05, health_modifier = -1, color_chances = string_list(list(/datum/raptor_color/yellow = 3))) + /obj/item/stack/ore/diamond/five amount = 5 diff --git a/code/modules/mob/living/basic/drone/_drone.dm b/code/modules/mob/living/basic/drone/_drone.dm index 10d7ccc442a..d595dc5196b 100644 --- a/code/modules/mob/living/basic/drone/_drone.dm +++ b/code/modules/mob/living/basic/drone/_drone.dm @@ -48,6 +48,7 @@ lighting_cutoff_blue = 25 can_be_held = TRUE worn_slot_flags = ITEM_SLOT_HEAD + inhand_holder_type = /obj/item/mob_holder/drone /// `TRUE` if we have picked our visual appearance, `FALSE` otherwise (default) var/picked = FALSE /// Stored drone color, restored when unhacked diff --git a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm index 29f5e436d4f..4f0fd61f1ba 100644 --- a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm +++ b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm @@ -80,6 +80,7 @@ if(beegent) reee[beegent.type] = 5 holder.AddComponentFrom(SOURCE_EDIBLE_INNATE, /datum/component/edible, reee, null, BEE_FOODGROUPS, 10, 0, list("bee"), null, 10) + SEND_SIGNAL(src, COMSIG_LIVING_SCOOPED_UP, picker, holder) picker.visible_message(span_warning("[picker] scoops up [src]!")) picker.put_in_hands(holder) diff --git a/code/modules/mob/living/basic/lavaland/raptor/_raptor.dm b/code/modules/mob/living/basic/lavaland/raptor/_raptor.dm index 174180cec33..2a772d7e262 100644 --- a/code/modules/mob/living/basic/lavaland/raptor/_raptor.dm +++ b/code/modules/mob/living/basic/lavaland/raptor/_raptor.dm @@ -1,12 +1,3 @@ -GLOBAL_LIST_INIT(raptor_growth_paths, list( - /mob/living/basic/raptor/baby_raptor/red = list(RAPTOR_PURPLE, RAPTOR_WHITE), - /mob/living/basic/raptor/baby_raptor/white = list(RAPTOR_GREEN, RAPTOR_PURPLE), - /mob/living/basic/raptor/baby_raptor/purple = list(RAPTOR_GREEN, RAPTOR_WHITE), - /mob/living/basic/raptor/baby_raptor/yellow = list(RAPTOR_GREEN, RAPTOR_RED), - /mob/living/basic/raptor/baby_raptor/green = list(RAPTOR_RED, RAPTOR_YELLOW), - /mob/living/basic/raptor/baby_raptor/blue = list(RAPTOR_RED, RAPTOR_PURPLE) -)) - GLOBAL_LIST_INIT(raptor_inherit_traits, list( BB_BASIC_DEPRESSED = "Depressed", BB_RAPTOR_MOTHERLY = "Motherly", @@ -16,23 +7,25 @@ GLOBAL_LIST_INIT(raptor_inherit_traits, list( GLOBAL_LIST_EMPTY(raptor_population) -#define HAPPINESS_BOOST_DAMPENER 0.3 - -/// Innate raptor offsets -#define RAPTOR_INNATE_SOURCE "raptor_innate" - /mob/living/basic/raptor name = "raptor" desc = "A trusty, powerful steed. Taming it might prove difficult..." icon = 'icons/mob/simple/lavaland/raptor_big.dmi' - speed = 2 + icon_state = "raptor_red" + base_icon_state = "raptor" + pixel_w = -12 + base_pixel_w = -12 + speed = 0.5 mob_biotypes = MOB_ORGANIC|MOB_BEAST - maxHealth = 270 - health = 270 + maxHealth = 200 + health = 200 melee_damage_lower = 10 melee_damage_upper = 15 combat_mode = TRUE mob_size = MOB_SIZE_LARGE + head_icon = 'icons/mob/clothing/back/pets_back.dmi' + worn_slot_flags = ITEM_SLOT_BACK + held_w_class = WEIGHT_CLASS_BULKY unsuitable_atmos_damage = 0 minimum_survivable_temperature = BODYTEMP_COLD_ICEBOX_SAFE maximum_survivable_temperature = INFINITY @@ -45,14 +38,13 @@ GLOBAL_LIST_EMPTY(raptor_population) /obj/item/food/meat/slab/chicken = 4, /obj/item/stack/sheet/bone = 2, ) - ai_controller = /datum/ai_controller/basic_controller/raptor - ///can this mob breed + // AI controller is set by our color + ai_controller = null + /// Can this raptor breed? var/can_breed = TRUE - ///should we change offsets on direction change? + /// Should we change offsets on direction change? var/change_offsets = TRUE - ///can we ride this mob - var/ridable_component = /datum/component/riding/creature/raptor - //pet commands when we tame the raptor + /// Pet commands when we tame the raptor var/static/list/pet_commands = list( /datum/pet_command/breed, /datum/pet_command/idle, @@ -62,24 +54,47 @@ GLOBAL_LIST_EMPTY(raptor_population) /datum/pet_command/follow, /datum/pet_command/fetch, ) - ///things we inherited from our parent - var/datum/raptor_inheritance/inherited_stats - ///our color - var/raptor_color - ///the description that appears in the dex - var/dex_description - ///path of our child - var/child_path + /// Can we wear a collar? If so, what is our icon state prefix for it? + var/collar_state = "raptor" + /// Raptor color datum assigned to this raptor, this is a singleton + var/datum/raptor_color/raptor_color = null + /// Are we an adult, youngling or baby? + var/growth_stage = RAPTOR_ADULT + /// Our current growth progress towards the next stage if we're a youngling or a baby + var/growth_progress = 0 + /// Probability of getting progress in the baby phase each second + var/growth_probability = 80 + /// Food types that we can consume + var/static/list/food_types = list( + /obj/item/stack/ore = 0, + /obj/item/food/meat = 15, + /obj/item/food/meat/slab = 25, + /obj/item/food/meat/slab/spider = -15, // Toxic meats + /obj/item/food/meat/slab/xeno = -15, + /obj/item/food/meat/steak = 50, + /obj/item/food/grown/ash_flora = 10, + /obj/item/fish = 15, + /obj/item/organ = 25, + ) + /// Inheritance datum we store our genetic data in + var/datum/raptor_inheritance/inherited_stats = null + /// Current happiness value of the raptor + var/happiness_percentage = 0 - -/mob/living/basic/raptor/Initialize(mapload) +/mob/living/basic/raptor/Initialize(mapload, datum/raptor_color/color_type, datum/raptor_inheritance/passed_stats) . = ..() - if(SSmapping.is_planetary()) - change_offsets = FALSE - icon = 'icons/mob/simple/lavaland/raptor_icebox.dmi' + inherited_stats = passed_stats || new(src) + // First thing as to go before tameable in change_growth_stage() + AddElement(/datum/element/basic_eating, food_types = food_types) + raptor_color = GLOB.raptor_colors[color_type || raptor_color || pick(GLOB.raptor_colors)] + raptor_color.setup_raptor(src) - AddElement(/datum/element/wears_collar) - add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE), INNATE_TRAIT) + if (growth_stage == RAPTOR_ADULT) + raptor_color.setup_adult(src) + else + change_growth_stage(growth_stage, RAPTOR_ADULT) + + add_traits(list(TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE, TRAIT_MINING_AOE_IMMUNE), INNATE_TRAIT) AddElement(\ /datum/element/crusher_loot,\ trophy_type = /obj/item/crusher_trophy/raptor_feather,\ @@ -87,15 +102,364 @@ GLOBAL_LIST_EMPTY(raptor_population) drop_immediately = FALSE,\ ) - if(!mapload) + if (!mapload) GLOB.raptor_population += REF(src) - AddComponent(/datum/component/obeys_commands, pet_commands) + AddComponent(/datum/component/obeys_commands, pet_commands, list(0, -base_pixel_w)) AddElement(\ /datum/element/change_force_on_death,\ move_resist = MOVE_RESIST_DEFAULT,\ ) + RegisterSignal(src, COMSIG_MOB_ATE, PROC_REF(on_eat)) + RegisterSignal(src, COMSIG_MOB_PRE_EAT, PROC_REF(on_pre_eat)) + AddElement(/datum/element/ai_retaliate) + AddElement(/datum/element/ai_flee_while_injured, stop_fleeing_at = 0.5, start_fleeing_below = 0.2) + + if (can_breed) + add_breeding_component() + + // Babies handle it in their change_growth_stage + if (growth_stage != RAPTOR_BABY) + update_blackboard() + + AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW) + RegisterSignal(src, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_dir_change)) + RegisterSignal(src, COMSIG_LIVING_SCOOPED_UP, PROC_REF(on_picked_up)) + adjust_offsets(dir) + add_happiness_component() + +/mob/living/basic/raptor/Destroy() + raptor_color = null + GLOB.raptor_population -= REF(src) + return ..() + +/mob/living/basic/raptor/death(gibbed) + . = ..() + GLOB.raptor_population -= REF(src) + +/mob/living/basic/raptor/buckle_mob(mob/living/target, force = FALSE, check_loc = TRUE, buckle_mob_flags= NONE) + if(!iscarbon(target)) + return + return ..() + +/mob/living/basic/raptor/proc/on_dir_change(datum/source, old_dir, new_dir) + SIGNAL_HANDLER + adjust_offsets(new_dir) + +/mob/living/basic/raptor/proc/adjust_offsets(direction) + if (!change_offsets) + return + + switch (direction) + if (NORTH, SOUTH) + add_offsets(RAPTOR_INNATE_SOURCE, w_add = 0, animate = FALSE) + if (EAST, SOUTHEAST, NORTHEAST) + add_offsets(RAPTOR_INNATE_SOURCE, w_add = -8, animate = FALSE) + if (WEST, SOUTHWEST, NORTHWEST) + add_offsets(RAPTOR_INNATE_SOURCE, w_add = 8, animate = FALSE) + +/mob/living/basic/raptor/examine(mob/user) + . = ..() + if (stat == DEAD) + return + + switch (health / maxHealth) + if (0 to 0.2) + . += span_italics(span_bolddanger("[p_They()] [p_are()] gruesomly wounded, barely staying up on [p_their()] feet!")) + if (0.2 to 0.4) + . += span_danger("[p_They()] [p_have()] heavy injuries and open wounds all around [p_their()] body!") + if (0.4 to 0.6) + . += span_warning("[p_They()] [p_are()] noticeably hurt, limping from [p_their()] cuts and bruises.") + if (0.6 to 0.8) + . += span_warning("[p_They()] [p_are()] visibly injured, a few bruises and cuts showing between [p_their()] feathers.") + if (0.8 to 0.999) + . += span_notice("[p_They()] [p_have()] a few minor bruises and scratches.") + +/mob/living/basic/raptor/Life(seconds_per_tick, times_fired) + . = ..() + if (growth_stage != RAPTOR_BABY || HAS_TRAIT(src, TRAIT_STASIS) || stat == DEAD) + return + if (!SPT_PROB(growth_probability * (1 + happiness_percentage * RAPTOR_GROWTH_HAPPINESS_MULTIPLIER), seconds_per_tick)) + return + growth_progress += rand(RAPTOR_BABY_GROWTH_LOWER, RAPTOR_BABY_GROWTH_UPPER) + if (growth_progress >= RAPTOR_GROWTH_REQUIRED) + change_growth_stage(RAPTOR_YOUNG) + growth_progress = 0 + +/mob/living/basic/raptor/early_melee_attack(atom/target, list/modifiers, ignore_cooldown) + . = ..() + if(!.) + return FALSE + if(!istype(target, /obj/structure/ore_container/food_trough/raptor_trough)) + return TRUE + var/obj/ore_food = locate(/obj/item/stack/ore) in target + if(isnull(ore_food)) + balloon_alert(src, "no food!") + else + UnarmedAttack(ore_food, TRUE, modifiers) + return FALSE + +/mob/living/basic/raptor/melee_attack(mob/living/target, list/modifiers, ignore_cooldown) + if (!combat_mode && istype(target, /mob/living/basic/raptor)) + var/mob/living/basic/raptor/possible_baby = target + if (possible_baby.growth_stage == RAPTOR_BABY) + return target.attack_hand(src, list(LEFT_CLICK = TRUE)) + return ..() + +/mob/living/basic/raptor/proc/add_breeding_component() + var/static/list/partner_types = typecacheof(list(/mob/living/basic/raptor)) + var/static/list/baby_types = list(/obj/item/food/egg = 1) ///raptor_egg = 1) + AddComponent(\ + /datum/component/breed, \ + can_breed_with = partner_types, \ + baby_paths = baby_types, \ + breed_timer = 3 MINUTES, \ + post_birth = CALLBACK(src, PROC_REF(egg_inherit)), \ + ) + +/mob/living/basic/raptor/proc/add_happiness_component() + var/static/list/percentage_callbacks = list(0, 15, 25, 35, 50, 75, 90, 100) + // Higher happiness cap so it decays slower, about 15 minutes from full to zero + AddComponent(\ + /datum/component/happiness, \ + maximum_happiness = 900, \ + on_petted_change = 50, \ + on_groom_change = 200, \ + on_eat_change = 150, \ + callback_percentages = percentage_callbacks,\ + happiness_callback = CALLBACK(src, PROC_REF(happiness_change)),\ + ) + +/mob/living/basic/raptor/proc/happiness_change(percent_value) + var/attack_boost = round((percent_value - happiness_percentage) * RAPTOR_HAPPINESS_DAMAGE_BOOST, 1) + melee_damage_lower += attack_boost + melee_damage_upper += attack_boost + happiness_percentage = percent_value + +/mob/living/basic/raptor/projectile_hit(obj/projectile/hitting_projectile, def_zone, piercing_hit, blocked) + // Most colors will redirect shots to their rider as to increase their own survivability, and only tank melee attacks + if (raptor_color.redirect_shots && length(buckled_mobs)) + return buckled_mobs[1].projectile_hit(hitting_projectile, def_zone, piercing_hit, blocked) + return ..() + +/// Pass our genetic data to the egg +/mob/living/basic/raptor/proc/egg_inherit(obj/item/food/egg/raptor_egg/baby_egg, mob/living/basic/raptor/partner) + var/datum/raptor_inheritance/child_genes = new() + child_genes.set_parents(src, partner) + baby_egg.inherited_stats = child_genes + baby_egg.child_color = get_child_color(partner) + // Halve our food modifiers every time we breed + for (var/food_type in inherited_stats.foods_eaten) + var/list/stat_mods = inherited_stats.foods_eaten[food_type] + stat_mods["amount"] /= 2 + stat_mods["attack"] /= 2 + stat_mods["health"] /= 2 + stat_mods["speed"] /= 2 + stat_mods["ability"] /= 2 + stat_mods["growth"] /= 2 + var/list/trait_list = stat_mods["traits"] + for (var/i in 1 to ceil(length(trait_list) / 2)) + trait_list -= pick(trait_list) + + var/list/color_chances = stat_mods["color_chances"] + for (var/datum/raptor_color/color_type as anything in color_chances) + color_chances[color_type] = floor(color_chances[color_type] / 2) + if (!color_chances[color_type]) + color_chances -= color_type + +/mob/living/basic/raptor/proc/get_child_color(mob/living/basic/raptor/partner) + if (raptor_color == partner.raptor_color) + return raptor_color.type + + if (raptor_color.guaranteed_crossbreeds[partner.raptor_color.type]) + return raptor_color.guaranteed_crossbreeds[partner.raptor_color.type] + + // This should be redundant as they should be mirroring eachother, but just in case + if (partner.raptor_color.guaranteed_crossbreeds[raptor_color.type]) + return partner.raptor_color.guaranteed_crossbreeds[raptor_color.type] + + // We've got all the colors in our family tree and aren't rolling a guarantee, bingo + if (length(inherited_stats.parent_colors | partner.inherited_stats.parent_colors | raptor_color.type | partner.raptor_color.type) == length(GLOB.raptor_colors)) + return /datum/raptor_color/black + + var/list/prob_list = list() + for (var/datum/raptor_color/color_type as anything in GLOB.raptor_colors) + prob_list[color_type] = color_type::spawn_chance + + var/amount_eaten = 0 + for (var/food_type in inherited_stats.foods_eaten) + var/list/stat_mods = inherited_stats.foods_eaten[food_type] + amount_eaten += stat_mods["amount"] + + for (var/food_type in inherited_stats.foods_eaten) + var/list/stat_mods = inherited_stats.foods_eaten[food_type] + var/list/color_chances = stat_mods["color_chances"] + for (var/datum/raptor_color/color_type as anything in color_chances) + prob_list[color_type] += floor(color_chances[color_type] * stat_mods["amount"]) + + return pick_weight(prob_list) + +/mob/living/basic/raptor/proc/on_picked_up(mob/living/basic/raptor/source, mob/living/user, obj/item/mob_holder/holder) + SIGNAL_HANDLER + // Our inventory code sucks so we have to do this + holder.icon = 'icons/mob/simple/lavaland/raptor_baby.dmi' + holder.icon_state = icon_state + holder.alternate_worn_layer = HEAD_LAYER + holder.pixel_w = 0 + holder.pixel_z = 0 + holder.base_pixel_w = 0 + holder.base_pixel_z = 0 + +/mob/living/basic/raptor/proc/on_pre_eat(datum/source, obj/item/potential_food, list/effect_mult) + SIGNAL_HANDLER + + if (isorgan(potential_food)) + var/obj/item/organ/guts = potential_food + if (!(guts.organ_flags & ORGAN_EDIBLE) || !(guts.organ_flags & ORGAN_ORGANIC)) + return COMSIG_MOB_CANCEL_EAT + + if (happiness_percentage) + effect_mult += happiness_percentage * RAPTOR_GROWTH_HAPPINESS_MULTIPLIER + +/mob/living/basic/raptor/proc/on_eat(datum/source, atom/food, mob/living/feeder) + SIGNAL_HANDLER + + if (!istype(food, /obj/item/food)) + return + + var/obj/item/food/meal = food + var/is_flora = istype(meal, /obj/item/food/grown/ash_flora) + var/is_meat = (meal.foodtypes & (MEAT|GORE)) + // Babies cannot gain growth from eating meat, only plants, but they get some passively + if ((!is_meat || growth_stage == RAPTOR_BABY) && !is_flora) + return + + if (growth_stage == RAPTOR_ADULT) + return + + // Better meals make your raptor grow faster + var/growth_value = meal.crafting_complexity * RAPTOR_MEAL_COMPLEXITY_GROWTH_FACTOR + (is_flora ? RAPTOR_GROWTH_BASE_PLANT : RAPTOR_GROWTH_BASE_MEAT) + growth_progress += growth_value * (1 + inherited_stats.growth_modifier) * (1 + happiness_percentage * RAPTOR_GROWTH_HAPPINESS_MULTIPLIER) + if (growth_progress >= RAPTOR_GROWTH_REQUIRED) + change_growth_stage(growth_stage == RAPTOR_BABY ? RAPTOR_YOUNG : RAPTOR_ADULT) + growth_progress = 0 + +/// Changes the raptor to a new growth stage. Only should be done forwards, or on raptor init as the first thing before everything else +/// Sorry for the monolith, but splitting it up results in even worse looking code with a ton of duplicate calls and assignments +/// And making a *second* datum is just insanity +/mob/living/basic/raptor/proc/change_growth_stage(new_stage, prev_stage = growth_stage) + if (new_stage == prev_stage) + return FALSE + + if (SEND_SIGNAL(src, COMSIG_RAPTOR_GROWTH_STAGE_CHANGE, new_stage, prev_stage) & COMPONENT_CANCEL_RAPTOR_GROWTH) + return FALSE + + growth_stage = new_stage + + // Visuals + switch (new_stage) + if (RAPTOR_BABY) + name = "baby raptor" + desc = "Will this grow into something useful?" + icon = 'icons/mob/simple/lavaland/raptor_baby.dmi' + base_icon_state = "baby" + base_pixel_w = 0 + mob_size = MOB_SIZE_TINY + if (RAPTOR_YOUNG) + name = "raptor youngling" + desc = "A young raptor that can grow into a robust, trusty steed. Rather naive at such an age, it shouldn't be too hard to tame." + icon = 'icons/mob/simple/lavaland/raptor_big.dmi' + base_icon_state = "young" + base_pixel_w = initial(base_pixel_w) + mob_size = MOB_SIZE_HUMAN + if (RAPTOR_ADULT) + name = "raptor" + desc = initial(desc) + icon = 'icons/mob/simple/lavaland/raptor_big.dmi' + base_icon_state = "raptor" + base_pixel_w = initial(base_pixel_w) + mob_size = initial(mob_size) + + can_be_held = initial(density) + density = initial(density) + move_resist = initial(move_resist) + can_breed = initial(can_breed) + change_offsets = initial(change_offsets) + + if (new_stage == RAPTOR_ADULT) + // Adults need to be tamed with skill rather than snacks + qdel(GetComponent(/datum/component/tameable)) + else // Make us teeny-tiny + can_be_held = TRUE + density = FALSE + can_breed = FALSE + move_resist = MOVE_RESIST_DEFAULT + change_offsets = FALSE + + if (prev_stage == RAPTOR_ADULT) + AddComponent(/datum/component/tameable, food_types = food_types, tame_chance = 25, bonus_tame_chance = 15, unique = TRUE) + + if (change_offsets) + adjust_offsets(dir) + else + remove_offsets(RAPTOR_INNATE_SOURCE, FALSE) + + if (can_breed) + add_breeding_component() + else + qdel(GetComponent(/datum/component/breed)) + + var/obj/item/mob_holder/holder = null + if (istype(loc, /obj/item/mob_holder)) + holder = loc + if (!can_be_held) + holder.release() + holder = null + + if (collar_state) + RemoveElement(/datum/element/wears_collar, collar_icon = 'icons/mob/simple/lavaland/raptor_big.dmi', collar_icon_state = "[collar_state]_") + + if (new_stage == RAPTOR_BABY) + collar_state = null + var/list/friends = ai_controller?.blackboard[BB_FRIENDS_LIST] + if (friends) + friends = friends.Copy() + QDEL_NULL(ai_controller) + ai_controller = new /datum/ai_controller/basic_controller/baby_raptor(src) + for (var/old_friend in friends) + ai_controller.insert_blackboard_key_lazylist(BB_FRIENDS_LIST, old_friend) + update_blackboard() + held_w_class = WEIGHT_CLASS_SMALL + worn_slot_flags = NONE + holder?.update_weight_class(held_w_class) + else + collar_state = base_icon_state + AddElement(/datum/element/wears_collar, collar_icon = 'icons/mob/simple/lavaland/raptor_big.dmi', collar_icon_state = "[collar_state]_") + if (prev_stage == RAPTOR_BABY) + var/list/friends = ai_controller?.blackboard[BB_FRIENDS_LIST] + if (friends) + friends = friends.Copy() + QDEL_NULL(ai_controller) + ai_controller = new raptor_color.ai_controller(src) + for (var/old_friend in friends) + ai_controller.insert_blackboard_key_lazylist(BB_FRIENDS_LIST, old_friend) + update_blackboard() + held_w_class = WEIGHT_CLASS_BULKY + worn_slot_flags = ITEM_SLOT_BACK + holder?.update_weight_class(held_w_class) + + // And finish the setup on our color's side + switch (new_stage) + if (RAPTOR_BABY) + raptor_color.setup_baby(src) + if (RAPTOR_YOUNG) + raptor_color.setup_young(src) + if (RAPTOR_ADULT) + raptor_color.setup_adult(src) + return TRUE + +/mob/living/basic/raptor/proc/update_blackboard() var/static/list/display_emote = list( BB_EMOTE_SAY = list("Chirp chirp chirp!", "Kweh!", "Bwark!"), BB_EMOTE_SEE = list("shakes its feathers!", "stretches!", "flaps its wings!", "pecks at the ground!"), @@ -110,235 +474,110 @@ GLOBAL_LIST_EMPTY(raptor_population) ) ai_controller.set_blackboard_key(BB_BASIC_MOB_SPEAK_LINES, display_emote) - inherited_stats = new - inherit_properties() - var/list/my_food = string_list(list(/obj/item/stack/ore)) - AddElement(/datum/element/basic_eating, food_types = my_food) - AddElement(/datum/element/ai_retaliate) - AddElement(/datum/element/ai_flee_while_injured, stop_fleeing_at = 0.5, start_fleeing_below = 0.2) - if(ridable_component) - AddElement(/datum/element/ridable, ridable_component) + var/static/list/preferred_foods = typecacheof(list( + /obj/item/food/meat, + /obj/item/food/grown/ash_flora, + )) - typecacheof(list( // Don't seek out toxic foods + /obj/item/food/meat/slab/spider, + /obj/item/food/meat/slab/xeno, + )) - if(can_breed) - add_breeding_component() + ai_controller.set_blackboard_key(BB_BASIC_FOODS, preferred_foods) - AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW) - RegisterSignal(src, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_dir_change)) - adjust_offsets(dir) - add_happiness_component() - -/mob/living/basic/raptor/buckle_mob(mob/living/target, force = FALSE, check_loc = TRUE, buckle_mob_flags= NONE) - if(!iscarbon(target)) - return - return ..() - -/mob/living/basic/raptor/proc/add_happiness_component() - var/static/list/percentage_callbacks = list(0, 15, 25, 35, 50, 75, 90, 100) - AddComponent(\ - /datum/component/happiness,\ - on_petted_change = 100,\ - on_groom_change = 100,\ - on_eat_change = 400,\ - callback_percentages = percentage_callbacks,\ - happiness_callback = CALLBACK(src, PROC_REF(happiness_change)),\ - ) - -/mob/living/basic/raptor/proc/on_dir_change(datum/source, old_dir, new_dir) - SIGNAL_HANDLER - adjust_offsets(new_dir) - -/mob/living/basic/raptor/proc/adjust_offsets(direction) - if (!change_offsets) - return - - switch (direction) - if (NORTH) - add_offsets(RAPTOR_INNATE_SOURCE, w_add = -8, animate = FALSE) - if (SOUTH) - add_offsets(RAPTOR_INNATE_SOURCE, w_add = 0, animate = FALSE) - if (EAST, SOUTHEAST, NORTHEAST) - add_offsets(RAPTOR_INNATE_SOURCE, w_add = -20, animate = FALSE) - if (WEST, SOUTHWEST, NORTHWEST) - add_offsets(RAPTOR_INNATE_SOURCE, w_add = -5, animate = FALSE) - -/mob/living/basic/raptor/early_melee_attack(atom/target, list/modifiers, ignore_cooldown) - . = ..() - if(!.) - return FALSE - if(!istype(target, /obj/structure/ore_container/food_trough/raptor_trough)) - return TRUE - - var/obj/ore_food = locate(/obj/item/stack/ore) in target - - if(isnull(ore_food)) - balloon_alert(src, "no food!") - else - UnarmedAttack(ore_food, TRUE, modifiers) - return FALSE - -/mob/living/basic/raptor/melee_attack(mob/living/target, list/modifiers, ignore_cooldown) - if(!combat_mode && istype(target, /mob/living/basic/raptor/baby_raptor)) - target.attack_hand(src, list(LEFT_CLICK = TRUE)) - return - return ..() - -/mob/living/basic/raptor/death(gibbed) - . = ..() - GLOB.raptor_population -= REF(src) - -/mob/living/basic/raptor/proc/happiness_change(percent_value) - var/attack_boost = round(initial(melee_damage_lower) * percent_value * HAPPINESS_BOOST_DAMPENER, 1) - melee_damage_lower = initial(melee_damage_lower) + attack_boost - melee_damage_upper = melee_damage_lower + 5 - - -///pass down our inheritance to the egg -/mob/living/basic/raptor/proc/egg_inherit(obj/item/food/egg/raptor_egg/baby_egg, mob/living/basic/raptor/partner) - var/datum/raptor_inheritance/inherit = new - inherit.set_parents(inherited_stats, partner.inherited_stats) - baby_egg.inherited_stats = inherit - baby_egg.determine_growth_path(src, partner) - -/mob/living/basic/raptor/proc/inherit_properties() - if(isnull(inherited_stats)) - return - for(var/trait in GLOB.raptor_inherit_traits) // done this way to allow overriding of traits when assigned new inherit datum - var/should_inherit = (trait in inherited_stats.inherit_traits) + for(var/trait in GLOB.raptor_inherit_traits) + var/should_inherit = (trait in inherited_stats.personality_traits) ai_controller?.set_blackboard_key(trait, should_inherit) - melee_damage_lower += inherited_stats.attack_modifier - melee_damage_upper += melee_damage_lower + 5 - maxHealth += inherited_stats.health_modifier - heal_overall_damage(maxHealth) -/mob/living/basic/raptor/proc/add_breeding_component() - var/static/list/partner_types = typecacheof(list(/mob/living/basic/raptor)) - var/static/list/baby_types = list(/obj/item/food/egg/raptor_egg = 1) - AddComponent(\ - /datum/component/breed,\ - can_breed_with = typecacheof(list(/mob/living/basic/raptor)),\ - baby_paths = baby_types,\ - post_birth = CALLBACK(src, PROC_REF(egg_inherit)),\ - breed_timer = 3 MINUTES,\ - ) - - -/mob/living/basic/raptor/Destroy() - QDEL_NULL(inherited_stats) - return ..() +// Raptor types for mappers to use /mob/living/basic/raptor/red - name = "red raptor" icon_state = "raptor_red" - icon_living = "raptor_red" - icon_dead = "raptor_red_dead" - melee_damage_lower = 15 - melee_damage_upper = 20 - raptor_color = RAPTOR_RED - ridable_component = /datum/component/riding/creature/raptor/combat - dex_description = "A resilient breed of raptors, battle-tested and bred for the purpose of humbling its foes in combat, \ - This breed demonstrates higher combat capabilities than its peers and oozes ruthless aggression." - child_path = /mob/living/basic/raptor/baby_raptor/red + raptor_color = /datum/raptor_color/red /mob/living/basic/raptor/purple - name = "purple raptor" icon_state = "raptor_purple" - icon_living = "raptor_purple" - icon_dead = "raptor_purple_dead" - raptor_color = RAPTOR_PURPLE - dex_description = "A dependable mount, bred for the purpose of long distance pilgrimages. This breed is also able to store its rider's possessions." - child_path = /mob/living/basic/raptor/baby_raptor/purple - -/mob/living/basic/raptor/purple/Initialize(mapload) - . = ..() - create_storage( - max_specific_storage = WEIGHT_CLASS_NORMAL, - max_total_storage = 10, - storage_type = /datum/storage/raptor_storage, - ) + raptor_color = /datum/raptor_color/purple /mob/living/basic/raptor/green - name = "green raptor" icon_state = "raptor_green" - icon_living = "raptor_green" - icon_dead = "raptor_green_dead" - maxHealth = 400 - health = 400 - raptor_color = RAPTOR_GREEN - dex_description = "A tough breed of raptor, made to withstand the harshest of punishment and to laugh in the face of pain, \ - this breed is able to withstand more punishment than its peers." - child_path = /mob/living/basic/raptor/baby_raptor/green - -/mob/living/basic/raptor/green/Initialize(mapload) - . = ..() - AddComponent(/datum/component/proficient_miner) + raptor_color = /datum/raptor_color/green /mob/living/basic/raptor/white - name = "white raptor" icon_state = "raptor_white" - icon_living = "raptor_white" - icon_dead = "raptor_white_dead" - raptor_color = RAPTOR_WHITE - dex_description = "A loving sort, it cares for it peers and rushes to their aid with reckless abandon. It is able to heal any raptors' ailments." - child_path = /mob/living/basic/raptor/baby_raptor/white - -/mob/living/basic/raptor/white/Initialize(mapload) - . = ..() - AddComponent(\ - /datum/component/healing_touch,\ - heal_brute = melee_damage_upper,\ - heal_burn = melee_damage_upper,\ - heal_time = 0,\ - valid_targets_typecache = typecacheof(list(/mob/living/basic/raptor)),\ - ) + raptor_color = /datum/raptor_color/white /mob/living/basic/raptor/black - name = "black raptor" icon_state = "raptor_black" - icon_living = "raptor_black" - icon_dead = "raptor_black_dead" - maxHealth = 400 - health = 400 - speed = 1.5 - melee_damage_lower = 20 - melee_damage_upper = 25 - raptor_color = RAPTOR_BLACK - dex_description = "An ultra rare breed. Due to its sparse nature, not much is known about this sort. However it is said to possess many of its peers' abilities." - child_path = /mob/living/basic/raptor/baby_raptor/black + raptor_color = /datum/raptor_color/black /mob/living/basic/raptor/yellow - name = "yellow raptor" icon_state = "raptor_yellow" - icon_living = "raptor_yellow" - icon_dead = "raptor_yellow_dead" - speed = 1.5 - raptor_color = RAPTOR_YELLOW - dex_description = "This breed possesses greasy fast speed, DEMON speed, making light work of long pilgrimages. It's said that a thunderclap could be heard when this breed reaches its maximum speed." - child_path = /mob/living/basic/raptor/baby_raptor/yellow + raptor_color = /datum/raptor_color/yellow /mob/living/basic/raptor/blue - name = "blue raptor" icon_state = "raptor_blue" - icon_living = "raptor_blue" - icon_dead = "raptor_blue_dead" - raptor_color = RAPTOR_BLUE - dex_description = "Known to produce nutritous and equally delicious milk, which is also said to possess healing properties." - child_path = /mob/living/basic/raptor/baby_raptor/blue + raptor_color = /datum/raptor_color/blue -/mob/living/basic/raptor/blue/Initialize(mapload) - . = ..() - AddComponent(\ - /datum/component/udder,\ - udder_type = /obj/item/udder/raptor,\ - ) +/mob/living/basic/raptor/young + growth_stage = RAPTOR_YOUNG -/datum/storage/raptor_storage - animated = FALSE - insert_on_attack = FALSE +/mob/living/basic/raptor/young/red + icon_state = "young_red" + raptor_color = /datum/raptor_color/red -/datum/storage/raptor_storage/on_mousedropped_onto(datum/source, obj/item/dropping, mob/user) - ..() - return NONE +/mob/living/basic/raptor/young/purple + icon_state = "young_purple" + raptor_color = /datum/raptor_color/purple -#undef HAPPINESS_BOOST_DAMPENER -#undef RAPTOR_INNATE_SOURCE +/mob/living/basic/raptor/young/green + icon_state = "young_green" + raptor_color = /datum/raptor_color/green + +/mob/living/basic/raptor/young/white + icon_state = "young_white" + raptor_color = /datum/raptor_color/white + +/mob/living/basic/raptor/young/black + icon_state = "young_black" + raptor_color = /datum/raptor_color/black + +/mob/living/basic/raptor/young/yellow + icon_state = "young_yellow" + raptor_color = /datum/raptor_color/yellow + +/mob/living/basic/raptor/young/blue + icon_state = "young_blue" + raptor_color = /datum/raptor_color/blue + +/mob/living/basic/raptor/baby + icon = 'icons/mob/simple/lavaland/raptor_baby.dmi' + growth_stage = RAPTOR_BABY + +/mob/living/basic/raptor/baby/red + icon_state = "baby_red" + raptor_color = /datum/raptor_color/red + +/mob/living/basic/raptor/baby/purple + icon_state = "baby_purple" + raptor_color = /datum/raptor_color/purple + +/mob/living/basic/raptor/baby/green + icon_state = "baby_green" + raptor_color = /datum/raptor_color/green + +/mob/living/basic/raptor/baby/white + icon_state = "baby_white" + raptor_color = /datum/raptor_color/white + +/mob/living/basic/raptor/baby/black + icon_state = "baby_black" + raptor_color = /datum/raptor_color/black + +/mob/living/basic/raptor/baby/yellow + icon_state = "baby_yellow" + raptor_color = /datum/raptor_color/yellow + +/mob/living/basic/raptor/baby/blue + icon_state = "baby_blue" + raptor_color = /datum/raptor_color/blue diff --git a/code/modules/mob/living/basic/lavaland/raptor/baby_raptor.dm b/code/modules/mob/living/basic/lavaland/raptor/baby_raptor.dm deleted file mode 100644 index 06d9fed8470..00000000000 --- a/code/modules/mob/living/basic/lavaland/raptor/baby_raptor.dm +++ /dev/null @@ -1,102 +0,0 @@ -/mob/living/basic/raptor/baby_raptor - name = "baby raptor" - desc = "Will this grow into something useful?" - icon = 'icons/mob/simple/lavaland/raptor_baby.dmi' - speed = 5 - maxHealth = 25 - health = 25 - melee_damage_lower = 3 - melee_damage_upper = 5 - density = FALSE - can_breed = FALSE - move_resist = MOVE_RESIST_DEFAULT - ai_controller = /datum/ai_controller/basic_controller/baby_raptor - ridable_component = null - change_offsets = FALSE - dex_description = "A cute baby raptor, Having it near a parent or a birds-nest could encourage it to grow faster, \ - grooming it and feeding it could also ensure that it grows up quicker!" - ///what do we grow into - var/growth_path - ///probability we are to be rolled - var/roll_rate = 100 - -/mob/living/basic/raptor/baby_raptor/Initialize(mapload) - . = ..() - if(isnull(growth_path)) - return - AddComponent(\ - /datum/component/growth_and_differentiation,\ - growth_time = null,\ - growth_path = growth_path,\ - growth_probability = 80,\ - lower_growth_value = 0.5,\ - upper_growth_value = 0.8,\ - signals_to_kill_on = list(COMSIG_MOB_CLIENT_LOGIN),\ - optional_checks = CALLBACK(src, PROC_REF(check_grow)),\ - optional_grow_behavior = CALLBACK(src, PROC_REF(ready_to_grow)),\ - ) - -/mob/living/basic/raptor/baby_raptor/add_happiness_component() - AddComponent(/datum/component/happiness, on_petted_change = 100) - -/mob/living/basic/raptor/baby_raptor/proc/check_grow() - return (stat != DEAD) - -/mob/living/basic/raptor/baby_raptor/proc/ready_to_grow() - var/mob/living/basic/raptor/grown_mob = new growth_path(get_turf(src)) - QDEL_NULL(grown_mob.inherited_stats) - grown_mob.inherited_stats = inherited_stats - inherited_stats = null - grown_mob.inherit_properties() - ADD_TRAIT(grown_mob, TRAIT_MOB_HATCHED, INNATE_TRAIT) //pass on the hatched trait - qdel(src) - -/mob/living/basic/raptor/baby_raptor/black - name = "baby black raptor" - icon_state = "baby_black" - icon_living = "baby_black" - icon_dead = "baby_black_dead" - growth_path = /mob/living/basic/raptor/black - roll_rate = 10 - -/mob/living/basic/raptor/baby_raptor/red - name = "baby red raptor" - icon_state = "baby_red" - icon_living = "baby_red" - icon_dead = "baby_red_dead" - growth_path = /mob/living/basic/raptor/red - -/mob/living/basic/raptor/baby_raptor/purple - name = "baby purple raptor" - icon_state = "baby_purple" - icon_living = "baby_purple" - icon_dead = "baby_purple_dead" - growth_path = /mob/living/basic/raptor/purple - -/mob/living/basic/raptor/baby_raptor/white - name = "baby white raptor" - icon_state = "baby_white" - icon_living = "baby_white" - icon_dead = "baby_white_dead" - growth_path = /mob/living/basic/raptor/white - -/mob/living/basic/raptor/baby_raptor/yellow - name = "baby yellow raptor" - icon_state = "baby_yellow" - icon_living = "baby_yellow" - icon_dead = "baby_yellow_dead" - growth_path = /mob/living/basic/raptor/yellow - -/mob/living/basic/raptor/baby_raptor/green - name = "baby green raptor" - icon_state = "baby_green" - icon_living = "baby_green" - icon_dead = "baby_green_dead" - growth_path = /mob/living/basic/raptor/green - -/mob/living/basic/raptor/baby_raptor/blue - name = "baby blue raptor" - icon_state = "baby_blue" - icon_living = "baby_blue" - icon_dead = "baby_blue_dead" - growth_path = /mob/living/basic/raptor/blue diff --git a/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_behavior.dm b/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_behavior.dm index a412fceeb12..777a76de1a6 100644 --- a/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_behavior.dm +++ b/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_behavior.dm @@ -8,7 +8,10 @@ return (source != target && target.health < target.maxHealth) /datum/ai_behavior/find_hunt_target/raptor_baby/valid_dinner(mob/living/source, mob/living/target, radius) - return can_see(source, target, radius) && target.stat != DEAD + if (!can_see(source, target, radius) || target.stat == DEAD || !istype(target, /mob/living/basic/raptor)) + return FALSE + var/mob/living/basic/raptor/raptor = target + return raptor.growth_stage == RAPTOR_BABY /datum/ai_behavior/hunt_target/interact_with_target/reset_target_combat_mode_off/care_for_young @@ -21,3 +24,15 @@ /datum/ai_behavior/find_hunt_target/raptor_trough/valid_dinner(mob/living/source, atom/movable/trough, radius) return !!(locate(/obj/item/stack/ore) in trough.contents) + +/datum/ai_behavior/find_injured_rider/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, types_to_hunt, hunt_range) + var/mob/living/living_mob = controller.pawn + if (!length(living_mob.buckled_mobs) || !isliving(living_mob.buckled_mobs[1])) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + + var/mob/living/rider = living_mob.buckled_mobs[1] + if (rider.stat == CONSCIOUS || rider.stat == DEAD || rider.health >= rider.maxHealth) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + + controller.set_blackboard_key(hunting_target_key, rider) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_controller.dm b/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_controller.dm index 27cd4d005f8..2f1353bfc79 100644 --- a/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_controller.dm +++ b/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_controller.dm @@ -9,8 +9,8 @@ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_BABIES_PARTNER_TYPES = list(/mob/living/basic/raptor), - BB_BABIES_CHILD_TYPES = list(/mob/living/basic/raptor/baby_raptor), BB_MAX_CHILDREN = 5, + BB_RAPTOR_FLEE_THRESHOLD = 0.25, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -19,6 +19,7 @@ /datum/ai_planning_subtree/escape_captivity, /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/raptor, /datum/ai_planning_subtree/flee_target/from_flee_key, + /datum/ai_planning_subtree/find_and_hunt_target/heal_rider, /datum/ai_planning_subtree/find_and_hunt_target/heal_raptors, /datum/ai_planning_subtree/random_speech/blackboard, /datum/ai_planning_subtree/pet_planning, @@ -26,6 +27,42 @@ /datum/ai_planning_subtree/simple_find_target, /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/find_and_hunt_target/raptor_trough, + /datum/ai_planning_subtree/find_food, + /datum/ai_planning_subtree/find_and_hunt_target/care_for_young, + /datum/ai_planning_subtree/make_babies, + /datum/ai_planning_subtree/express_happiness, + /datum/ai_planning_subtree/find_and_hunt_target/play_with_owner/raptor, + ) + +/// Angry raptors with no faction check on retaliation +/datum/ai_controller/basic_controller/raptor/aggressive + blackboard = list( + BB_INTERACTIONS_WITH_OWNER = list( + "pecks", + "nuzzles", + "wags their tail against", + "playfully leans against" + ), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/exact_match, + BB_HUNT_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_BABIES_PARTNER_TYPES = list(/mob/living/basic/raptor), + BB_MAX_CHILDREN = 5, + BB_RAPTOR_FLEE_THRESHOLD = 0.1, + ) + + planning_subtrees = list( + /datum/ai_planning_subtree/escape_captivity, + /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/raptor, + /datum/ai_planning_subtree/flee_target/from_flee_key, + /datum/ai_planning_subtree/find_and_hunt_target/heal_raptors, + /datum/ai_planning_subtree/random_speech/blackboard, + /datum/ai_planning_subtree/pet_planning, + /datum/ai_planning_subtree/target_retaliate, + /datum/ai_planning_subtree/simple_find_target/hunt, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/find_and_hunt_target/raptor_trough, + /datum/ai_planning_subtree/find_food, /datum/ai_planning_subtree/find_and_hunt_target/care_for_young, /datum/ai_planning_subtree/make_babies, /datum/ai_planning_subtree/express_happiness, @@ -55,7 +92,6 @@ blackboard = list( BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_FIND_MOM_TYPES = list(/mob/living/basic/raptor), - BB_IGNORE_MOM_TYPES = list(/mob/living/basic/raptor/baby_raptor), ) ai_movement = /datum/ai_movement/basic_avoidance @@ -67,5 +103,5 @@ /datum/ai_planning_subtree/random_speech/blackboard, /datum/ai_planning_subtree/find_and_hunt_target/raptor_trough, /datum/ai_planning_subtree/express_happiness, - /datum/ai_planning_subtree/look_for_adult, + /datum/ai_planning_subtree/look_for_adult/raptor, ) diff --git a/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_subtrees.dm b/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_subtrees.dm index 06697d60b94..66f08924023 100644 --- a/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_subtrees.dm +++ b/code/modules/mob/living/basic/lavaland/raptor/raptor_ai_subtrees.dm @@ -11,19 +11,41 @@ return return ..() +/datum/ai_planning_subtree/find_and_hunt_target/heal_rider + target_key = BB_INJURED_RAPTOR + hunting_behavior = /datum/ai_behavior/hunt_target/interact_with_target/heal_raptor + finding_behavior = /datum/ai_behavior/find_injured_rider + hunt_targets = list(/mob/living/carbon/human) + +/datum/ai_planning_subtree/find_and_hunt_target/heal_rider/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(!controller.blackboard[BB_BASIC_MOB_HEALER]) + return + return ..() + /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/raptor target_key = BB_BASIC_MOB_FLEE_TARGET /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/raptor/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - if(!controller.blackboard[BB_RAPTOR_COWARD]) + if(controller.blackboard[BB_RAPTOR_COWARD]) + return ..() + + var/mob/living/basic/raptor/raptor = controller.pawn + if (raptor.health <= raptor.maxHealth * controller.blackboard[BB_RAPTOR_FLEE_THRESHOLD]) + return ..() + + if (!length(raptor.buckled_mobs)) return - return ..() + + var/mob/living/buckled_to = raptor.buckled_mobs[1] + // Flee if our owner is badly injured and out + if (buckled_to.stat != CONSCIOUS && buckled_to.stat != DEAD) + return ..() /datum/ai_planning_subtree/find_and_hunt_target/care_for_young target_key = BB_RAPTOR_BABY hunting_behavior = /datum/ai_behavior/hunt_target/interact_with_target/reset_target_combat_mode_off/care_for_young finding_behavior = /datum/ai_behavior/find_hunt_target/raptor_baby - hunt_targets = list(/mob/living/basic/raptor/baby_raptor) + hunt_targets = list(/mob/living/basic/raptor) hunt_chance = 75 hunt_range = 9 diff --git a/code/modules/mob/living/basic/lavaland/raptor/raptor_color.dm b/code/modules/mob/living/basic/lavaland/raptor/raptor_color.dm new file mode 100644 index 00000000000..486e54519bb --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/raptor/raptor_color.dm @@ -0,0 +1,439 @@ +GLOBAL_LIST_INIT(raptor_colors, init_raptor_colors()) + +/proc/init_raptor_colors() + var/list/colors = list() + for (var/datum/raptor_color/color_type as anything in subtypesof(/datum/raptor_color)) + colors[color_type] = new color_type() + return colors + +/datum/raptor_color + /// Color name used for raptor name and icon + var/color = "error" + /// RaptorDex description for the raptor + var/description = "Report this!" + /// Raptor's health + var/health = 220 + /// Raptor's speed + var/speed = 0.5 + // Minimal and maximal damage for the raptor + var/melee_damage_lower = 10 + var/melee_damage_upper = 15 + /// Does this raptor redirect projectile hits onto its rider? + var/redirect_shots = TRUE + /// Rideable component type to assign to the raptor + var/rideable_component = /datum/component/riding/creature/raptor + /// Guaranteed cross-breeding colors, other parent color -> child color + var/guaranteed_crossbreeds = list() + /// Type of AI controller the raptor uses + var/datum/ai_controller/ai_controller = /datum/ai_controller/basic_controller/raptor + /// Chance that a newborn baby raptor will be of this color + var/spawn_chance = 33 + +/// Shared proc, only called once on raptor init for color-specific traits and properties +/datum/raptor_color/proc/setup_raptor(mob/living/basic/raptor/raptor) + if (raptor.ai_controller) + CRASH("setup_raptor called on a raptor ([raptor]) with a present AI controller! This is most likely a result of a second call to setup_raptor.") + raptor.ai_controller = new ai_controller(raptor) + +/datum/raptor_color/proc/setup_adult(mob/living/basic/raptor/raptor) + var/datum/raptor_inheritance/stats = raptor.inherited_stats + var/real_health = health + stats.health_modifier + // If we grow up while damaged, keep the damage percentage the same + raptor.health *= real_health / raptor.maxHealth + raptor.maxHealth = real_health + // -0.33 ~ 0.33 gets rounded to 0 rather than +-0.5 + var/speed_mod = clamp(round(abs(stats.speed_modifier - 0.08), 0.5) * sign(stats.speed_modifier), -0.5, 0.5) + raptor.set_varspeed(speed - speed_mod) + raptor.melee_damage_lower = melee_damage_lower + stats.attack_modifier + raptor.melee_damage_upper = melee_damage_upper + stats.attack_modifier + if (rideable_component) + raptor.AddElement(/datum/element/ridable, rideable_component) + setup_appearance(raptor) + +/datum/raptor_color/proc/setup_young(mob/living/basic/raptor/raptor) + var/datum/raptor_inheritance/stats = raptor.inherited_stats + var/real_health = health + stats.health_modifier + raptor.health *= real_health / 2 / raptor.maxHealth + raptor.maxHealth = real_health / 2 + var/speed_mod = clamp(round(abs(stats.speed_modifier - 0.08), 0.5) * sign(stats.speed_modifier), -0.5, 0.5) + raptor.set_varspeed(speed - speed_mod) + raptor.melee_damage_lower = floor((melee_damage_lower + stats.attack_modifier) / 2) + raptor.melee_damage_upper = floor((melee_damage_upper + stats.attack_modifier) / 2) + setup_appearance(raptor) + +/datum/raptor_color/proc/setup_baby(mob/living/basic/raptor/raptor) + var/datum/raptor_inheritance/stats = raptor.inherited_stats + var/real_health = health + stats.health_modifier + raptor.health *= real_health / 8 / raptor.maxHealth + raptor.maxHealth = real_health / 8 + var/speed_mod = clamp(round(abs(stats.speed_modifier - 0.08), 0.5) * sign(stats.speed_modifier), -0.5, 0.5) + raptor.set_varspeed(speed + 4.5 - speed_mod) + raptor.melee_damage_lower = floor((melee_damage_lower + stats.attack_modifier) / 3) + raptor.melee_damage_upper = floor((melee_damage_upper + stats.attack_modifier) / 3) + setup_appearance(raptor) + +/datum/raptor_color/proc/setup_appearance(mob/living/basic/raptor/raptor) + raptor.name = "[color] [raptor.name]" + raptor.icon_state = "[raptor.base_icon_state]_[color]" + raptor.held_state = "[raptor.base_icon_state]_[color]" + raptor.icon_living = "[raptor.base_icon_state]_[color]" + raptor.icon_dead = "[raptor.base_icon_state]_[color]_dead" + raptor.update_appearance() + +/datum/raptor_color/red + color = "red" + description = "A resilient breed of raptors, battle-tested and bred for the purpose of humbling its foes in combat, \ + This breed demonstrates higher combat capabilities than its peers and oozes ruthless aggression." + melee_damage_lower = 15 + melee_damage_upper = 20 + health = 300 + rideable_component = /datum/component/riding/creature/raptor/combat + redirect_shots = FALSE + guaranteed_crossbreeds = list( + /datum/raptor_color/green = /datum/raptor_color/yellow, + /datum/raptor_color/blue = /datum/raptor_color/purple, + ) + // Doesn't care for your excuses for friendly fire + ai_controller = /datum/ai_controller/basic_controller/raptor/aggressive + +/datum/raptor_color/purple + color = "purple" + description = "A small, nimble breed, these raptors have been bred as travel companions rather than mounts, capable of storing the owner's possessions and helping them escape from danger unscathed." + health = 140 // smol + rideable_component = /datum/component/riding/creature/raptor/small + guaranteed_crossbreeds = list( + /datum/raptor_color/green = /datum/raptor_color/white, + /datum/raptor_color/yellow = /datum/raptor_color/blue, + ) + +/datum/raptor_color/purple/setup_raptor(mob/living/basic/raptor/raptor) + . = ..() + RegisterSignal(raptor, COMSIG_MOVABLE_PREBUCKLE, PROC_REF(on_pre_buckle)) + raptor.inhand_holder_type = /obj/item/mob_holder/purple_raptor + +/datum/raptor_color/purple/proc/on_pre_buckle(mob/living/basic/raptor/source, mob/living/potential_rider, force = FALSE, ride_check_flags = NONE) + SIGNAL_HANDLER + + if (!ishuman(potential_rider)) + return COMPONENT_BLOCK_BUCKLE + + var/mob/living/carbon/human/rider = potential_rider + if (rider.mob_height > HUMAN_HEIGHT_SHORTEST) + to_chat(rider, span_warning("Your tall stature will crush [source] were you attempt to ride [source.p_them()]!")) + return COMPONENT_BLOCK_BUCKLE + +// Purple raptors never "fully" grow up, and remain usable as backpacks +/datum/raptor_color/purple/setup_adult(mob/living/basic/raptor/raptor) + raptor.base_pixel_w = initial(raptor.base_pixel_w) + raptor.can_be_held = TRUE + raptor.density = FALSE + raptor.move_resist = MOVE_RESIST_DEFAULT + raptor.change_offsets = FALSE + raptor.remove_offsets(RAPTOR_INNATE_SOURCE, FALSE) + raptor.held_w_class = WEIGHT_CLASS_BULKY + . = ..() + // Non-shorties cannot ride these, so we gotta keep em tameable through food + raptor.AddComponent(/datum/component/tameable, food_types = raptor.food_types, tame_chance = 25, bonus_tame_chance = 15, unique = TRUE) + if (raptor.atom_storage) + return + // A bit bigger (23 vs 21) than a backpack at max size, a bit less by default + var/storage_volume = floor(19 * (1 + raptor.inherited_stats.ability_modifier)) + raptor.create_storage( + max_total_storage = storage_volume, + max_slots = storage_volume, + storage_type = /datum/storage/raptor_storage, + ) + +/datum/raptor_color/purple/setup_young(mob/living/basic/raptor/raptor) + . = ..() + if (raptor.atom_storage) + return + var/storage_volume = floor(19 * (1 + raptor.inherited_stats.ability_modifier)) + raptor.create_storage( + max_total_storage = storage_volume, + max_slots = storage_volume, + storage_type = /datum/storage/raptor_storage, + ) + +/obj/item/mob_holder/purple_raptor + /// Wings action granted to whoever is wearing us on their back + var/datum/action/innate/raptor_wings/flight_action = null + + /// Are our wings open? + var/wings_open = FALSE + /// Wings underlay added to the owner, because human rendering code is a mess + var/mutable_appearance/wings_underlay = null + /// Our drift force + var/drift_force = 2 NEWTONS + /// Our stabilizing force + var/stabilizer_force = 4.5 NEWTONS + +/obj/item/mob_holder/purple_raptor/Initialize(mapload, mob/living/held_mob, worn_state, head_icon, lh_icon, rh_icon, worn_slot_flags) + . = ..() + + var/mob/living/basic/raptor/raptor = held_mob + if (raptor.growth_stage == RAPTOR_BABY) + return + + // Create a mirror storage for our raptor when picked up to handle interactions + var/datum/storage/raptor_storage = create_storage( + max_total_storage = held_mob.atom_storage.max_total_storage, + max_slots = held_mob.atom_storage.max_slots, + storage_type = /datum/storage/raptor_storage, + ) + raptor_storage.set_real_location(held_mob) + raptor_storage.insert_on_attack = TRUE + + if (raptor.growth_stage != RAPTOR_ADULT) + return + + flight_action = new(src) + + AddComponent( \ + /datum/component/jetpack, \ + TRUE, \ + drift_force, \ + stabilizer_force, \ + COMSIG_RAPTOR_WINGS_OPENED, \ + COMSIG_RAPTOR_WINGS_CLOSED, \ + null, \ + CALLBACK(src, PROC_REF(can_fly)), \ + CALLBACK(src, PROC_REF(can_fly)), \ + ) + +/obj/item/mob_holder/purple_raptor/Destroy() + if (ishuman(loc) && wings_open) + toggle_wings(loc) + QDEL_NULL(flight_action) + return ..() + +/obj/item/mob_holder/purple_raptor/equipped(mob/user, slot, initial) + . = ..() + if ((slot & ITEM_SLOT_BACK) && ishuman(user) && flight_action) + flight_action.Grant(held_mob) + flight_action.GiveAction(user) + +/obj/item/mob_holder/purple_raptor/dropped(mob/user, silent) + . = ..() + if (wings_open) + toggle_wings(user) + // Removed in Destroy() + if (flight_action) + flight_action.Remove(held_mob) + flight_action.HideFrom(user) + +/obj/item/mob_holder/purple_raptor/proc/on_weight_updated(mob/living/carbon/human/source) + SIGNAL_HANDLER + + if (source.mob_height <= HUMAN_HEIGHT_SHORTEST && !HAS_TRAIT(source, TRAIT_FAT)) + source.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/raptor/slow) + source.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/raptor) + else + source.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/raptor) + source.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/raptor/slow) + +/obj/item/mob_holder/purple_raptor/proc/can_fly() + var/mob/living/carbon/human/user = loc + if (!istype(user) || user.stat || user.body_position == LYING_DOWN || isnull(user.client)) + return FALSE + + if (user.get_organ_slot(ORGAN_SLOT_EXTERNAL_WINGS)) + return FALSE + + var/turf/location = get_turf(user) + if (!istype(location)) + return FALSE + + var/datum/gas_mixture/environment = location.return_air() + if (environment?.return_pressure() >= HAZARD_LOW_PRESSURE + 10) + return TRUE + + to_chat(user, span_warning("The atmosphere is too thin for you to fly!")) + return FALSE + +/obj/item/mob_holder/purple_raptor/proc/toggle_wings(mob/living/carbon/human/user) + // In case something goes wrong + if (!istype(user)) + wings_open = FALSE + worn_icon_state = icon_state + SEND_SIGNAL(src, COMSIG_RAPTOR_WINGS_CLOSED, user) + STOP_PROCESSING(SSprocessing, src) + return + + if (!wings_open && !can_fly()) + return + + wings_open = !wings_open + worn_icon_state = "[icon_state][wings_open ? "_wings_out" : ""]" + user.update_worn_back() + + // Raptors won't have the best of times keeping up tall humans or fatties up in the air + var/struggling = HAS_TRAIT(user, TRAIT_FAT) || user.mob_height > HUMAN_HEIGHT_SHORTEST + if (wings_open) + wings_underlay = user.apply_height_offsets(mutable_appearance(worn_icon, "raptor_purple_wings", -BODY_BEHIND_LAYER, user), UPPER_BODY) + user.add_overlay(wings_underlay) + user.physiology.stun_mod *= 2 + user.add_traits(list(TRAIT_MOVE_FLOATING, TRAIT_IGNORING_GRAVITY, TRAIT_NOGRAV_ALWAYS_DRIFT), REF(src)) + if (struggling) + user.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/raptor/slow) + else + user.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/raptor) + user.AddElement(/datum/element/forced_gravity, 0) + passtable_on(user, REF(src)) + to_chat(user, span_notice("You begin gently hovering above ground as [held_mob] on your back starts furiously flapping [held_mob.p_their()] wings[struggling ? ", struggling to keep you up in the air" : ""]!")) + user.set_resting(FALSE, TRUE) + user.refresh_gravity() + START_PROCESSING(SSprocessing, src) + RegisterSignals(user, list(COMSIG_HUMAN_HEIGHT_UPDATED, SIGNAL_ADDTRAIT(TRAIT_FAT), SIGNAL_REMOVETRAIT(TRAIT_FAT)), PROC_REF(on_weight_updated)) + SEND_SIGNAL(src, COMSIG_RAPTOR_WINGS_OPENED, user) + return + + user.cut_overlay(wings_underlay) + QDEL_NULL(wings_underlay) + user.physiology.stun_mod *= 0.5 + user.remove_traits(list(TRAIT_MOVE_FLOATING, TRAIT_IGNORING_GRAVITY, TRAIT_NOGRAV_ALWAYS_DRIFT), REF(src)) + user.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/raptor/slow) + user.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/raptor) + user.RemoveElement(/datum/element/forced_gravity, 0) + passtable_off(user, REF(src)) + to_chat(user, span_notice("You settle gently back onto the ground[struggling ? ", [held_mob] on your back breathing out a sigh of releif" : ""]...")) + user.refresh_gravity() + STOP_PROCESSING(SSprocessing, src) + UnregisterSignal(user, list(COMSIG_HUMAN_HEIGHT_UPDATED, SIGNAL_ADDTRAIT(TRAIT_FAT), SIGNAL_REMOVETRAIT(TRAIT_FAT))) + SEND_SIGNAL(src, COMSIG_RAPTOR_WINGS_CLOSED, user) + +/obj/item/mob_holder/purple_raptor/process(seconds_per_tick) + if (!can_fly()) + toggle_wings(loc) + return PROCESS_KILL + +/datum/storage/raptor_storage + animated = FALSE + insert_on_attack = FALSE // should flip when worn on the back + +/datum/storage/raptor_storage/on_mousedropped_onto(datum/source, obj/item/dropping, mob/user) + return NONE + +/datum/action/innate/raptor_wings + name = "Toggle Flight" + check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_IMMOBILE | AB_CHECK_INCAPACITATED + button_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon_state = "raptor_wings" + +/datum/action/innate/raptor_wings/Activate() + var/obj/item/mob_holder/purple_raptor/holder = target + var/mob/living/carbon/human/user = holder.loc + if (istype(user) && user.get_item_by_slot(ITEM_SLOT_BACK) == holder) + holder.toggle_wings(user) + +/datum/raptor_color/green + color = "green" + description = "A tough breed of raptor, made to withstand the harshest of punishment and to laugh in the face of pain, \ + this breed is able to withstand more punishment than its peers." + health = 400 + // redirect_shots = FALSE // Need to figure out if I want this or not here + guaranteed_crossbreeds = list( + /datum/raptor_color/purple = /datum/raptor_color/white, + /datum/raptor_color/red = /datum/raptor_color/yellow, + ) + +/datum/raptor_color/green/setup_adult(mob/living/basic/raptor/raptor) + . = ..() + var/ability_scale = 1 - INVERSE_LERP(RAPTOR_INHERIT_MIN_MODIFIER, RAPTOR_INHERIT_MAX_MODIFIER, raptor.inherited_stats.ability_modifier) + var/mining_mod = round(ability_scale * 0.1, 0.025) + if (ability_scale >= 0.75) + mining_mod = 0 + raptor.AddComponent(/datum/component/proficient_miner, mining_mod, TRUE) + +/datum/raptor_color/white + color = "white" + description = "A loving sort, it cares for it peers and rushes to their aid with reckless abandon. It is able to heal any raptors' ailments, and rescue its owner in case of an emergency." + rideable_component = /datum/component/riding/creature/raptor/healer + guaranteed_crossbreeds = list( + /datum/raptor_color/blue = /datum/raptor_color/green, + /datum/raptor_color/yellow = /datum/raptor_color/red, + ) + +/datum/raptor_color/white/setup_young(mob/living/basic/raptor/raptor) + . = ..() + raptor.AddComponent( \ + /datum/component/healing_touch, \ + heal_brute = melee_damage_upper * 0.75 * (1 + raptor.inherited_stats.ability_modifier), \ + heal_burn = melee_damage_upper * 0.75 * (1 + raptor.inherited_stats.ability_modifier), \ + heal_time = 0, \ + valid_targets_typecache = typecacheof(list(/mob/living/basic/raptor)), \ + ) + +/datum/raptor_color/white/setup_adult(mob/living/basic/raptor/raptor) + . = ..() + qdel(raptor.GetComponent(/datum/component/healing_touch)) + raptor.AddComponent( \ + /datum/component/healing_touch, \ + heal_brute = melee_damage_upper * (1 + raptor.inherited_stats.ability_modifier), \ + heal_burn = melee_damage_upper * (1 + raptor.inherited_stats.ability_modifier), \ + heal_time = 0, \ + valid_targets_typecache = typecacheof(list(/mob/living/basic/raptor, /mob/living/carbon/human)), \ + extra_checks = CALLBACK(src, PROC_REF(heal_checks)), \ + healing_multiplier = CALLBACK(src, PROC_REF(heal_multiplier)), \ + ) + +/datum/raptor_color/white/proc/heal_checks(mob/living/healer, mob/living/target) + if (istype(target, /mob/living/basic/raptor)) + return TRUE + // Only heal raptors, or critted rider + if (target.stat == CONSCIOUS || target.stat == DEAD) + return FALSE + return target.buckled == healer + +/datum/raptor_color/white/proc/heal_multiplier(mob/living/healer, mob/living/target) + if (istype(target, /mob/living/basic/raptor)) + return 1 + // The healing is slow so this is fine + return 0.67 + +/datum/raptor_color/yellow + color = "yellow" + description = "This breed possesses greasy fast speed, DEMON speed, making light work of long pilgrimages. \ + It's said that a thunderclap could be heard when this breed reaches its maximum speed." + speed = 0 + guaranteed_crossbreeds = list( + /datum/raptor_color/purple = /datum/raptor_color/blue, + /datum/raptor_color/white = /datum/raptor_color/red, + ) + +/datum/raptor_color/blue + color = "blue" + description = "Covered in tough, lava-resistant feathers with thick insulated fur underneath, this breed is capable of marching through lava and fire alike." + guaranteed_crossbreeds = list( + /datum/raptor_color/red = /datum/raptor_color/purple, + /datum/raptor_color/white = /datum/raptor_color/green, + ) + +/datum/raptor_color/blue/setup_raptor(mob/living/basic/raptor/raptor) + . = ..() + raptor.add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_NOFIRE_SPREAD), INNATE_TRAIT) + +/datum/raptor_color/black + color = "black" + description = "An ultra rare breed. Due to its sparse nature, not much is known about this sort. However it is said to possess many of its peers' abilities." + health = 400 + speed = 0 + melee_damage_lower = 20 + melee_damage_upper = 25 + redirect_shots = FALSE + rideable_component = /datum/component/riding/creature/raptor/combat + ai_controller = /datum/ai_controller/basic_controller/raptor/aggressive + spawn_chance = 1 // 1 in 150 chance without modifiers + +/datum/raptor_color/black/setup_raptor(mob/living/basic/raptor/raptor) + . = ..() + raptor.add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_NOFIRE_SPREAD), INNATE_TRAIT) + +/datum/raptor_color/black/setup_adult(mob/living/basic/raptor/raptor) + . = ..() + // Slightly worse than greens at this + var/ability_scale = 1 - INVERSE_LERP(RAPTOR_INHERIT_MIN_MODIFIER, RAPTOR_INHERIT_MAX_MODIFIER, raptor.inherited_stats.ability_modifier) + var/mining_mod = round(ability_scale * 0.2, 0.025) + if (ability_scale >= 0.8) + mining_mod = 0 + raptor.AddComponent(/datum/component/proficient_miner, mining_mod, TRUE) diff --git a/code/modules/mob/living/basic/lavaland/raptor/raptor_dex.dm b/code/modules/mob/living/basic/lavaland/raptor/raptor_dex.dm index e7224e29d87..90595dd942a 100644 --- a/code/modules/mob/living/basic/lavaland/raptor/raptor_dex.dm +++ b/code/modules/mob/living/basic/lavaland/raptor/raptor_dex.dm @@ -1,62 +1,64 @@ /obj/item/raptor_dex - name = "raptor Dex" + name = "RaptorDex" desc = "A device used to analyze lavaland raptors!" icon = 'icons/obj/devices/scanner.dmi' icon_state = "raptor_dex" item_flags = NOBLUDGEON - ///current raptor we are analyzing - var/datum/weakref/raptor + /// Raptor scan data we have stored + var/list/scan_data = list("raptor_scan" = FALSE) /obj/item/raptor_dex/ui_interact(mob/user, datum/tgui/ui) - if(isnull(raptor?.resolve())) - balloon_alert(user, "no specimen data!") - return TRUE - ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "RaptorDex") ui.open() -/obj/item/raptor_dex/ui_static_data(mob/user) - var/list/data = list() - var/mob/living/basic/raptor/my_raptor = raptor.resolve() - - data["raptor_image"] = icon2base64(icon(icon = my_raptor.icon, icon_state = my_raptor.icon_state, frame = 1)) - data["raptor_attack"] = my_raptor.melee_damage_lower - data["raptor_health"] = my_raptor.maxHealth - data["raptor_speed"] = my_raptor.speed - data["raptor_color"] = my_raptor.name - data["raptor_gender"] = my_raptor.gender - data["raptor_description"] = my_raptor.dex_description - - var/happiness_percentage = my_raptor.ai_controller?.blackboard[BB_BASIC_HAPPINESS] - var/obj/effect/overlay/happiness_overlay/display = new - display.set_hearts(happiness_percentage) - display.pixel_y = ICON_SIZE_Y * 0.5 - data["raptor_happiness"] = icon2base64(getFlatIcon(display, no_anim = TRUE)) - qdel(display) - - var/datum/raptor_inheritance/inherit = my_raptor.inherited_stats - if(isnull(inherit)) - return data - - data["inherited_attack"] = inherit.attack_modifier - data["inherited_attack_max"] = RAPTOR_INHERIT_MAX_ATTACK - data["inherited_health"] = inherit.health_modifier - data["inherited_health_max"] = RAPTOR_INHERIT_MAX_HEALTH - - data["inherited_traits"] = list() - for(var/index in inherit.inherit_traits) - data["inherited_traits"] += GLOB.raptor_inherit_traits[index] - return data - +/obj/item/raptor_dex/ui_data(mob/user) + return scan_data /obj/item/raptor_dex/interact_with_atom(atom/attacked_atom, mob/living/user) if(!istype(attacked_atom, /mob/living/basic/raptor)) return NONE - raptor = WEAKREF(attacked_atom) + var/mob/living/basic/raptor/my_raptor = attacked_atom + var/datum/movespeed_modifier/intent_mod = my_raptor.get_move_intent_slowdown() + + scan_data = list() + scan_data["raptor_scan"] = TRUE + scan_data["raptor_image"] = icon2base64(icon(icon = my_raptor.icon, icon_state = my_raptor.icon_state, dir = SOUTH, frame = 1)) + scan_data["raptor_attack"] = my_raptor.melee_damage_lower + scan_data["raptor_health"] = my_raptor.health + scan_data["raptor_max_health"] = my_raptor.maxHealth + scan_data["raptor_speed"] = my_raptor.speed + intent_mod?.multiplicative_slowdown + scan_data["raptor_color"] = my_raptor.name + scan_data["raptor_gender"] = my_raptor.gender + scan_data["raptor_description"] = my_raptor.raptor_color.description + + var/happiness_percentage = my_raptor.ai_controller?.blackboard[BB_BASIC_HAPPINESS] + var/obj/effect/overlay/happiness_overlay/display = new() + display.set_hearts(happiness_percentage) + display.pixel_y = ICON_SIZE_Y * 0.5 + scan_data["raptor_happiness"] = icon2base64(getFlatIcon(display, no_anim = TRUE)) + qdel(display) + + var/datum/raptor_inheritance/inherit = my_raptor.inherited_stats + if(!isnull(inherit)) + scan_data["inherited_attack"] = inherit.attack_modifier + scan_data["inherited_attack_max"] = RAPTOR_INHERIT_MAX_ATTACK + scan_data["inherited_health"] = inherit.health_modifier + scan_data["inherited_health_max"] = RAPTOR_INHERIT_MAX_HEALTH + scan_data["inherited_speed"] = inherit.speed_modifier + scan_data["inherited_speed_max"] = RAPTOR_INHERIT_MAX_SPEED + scan_data["inherited_ability"] = inherit.ability_modifier + scan_data["inherited_ability_max"] = RAPTOR_INHERIT_MAX_MODIFIER + scan_data["inherited_growth"] = inherit.growth_modifier + scan_data["inherited_growth_max"] = RAPTOR_INHERIT_MAX_MODIFIER + + scan_data["inherited_traits"] = list() + for(var/index in inherit.personality_traits) + scan_data["inherited_traits"] += GLOB.raptor_inherit_traits[index] + playsound(src, 'sound/mobs/non-humanoids/orbie/orbie_send_out.ogg', 20) - balloon_alert(user, "scanned") + balloon_alert(my_raptor, "scanned") ui_interact(user) return ITEM_INTERACT_SUCCESS diff --git a/code/modules/mob/living/basic/lavaland/raptor/raptor_egg.dm b/code/modules/mob/living/basic/lavaland/raptor/raptor_egg.dm index 29e6a7b9c28..698dafac6c2 100644 --- a/code/modules/mob/living/basic/lavaland/raptor/raptor_egg.dm +++ b/code/modules/mob/living/basic/lavaland/raptor/raptor_egg.dm @@ -1,58 +1,52 @@ /obj/item/food/egg/raptor_egg + name = "raptor egg" + desc = "An uneven egg with a rough, thick shell." icon = 'icons/mob/simple/lavaland/raptor_baby.dmi' icon_state = "raptor_egg" - ///inheritance datum to pass on to the child - var/datum/raptor_inheritance/inherited_stats + resistance_flags = LAVA_PROOF|FIRE_PROOF + /// Color typepath of the child we spawn + var/datum/raptor_color/child_color = /datum/raptor_color + /// Inheritance data to pass onto the child + var/datum/raptor_inheritance/inherited_stats = null + /// Current growth progress + var/growth_progress = 0 + /// Minimum growth progress per second + var/min_growth_rate = 0.5 + /// Maximum growth progress per second + var/max_growth_rate = 1 /obj/item/food/egg/raptor_egg/Initialize(mapload) . = ..() - if(SSmapping.is_planetary()) - icon = 'icons/mob/simple/lavaland/raptor_icebox.dmi' - -/obj/item/food/egg/raptor_egg/proc/determine_growth_path(mob/living/basic/raptor/dad, mob/living/basic/raptor/mom) - if(dad.type == mom.type) - add_growth_component(dad.child_path) - return - var/dad_color = dad.raptor_color - var/mom_color = mom.raptor_color - var/list/my_colors = list(dad_color, mom_color) - sortTim(my_colors, GLOBAL_PROC_REF(cmp_text_asc)) - for(var/path in GLOB.raptor_growth_paths) //guaranteed spawns - var/list/required_colors = GLOB.raptor_growth_paths[path] - if(!compare_list(my_colors, required_colors)) - continue - add_growth_component(path) - return - var/list/valid_subtypesof = list() - var/static/list/all_subtypes = subtypesof(/mob/living/basic/raptor/baby_raptor) - for(var/path in all_subtypes) - var/mob/living/basic/raptor/baby_raptor/raptor_path = path - if(!prob(initial(raptor_path.roll_rate))) - continue - valid_subtypesof += raptor_path - add_growth_component(pick(valid_subtypesof)) - -/obj/item/food/egg/raptor_egg/proc/add_growth_component(growth_path) - if(length(GLOB.raptor_population) >= MAX_RAPTOR_POP) - return - AddComponent(\ - /datum/component/fertile_egg,\ - embryo_type = growth_path,\ - minimum_growth_rate = 0.5,\ - maximum_growth_rate = 1,\ - total_growth_required = 100,\ - current_growth = 0,\ - location_allowlist = typecacheof(list(/turf)),\ - post_hatch = CALLBACK(src, PROC_REF(post_hatch)),\ - ) - -/obj/item/food/egg/raptor_egg/proc/post_hatch(mob/living/basic/raptor/baby) - if(!istype(baby)) - return - QDEL_NULL(baby.inherited_stats) - baby.inherited_stats = inherited_stats - inherited_stats = null + START_PROCESSING(SSobj, src) /obj/item/food/egg/raptor_egg/Destroy() + STOP_PROCESSING(SSobj, src) QDEL_NULL(inherited_stats) return ..() + +/obj/item/food/egg/raptor_egg/examine(mob/user) + . = ..() + if (growth_progress >= RAPTOR_EGG_GROWTH_PROGRESS) + . += span_boldnotice("Its noticeably shaking, ready to hatch!") + +/obj/item/food/egg/raptor_egg/process(seconds_per_tick) + if (!isturf(loc) || length(GLOB.raptor_population) >= MAX_RAPTOR_POP) + return + + var/growth_value = rand(min_growth_rate, max_growth_rate) * seconds_per_tick * (1 + inherited_stats.growth_modifier) + // Slower growth off hot lavaland + if (!SSmapping.level_trait(z, ZTRAIT_ASHSTORM)) + growth_value *= 0.75 + // Faster growth in hot hot lava + if (islava(loc)) + growth_value *= 1.5 + + growth_progress += growth_value + // Don't hatch on lava though, or the chick will die instantly + if (growth_progress < RAPTOR_EGG_GROWTH_PROGRESS || islava(loc)) + return + + visible_message(span_notice("[src] hatches with a quiet cracking sound.")) + new /mob/living/basic/raptor(loc, child_color, inherited_stats) + inherited_stats = null + qdel(src) diff --git a/code/modules/mob/living/basic/lavaland/raptor/raptor_inheritance.dm b/code/modules/mob/living/basic/lavaland/raptor/raptor_inheritance.dm index 4f72e37a4cf..8c3e0ec8b3e 100644 --- a/code/modules/mob/living/basic/lavaland/raptor/raptor_inheritance.dm +++ b/code/modules/mob/living/basic/lavaland/raptor/raptor_inheritance.dm @@ -1,31 +1,97 @@ -#define RANDOM_INHERIT_AMOUNT 2 /datum/raptor_inheritance - ///list of traits we inherit - var/list/inherit_traits = list() - ///attack modifier - var/attack_modifier - ///health_modifier - var/health_modifier + /// Inherited parent personality traits + var/list/personality_traits = list() + /// Flat damage modifier + var/attack_modifier = 0 + /// Flat health modifier + var/health_modifier = 0 + /// Speed modifier, not randomized by default + var/speed_modifier = 0 + /// Primary ability stat modifier, not randomized by default + /// Multiplier equates to 1 + this + var/ability_modifier = 0 + /// Growth rate modifier, not randomized by default + /// Multiplier equates to 1 + this + var/growth_modifier = 0 + /// Foods eaten that can affect our child's stats -> stats they modify + var/list/foods_eaten = list() + /// List of all colors in our family tree + var/list/parent_colors = list() -/datum/raptor_inheritance/New(datum/raptor_inheritance/father, datum/raptor_inheritance/mother) +// Owner being set will randomize the stats as it means we're spawned not via an egg +// otherwise wait for set_parents call to inherit genetics +/datum/raptor_inheritance/New(mob/living/basic/raptor/owner) . = ..() - randomize_stats() - -/datum/raptor_inheritance/proc/randomize_stats() - attack_modifier = rand(0, RAPTOR_INHERIT_MAX_ATTACK) - health_modifier = rand(0, RAPTOR_INHERIT_MAX_HEALTH) - var/list/traits_to_pick = GLOB.raptor_inherit_traits.Copy() - for(var/i in 1 to RANDOM_INHERIT_AMOUNT) - inherit_traits += pick_n_take(traits_to_pick) - -/datum/raptor_inheritance/proc/set_parents(datum/raptor_inheritance/father, datum/raptor_inheritance/mother) - if(isnull(father) || isnull(mother)) + if (!owner) return - if(length(father.inherit_traits)) - inherit_traits += pick(father.inherit_traits) - if(length(mother.inherit_traits)) - inherit_traits += pick(mother.inherit_traits) - attack_modifier = rand(min(father.attack_modifier, mother.attack_modifier), max(father.attack_modifier, mother.attack_modifier)) - health_modifier = rand(min(father.health_modifier, mother.health_modifier), max(father.health_modifier, mother.health_modifier)) -#undef RANDOM_INHERIT_AMOUNT + attack_modifier = rand(RAPTOR_INHERIT_MIN_ATTACK * 0.5, RAPTOR_INHERIT_MAX_ATTACK * 0.5) + health_modifier = rand(RAPTOR_INHERIT_MIN_HEALTH * 0.5, RAPTOR_INHERIT_MAX_HEALTH * 0.5) + var/list/traits_to_pick = GLOB.raptor_inherit_traits.Copy() + for(var/i in 1 to rand(1, RAPTOR_TRAIT_INHERIT_AMOUNT)) + personality_traits += pick_n_take(traits_to_pick) + +/datum/raptor_inheritance/proc/set_parents(mob/living/basic/raptor/mother, mob/living/basic/raptor/father) + var/datum/raptor_inheritance/mom_stats = mother.inherited_stats + var/datum/raptor_inheritance/dad_stats = father.inherited_stats + + parent_colors = mom_stats.parent_colors | dad_stats.parent_colors | mother.raptor_color.type | father.raptor_color.type + + var/list/traits_to_pick = list() + // + so shared traits have double the weight + for (var/raptor_trait in mom_stats.personality_traits + dad_stats.personality_traits) + if (!traits_to_pick[raptor_trait]) + traits_to_pick[raptor_trait] = 0 + traits_to_pick[raptor_trait] += 1 + + var/attack_mod = 0 + var/health_mod = 0 + var/speed_mod = 0 + var/ability_mod = 0 + var/growth_mod = 0 + var/amount_eaten = 0 + + for (var/food_type in foods_eaten) + var/list/stat_mods = foods_eaten[food_type] + amount_eaten += stat_mods["amount"] + + for (var/food_type in foods_eaten) + var/list/stat_mods = foods_eaten[food_type] + // First multiply stats themselves, then multiply to get a proportion of this food from amount_eaten + var/amount = stat_mods["amount"] ** 2 + // Eating other foods reduces the effects of a specific one + attack_mod += stat_mods["attack"] / amount_eaten * amount + health_mod += stat_mods["health"] / amount_eaten * amount + speed_mod += stat_mods["speed"] / amount_eaten * amount + ability_mod += stat_mods["ability"] / amount_eaten * amount + growth_mod += stat_mods["growth"] / amount_eaten * amount + var/list/trait_list = stat_mods["traits"] + for (var/raptor_trait in trait_list) + if (!traits_to_pick[raptor_trait]) + traits_to_pick[raptor_trait] = 0 + traits_to_pick[raptor_trait] += trait_list[raptor_trait] * stat_mods["amount"] + + // If we don't clamp these, RNG and drift can get wildly out of control and result in polar values + // and this way we at most get twice the minimum/maximum value, so at least half the rand spread is within the clamp values + attack_mod = clamp(attack_mod, RAPTOR_INHERIT_MIN_ATTACK, RAPTOR_INHERIT_MAX_ATTACK) + health_mod = clamp(health_mod, RAPTOR_INHERIT_MIN_HEALTH, RAPTOR_INHERIT_MAX_HEALTH) + speed_mod = clamp(speed_mod, RAPTOR_INHERIT_MIN_SPEED, RAPTOR_INHERIT_MAX_SPEED) + ability_mod = clamp(ability_mod, RAPTOR_INHERIT_MIN_MODIFIER, RAPTOR_INHERIT_MAX_MODIFIER) + growth_mod = clamp(growth_mod, RAPTOR_INHERIT_MIN_MODIFIER, RAPTOR_INHERIT_MAX_MODIFIER) + + attack_modifier = rand((min(mom_stats.attack_modifier, dad_stats.attack_modifier) + min(0, attack_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MIN_ATTACK, (max(mom_stats.attack_modifier, dad_stats.attack_modifier) + max(0, attack_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MAX_ATTACK) + health_modifier = rand((min(mom_stats.health_modifier, dad_stats.health_modifier) + min(0, health_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MIN_HEALTH, (max(mom_stats.health_modifier, dad_stats.health_modifier) + max(0, health_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MAX_HEALTH) + speed_modifier = rand((min(mom_stats.speed_modifier, dad_stats.speed_modifier) + min(0, speed_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MIN_SPEED, (max(mom_stats.speed_modifier, dad_stats.speed_modifier) + max(0, speed_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MAX_SPEED) + ability_modifier = rand((min(mom_stats.ability_modifier, dad_stats.ability_modifier) + min(0, ability_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MIN_MODIFIER, (max(mom_stats.ability_modifier, dad_stats.ability_modifier) + max(0, ability_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MAX_MODIFIER) + growth_modifier = rand((min(mom_stats.growth_modifier, dad_stats.growth_modifier) + min(0, growth_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MIN_MODIFIER, (max(mom_stats.growth_modifier, dad_stats.growth_modifier) + max(0, growth_mod)) + RAPTOR_GENETIC_DRIFT * RAPTOR_INHERIT_MAX_MODIFIER) + + for(var/i in 1 to min(length(traits_to_pick), RAPTOR_TRAIT_INHERIT_AMOUNT)) + var/chosen_trait = pick_weight(traits_to_pick) + traits_to_pick -= chosen_trait + personality_traits += chosen_trait + + attack_modifier = clamp(attack_modifier, RAPTOR_INHERIT_MIN_ATTACK, RAPTOR_INHERIT_MAX_ATTACK) + health_modifier = clamp(health_modifier, RAPTOR_INHERIT_MIN_HEALTH, RAPTOR_INHERIT_MAX_HEALTH) + speed_modifier = clamp(speed_modifier, RAPTOR_INHERIT_MIN_SPEED, RAPTOR_INHERIT_MAX_SPEED) + ability_modifier = clamp(ability_modifier, RAPTOR_INHERIT_MIN_MODIFIER, RAPTOR_INHERIT_MAX_MODIFIER) + growth_modifier = clamp(growth_modifier, RAPTOR_INHERIT_MIN_MODIFIER, RAPTOR_INHERIT_MAX_MODIFIER) diff --git a/code/modules/mob/living/basic/snails/snail.dm b/code/modules/mob/living/basic/snails/snail.dm index 0cbdaf9f113..5c8ea912ee4 100644 --- a/code/modules/mob/living/basic/snails/snail.dm +++ b/code/modules/mob/living/basic/snails/snail.dm @@ -81,6 +81,7 @@ /mob/living/basic/snail/mob_pickup(mob/living/user) var/obj/item/mob_holder/snail/holder = new(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags) + SEND_SIGNAL(src, COMSIG_LIVING_SCOOPED_UP, user, holder) var/display_message = "[user] [HAS_TRAIT(src, TRAIT_MOVE_FLOATING) ? "scoops up [src]" : "peels [src] off the ground"]!" user.visible_message(span_warning(display_message)) user.put_in_hands(holder) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 9406dda88d4..f11eece642a 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -280,6 +280,7 @@ mob_height = dna?.species?.update_species_heights(src) || base_mob_height if(old_height != mob_height) regenerate_icons() + SEND_SIGNAL(src, COMSIG_HUMAN_HEIGHT_UPDATED, old_height) /** * Makes a full copy of src and returns it. diff --git a/code/modules/mob/living/inhand_holder.dm b/code/modules/mob/living/inhand_holder.dm index f7f76700d53..509d4e4f004 100644 --- a/code/modules/mob/living/inhand_holder.dm +++ b/code/modules/mob/living/inhand_holder.dm @@ -8,8 +8,6 @@ slot_flags = NONE /// Mob inside of us var/mob/living/held_mob - /// True if we've started being destroyed - var/destroying = FALSE lefthand_file = 'icons/mob/inhands/clothing/hats_lefthand.dmi' righthand_file = 'icons/mob/inhands/clothing/hats_righthand.dmi' body_parts_covered = HEAD @@ -31,9 +29,9 @@ return ..() /obj/item/mob_holder/Destroy() - destroying = TRUE - if(held_mob) + if(held_mob?.loc == src) release() + held_mob = null return ..() /obj/item/mob_holder/proc/insert_mob(mob/living/new_prisoner) @@ -78,11 +76,10 @@ /obj/item/mob_holder/proc/release(display_messages = TRUE) if(!held_mob) - if(!destroying) + if(!QDELETED(src)) qdel(src) return FALSE var/mob/living/released_mob = held_mob - held_mob = null // stops the held mob from being release()'d twice. if(isliving(loc)) var/mob/living/captor = loc if(display_messages) @@ -93,7 +90,7 @@ released_mob.setDir(SOUTH) if(display_messages) released_mob.visible_message(span_warning("[released_mob] uncurls!")) - if(!destroying) + if(!QDELETED(src)) qdel(src) return TRUE @@ -159,3 +156,6 @@ if(. || !held_mob) // Another interaction was performed return tool.melee_attack_chain(user, held_mob, modifiers) //Interact with the mob with our tool + +/obj/item/mob_holder/IsContainedAtomAccessible(atom/contained, atom/movable/user) + return TRUE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 7938b8f5447..9d86aa3eb06 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1965,7 +1965,8 @@ GLOBAL_LIST_EMPTY(fire_appearances) return ..() /mob/living/proc/mob_pickup(mob/living/user) - var/obj/item/mob_holder/holder = new(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags) + var/obj/item/mob_holder/holder = new inhand_holder_type(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags) + SEND_SIGNAL(src, COMSIG_LIVING_SCOOPED_UP, user, holder) user.visible_message(span_warning("[user] scoops up [src]!")) user.put_in_hands(holder) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index cc8934a755a..8b85214bbdd 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -204,6 +204,8 @@ var/icon/head_icon = 'icons/mob/clothing/head/pets_head.dmi' /// icon_state for holding mobs. var/held_state = "" + /// Typepath of the holder created when we're picked up + var/inhand_holder_type = /obj/item/mob_holder ///If combat mode is on or not var/combat_mode = FALSE diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm index 43341cfbc16..8f046748514 100644 --- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm @@ -259,6 +259,7 @@ greyscale_colors = "#927444#8b4c31#4c202d" starting_programs = list( /datum/computer_file/program/skill_tracker, + /datum/computer_file/program/raptordex, ) /obj/item/modular_computer/pda/bitrunner diff --git a/code/modules/modular_computers/file_system/programs/raptordex.dm b/code/modules/modular_computers/file_system/programs/raptordex.dm new file mode 100644 index 00000000000..b54e847ce1f --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/raptordex.dm @@ -0,0 +1,61 @@ +/datum/computer_file/program/raptordex + filename = "raptordex" + filedesc = "RaptorDex" + downloader_category = PROGRAM_CATEGORY_DEVICE + program_open_overlay = "bountyboard" + extended_desc = "Scan and analyze raptor genes." + size = 2 + tgui_id = "RaptorDex" + program_icon = "crow" + can_run_on_flags = PROGRAM_PDA + /// Raptor scan data we have stored + var/list/scan_data = list("raptor_scan" = FALSE) + +/datum/computer_file/program/raptordex/tap(atom/tapped_atom, mob/living/user, list/modifiers) + if(!istype(tapped_atom, /mob/living/basic/raptor)) + return FALSE + + var/mob/living/basic/raptor/my_raptor = tapped_atom + var/datum/movespeed_modifier/intent_mod = my_raptor.get_move_intent_slowdown() + + scan_data = list() + scan_data["raptor_scan"] = TRUE + scan_data["raptor_image"] = icon2base64(icon(icon = my_raptor.icon, icon_state = my_raptor.icon_state, dir = SOUTH, frame = 1)) + scan_data["raptor_attack"] = my_raptor.melee_damage_lower + scan_data["raptor_health"] = my_raptor.health + scan_data["raptor_max_health"] = my_raptor.maxHealth + scan_data["raptor_speed"] = my_raptor.speed + intent_mod?.multiplicative_slowdown + scan_data["raptor_color"] = my_raptor.name + scan_data["raptor_gender"] = my_raptor.gender + scan_data["raptor_description"] = my_raptor.raptor_color.description + + var/happiness_percentage = my_raptor.ai_controller?.blackboard[BB_BASIC_HAPPINESS] + var/obj/effect/overlay/happiness_overlay/display = new() + display.set_hearts(happiness_percentage) + display.pixel_y = ICON_SIZE_Y * 0.5 + scan_data["raptor_happiness"] = icon2base64(getFlatIcon(display, no_anim = TRUE)) + qdel(display) + + var/datum/raptor_inheritance/inherit = my_raptor.inherited_stats + if(!isnull(inherit)) + scan_data["inherited_attack"] = inherit.attack_modifier + scan_data["inherited_attack_max"] = RAPTOR_INHERIT_MAX_ATTACK + scan_data["inherited_health"] = inherit.health_modifier + scan_data["inherited_health_max"] = RAPTOR_INHERIT_MAX_HEALTH + scan_data["inherited_speed"] = inherit.speed_modifier + scan_data["inherited_speed_max"] = RAPTOR_INHERIT_MAX_SPEED + scan_data["inherited_ability"] = inherit.ability_modifier + scan_data["inherited_ability_max"] = RAPTOR_INHERIT_MAX_MODIFIER + scan_data["inherited_growth"] = inherit.growth_modifier + scan_data["inherited_growth_max"] = RAPTOR_INHERIT_MAX_MODIFIER + + scan_data["inherited_traits"] = list() + for(var/index in inherit.personality_traits) + scan_data["inherited_traits"] += GLOB.raptor_inherit_traits[index] + + playsound(computer, 'sound/mobs/non-humanoids/orbie/orbie_send_out.ogg', 20) + my_raptor.balloon_alert(user, "scanned") + return TRUE + +/datum/computer_file/program/raptordex/ui_data(mob/user) + return scan_data diff --git a/code/modules/movespeed/modifiers/items.dm b/code/modules/movespeed/modifiers/items.dm index 1f988f50c57..a94dc9ade5e 100644 --- a/code/modules/movespeed/modifiers/items.dm +++ b/code/modules/movespeed/modifiers/items.dm @@ -11,6 +11,12 @@ /datum/movespeed_modifier/jetpack/wings multiplicative_slowdown = -0.3 +/datum/movespeed_modifier/jetpack/raptor + multiplicative_slowdown = 0.2 + +/datum/movespeed_modifier/jetpack/raptor/slow + multiplicative_slowdown = 1 + /datum/movespeed_modifier/die_of_fate multiplicative_slowdown = 1 diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm index 8a3adfde01c..f3107b31af3 100644 --- a/code/modules/movespeed/modifiers/mobs.dm +++ b/code/modules/movespeed/modifiers/mobs.dm @@ -163,10 +163,10 @@ variable = TRUE /datum/movespeed_modifier/goliath_mount - multiplicative_slowdown = -26 + multiplicative_slowdown = -27.5 /datum/movespeed_modifier/goldgrub_mount - multiplicative_slowdown = -3 + multiplicative_slowdown = -4.5 /datum/movespeed_modifier/settler multiplicative_slowdown = 0.2 diff --git a/icons/mob/actions/actions_animal.dmi b/icons/mob/actions/actions_animal.dmi index b0b58b463f5..fa6d350e7b4 100644 Binary files a/icons/mob/actions/actions_animal.dmi and b/icons/mob/actions/actions_animal.dmi differ diff --git a/icons/mob/clothing/back/pets_back.dmi b/icons/mob/clothing/back/pets_back.dmi new file mode 100644 index 00000000000..b65c53cf369 Binary files /dev/null and b/icons/mob/clothing/back/pets_back.dmi differ diff --git a/icons/mob/simple/lavaland/raptor_baby.dmi b/icons/mob/simple/lavaland/raptor_baby.dmi index f892a3cb84f..861ea55efd4 100644 Binary files a/icons/mob/simple/lavaland/raptor_baby.dmi and b/icons/mob/simple/lavaland/raptor_baby.dmi differ diff --git a/icons/mob/simple/lavaland/raptor_big.dmi b/icons/mob/simple/lavaland/raptor_big.dmi index 2a89d84c85e..ebc70e20c3c 100644 Binary files a/icons/mob/simple/lavaland/raptor_big.dmi and b/icons/mob/simple/lavaland/raptor_big.dmi differ diff --git a/tgstation.dme b/tgstation.dme index a720f56ee10..2d650fb273e 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1625,6 +1625,7 @@ #include "code\datums\elements\radiation_protected_clothing.dm" #include "code\datums\elements\radioactive.dm" #include "code\datums\elements\ranged_armour.dm" +#include "code\datums\elements\raptor_food.dm" #include "code\datums\elements\reagents_heated_on_fire.dm" #include "code\datums\elements\reagents_item_heatable.dm" #include "code\datums\elements\regal_rat_minion.dm" @@ -5199,10 +5200,10 @@ #include "code\modules\mob\living\basic\lavaland\mook\mook_village.dm" #include "code\modules\mob\living\basic\lavaland\node_drone\node_drone.dm" #include "code\modules\mob\living\basic\lavaland\raptor\_raptor.dm" -#include "code\modules\mob\living\basic\lavaland\raptor\baby_raptor.dm" #include "code\modules\mob\living\basic\lavaland\raptor\raptor_ai_behavior.dm" #include "code\modules\mob\living\basic\lavaland\raptor\raptor_ai_controller.dm" #include "code\modules\mob\living\basic\lavaland\raptor\raptor_ai_subtrees.dm" +#include "code\modules\mob\living\basic\lavaland\raptor\raptor_color.dm" #include "code\modules\mob\living\basic\lavaland\raptor\raptor_dex.dm" #include "code\modules\mob\living\basic\lavaland\raptor\raptor_egg.dm" #include "code\modules\mob\living\basic\lavaland\raptor\raptor_food_trough.dm" @@ -5656,6 +5657,7 @@ #include "code\modules\modular_computers\file_system\programs\portrait_printer.dm" #include "code\modules\modular_computers\file_system\programs\powermonitor.dm" #include "code\modules\modular_computers\file_system\programs\radar.dm" +#include "code\modules\modular_computers\file_system\programs\raptordex.dm" #include "code\modules\modular_computers\file_system\programs\records.dm" #include "code\modules\modular_computers\file_system\programs\restock_tracker.dm" #include "code\modules\modular_computers\file_system\programs\robocontrol.dm" diff --git a/tgui/packages/tgui/interfaces/RaptorDex.tsx b/tgui/packages/tgui/interfaces/RaptorDex.tsx index f777837b23c..27724a533b3 100644 --- a/tgui/packages/tgui/interfaces/RaptorDex.tsx +++ b/tgui/packages/tgui/interfaces/RaptorDex.tsx @@ -1,17 +1,20 @@ import { Image, LabeledList, + Modal, ProgressBar, Section, Stack, } from 'tgui-core/components'; - +import { capitalizeAll, capitalizeFirst } from 'tgui-core/string'; import { useBackend } from '../backend'; import { Window } from '../layouts'; type Data = { + raptor_scan: boolean; raptor_attack: number; raptor_health: number; + raptor_max_health: number; raptor_speed: number; raptor_color: string; raptor_image: string; @@ -22,14 +25,22 @@ type Data = { inherited_attack_max: number; inherited_health: number; inherited_health_max: number; + inherited_speed: number; + inherited_speed_max: number; + inherited_ability: number; + inherited_ability_max: number; + inherited_growth: number; + inherited_growth_max: number; inherited_traits: string[]; }; export const RaptorDex = (props) => { const { act, data } = useBackend(); const { + raptor_scan, raptor_attack, raptor_health, + raptor_max_health, raptor_speed, raptor_image, raptor_gender, @@ -37,21 +48,39 @@ export const RaptorDex = (props) => { inherited_attack_max, inherited_health, inherited_health_max, + inherited_speed, + inherited_speed_max, + inherited_ability, + inherited_ability_max, + inherited_growth, + inherited_growth_max, raptor_happiness, inherited_traits, raptor_description, raptor_color, } = data; + + if (!raptor_scan) { + return ( + + + No scan data present. + + + ); + } + return ( - + + {' '} -
+
{ }} />
+
+ {raptor_description} +
- {raptor_health} + {raptor_health} / {raptor_max_health} {raptor_attack} - {10 - raptor_speed} + {Math.round(10 / Math.max(raptor_speed, 0.5))} - {raptor_gender} + {capitalizeFirst(raptor_gender)}
@@ -84,12 +116,9 @@ export const RaptorDex = (props) => { value={inherited_health} maxValue={inherited_health_max} ranges={{ - good: [0.7 * inherited_health_max, inherited_health_max], - average: [ - 0.4 * inherited_health_max, - inherited_health_max, - ], - bad: [-Infinity, inherited_health_max], + good: [0.5 * inherited_health_max, Infinity], + average: [0, inherited_health_max * 0.5], + bad: [-Infinity, 0], }} /> @@ -98,12 +127,42 @@ export const RaptorDex = (props) => { value={inherited_attack} maxValue={inherited_attack_max} ranges={{ - good: [0.7 * inherited_attack_max, inherited_attack_max], - average: [ - 0.4 * inherited_attack_max, - inherited_attack_max, - ], - bad: [-Infinity, inherited_attack_max], + good: [0.5 * inherited_attack_max, Infinity], + average: [0, inherited_attack_max * 0.5], + bad: [-Infinity, 0], + }} + /> + + + + + + + + + @@ -113,7 +172,7 @@ export const RaptorDex = (props) => {
{
-
- {raptor_description} -
);