diff --git a/_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm b/_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm index f8be6a5fccc..82bb62e0908 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm @@ -214,7 +214,7 @@ }, /area/ruin/space/tcommsat) "lq" = ( -/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob/modsuit, /turf/simulated/floor/plating/airless, /area/ruin/space/tcommsat) "my" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm b/_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm index 022a9a203e1..2ffe30eefbb 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm @@ -22,7 +22,7 @@ /turf/template_noop, /area/template_noop) "af" = ( -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space, +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/backup, /turf/template_noop, /area/template_noop) "ag" = ( @@ -126,7 +126,7 @@ /area/ruin) "aW" = ( /obj/structure/lattice, -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space, +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/backup, /turf/template_noop, /area/template_noop) "aY" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm b/_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm index bd07b50dc38..466e24b7cc3 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm @@ -141,7 +141,7 @@ /turf/template_noop, /area/template_noop) "U" = ( -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space, +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/backup, /turf/template_noop, /area/template_noop) "V" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm b/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm index 7474a3c3748..f8ac4b5cfe7 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm @@ -442,9 +442,7 @@ /area/ruin/space/syndicate_listening_station) "Go" = ( /obj/structure/chair/office/dark, -/mob/living/simple_animal/hostile/syndicate{ - name = "Syndicate Communications Officer" - }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob, /turf/simulated/floor/plasteel/dark, /area/ruin/space/syndicate_listening_station) "Gy" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/submaps/sieged_lab_submaps.dmm b/_maps/map_files/RandomRuins/SpaceRuins/submaps/sieged_lab_submaps.dmm index 8b066c4298f..f0fab13debe 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/submaps/sieged_lab_submaps.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/submaps/sieged_lab_submaps.dmm @@ -17,7 +17,7 @@ /area/template_noop) "ax" = ( /obj/effect/map_effect/marker/mapmanip/submap/extract/ruin/sieged_lab/horiz_hallway, -/mob/living/simple_animal/hostile/syndicate/melee, +/mob/living/simple_animal/hostile/syndicate, /turf/template_noop, /area/template_noop) "aK" = ( @@ -1625,7 +1625,7 @@ /turf/template_noop, /area/template_noop) "GI" = ( -/mob/living/simple_animal/hostile/syndicate/melee, +/mob/living/simple_animal/hostile/syndicate, /turf/simulated/floor/plasteel{ icon_state = "white" }, @@ -1660,7 +1660,7 @@ /turf/simulated/floor/plating, /area/template_noop) "Hq" = ( -/mob/living/simple_animal/hostile/syndicate/melee, +/mob/living/simple_animal/hostile/syndicate, /turf/simulated/floor/plating, /area/template_noop) "HF" = ( @@ -2146,7 +2146,7 @@ }, /area/template_noop) "Uq" = ( -/mob/living/simple_animal/hostile/syndicate/melee, +/mob/living/simple_animal/hostile/syndicate, /turf/template_noop, /area/template_noop) "UH" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm b/_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm index 63cc3040fdd..dc8db2a6f14 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm @@ -142,7 +142,7 @@ /turf/template_noop, /area/ruin/space/syndicate_druglab/asteroid) "st" = ( -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob, /turf/simulated/floor/pod/dark, /area/ruin/space/syndicate_druglab) "sD" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm b/_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm index 2ab0ea1a3a9..4ce36fd5684 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm @@ -742,7 +742,7 @@ /area/template_noop) "CR" = ( /obj/structure/chair/office/dark, -/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob, /turf/simulated/floor/engine, /area/ruin/space/syndicakefactory) "CW" = ( @@ -803,7 +803,7 @@ }, /area/ruin/space/syndicakefactory) "EH" = ( -/obj/effect/mob_spawn/human/corpse/syndicatesoldier, +/obj/effect/mob_spawn/human/corpse/syndicate, /turf/simulated/floor/plasteel{ icon_state = "cafeteria" }, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm b/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm index f2d247630ed..cdcdf7e822e 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm @@ -481,7 +481,7 @@ }, /area/syndicate_depot/core) "bC" = ( -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer, +/mob/living/simple_animal/hostile/syndicate/depot/officer, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -838,7 +838,7 @@ /obj/machinery/atmospherics/pipe/simple/hidden{ dir = 4 }, -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory, +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/elite, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -879,7 +879,7 @@ /obj/machinery/atmospherics/unary/passive_vent/high_volume{ dir = 8 }, -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer, +/mob/living/simple_animal/hostile/syndicate/depot/officer, /turf/simulated/floor/plasteel{ icon_state = "dark" }, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm b/_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm index ae5b9c8337d..203d8aea28a 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm @@ -40,11 +40,6 @@ /obj/item/clothing/mask/gas/syndicate, /turf/simulated/floor/plasteel/dark, /area/ruin/space/turreted_outpost/vault) -"eg" = ( -/obj/structure/chair/comfy/red, -/mob/living/simple_animal/hostile/syndicate/ranged, -/turf/simulated/floor/plasteel/dark, -/area/ruin/space/turreted_outpost) "eh" = ( /obj/structure/cable/yellow{ icon_state = "1-8" @@ -190,7 +185,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/mob/living/simple_animal/hostile/syndicate/ranged, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob, /turf/simulated/floor/plasteel/dark, /area/ruin/space/turreted_outpost) "sp" = ( @@ -249,8 +244,8 @@ /turf/simulated/floor/plasteel/freezer, /area/ruin/space/turreted_outpost) "wW" = ( -/mob/living/simple_animal/hostile/syndicate/ranged, /obj/structure/chair/comfy/red, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob, /turf/simulated/floor/plasteel/dark, /area/ruin/space/turreted_outpost) "xd" = ( @@ -322,10 +317,10 @@ /obj/structure/chair{ dir = 8 }, -/mob/living/simple_animal/hostile/syndicate/melee/autogib, /obj/structure/cable{ icon_state = "1-2" }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob/modsuit, /turf/simulated/floor/plasteel/dark, /area/ruin/space/turreted_outpost) "Cp" = ( @@ -375,7 +370,7 @@ /area/ruin/space/turreted_outpost) "Fz" = ( /obj/structure/chair/comfy/red, -/mob/living/simple_animal/hostile/syndicate/melee/autogib, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob/modsuit, /turf/simulated/floor/plasteel/dark, /area/ruin/space/turreted_outpost) "Gd" = ( @@ -1129,7 +1124,7 @@ iq qa Ja QB -eg +wW HH Ub qK diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm index 79b2dcc3ab7..c58f741a19c 100644 --- a/code/datums/outfits/outfit_admin.dm +++ b/code/datums/outfits/outfit_admin.dm @@ -92,7 +92,7 @@ l_hand = /obj/item/tank/internals/oxygen/red backpack_contents = list( - /obj/item/storage/box/survival_syndi = 1, + /obj/item/storage/box/survival_syndie = 1, /obj/item/gun/projectile/automatic/pistol = 1, /obj/item/ammo_box/magazine/m10mm = 1, /obj/item/crowbar/red = 1, diff --git a/code/game/area/areas/depot-areas.dm b/code/game/area/areas/depot-areas.dm index 52def39ba0d..7b047a22b06 100644 --- a/code/game/area/areas/depot-areas.dm +++ b/code/game/area/areas/depot-areas.dm @@ -254,7 +254,7 @@ var/obj/effect/landmark/L = thing if(prob(50)) if(L.name == "syndi_depot_backup") - var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space/S = new /mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space(get_turf(L)) + var/mob/living/simple_animal/hostile/syndicate/depot/modsuit/backup/S = new /mob/living/simple_animal/hostile/syndicate/depot/modsuit/backup(get_turf(L)) S.name = "Syndicate Backup " + "([rand(1, 1000)])" S.depotarea = src list_add(S, guard_list) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 99be8d840c2..ce855240606 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -281,7 +281,7 @@ synd_mob.equip_to_slot_or_del(new /obj/item/card/id/syndicate(synd_mob), ITEM_SLOT_ID) synd_mob.equip_to_slot_or_del(new back(synd_mob), ITEM_SLOT_BACK) synd_mob.equip_to_slot_or_del(new /obj/item/gun/projectile/automatic/pistol(synd_mob), ITEM_SLOT_BELT) - synd_mob.equip_to_slot_or_del(new /obj/item/storage/box/survival_syndi(synd_mob.back), ITEM_SLOT_IN_BACKPACK) + synd_mob.equip_to_slot_or_del(new /obj/item/storage/box/survival_syndie(synd_mob.back), ITEM_SLOT_IN_BACKPACK) synd_mob.equip_to_slot_or_del(new /obj/item/pinpointer/nukeop(synd_mob), ITEM_SLOT_PDA) var/obj/item/radio/uplink/nuclear/U = new /obj/item/radio/uplink/nuclear(synd_mob) U.hidden_uplink.uplink_owner="[synd_mob.key]" diff --git a/code/game/jobs/job/syndicate_jobs.dm b/code/game/jobs/job/syndicate_jobs.dm index 68a462ccc48..99418e9aa27 100644 --- a/code/game/jobs/job/syndicate_jobs.dm +++ b/code/game/jobs/job/syndicate_jobs.dm @@ -28,7 +28,7 @@ l_ear = /obj/item/radio/headset/syndicate/alt/syndteam pda = /obj/item/pinpointer/advpinpointer id = /obj/item/card/id/syndicate/command - box = /obj/item/storage/box/survival_syndi + box = /obj/item/storage/box/survival_syndie backpack_contents = list( /obj/item/flashlight = 1, /obj/item/ammo_box/magazine/m50 = 2, diff --git a/code/game/objects/effects/spawners/depot_spawners.dm b/code/game/objects/effects/spawners/depot_spawners.dm index 153871d088e..0e9c2813c6a 100644 --- a/code/game/objects/effects/spawners/depot_spawners.dm +++ b/code/game/objects/effects/spawners/depot_spawners.dm @@ -20,8 +20,8 @@ /obj/effect/spawner/random/syndicate/mob name = "50pc melee syndimob" icon = 'icons/effects/spawner_icons.dmi' - icon_state = "syndie_depot" - loot = list(/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot) + icon_state = "syndicate" + loot = list(/mob/living/simple_animal/hostile/syndicate/depot) spawn_loot_chance = 50 /obj/effect/spawner/random/syndicate/medbot diff --git a/code/game/objects/effects/spawners/random/loot_spawners.dm b/code/game/objects/effects/spawners/random/loot_spawners.dm index 2b74e43368f..79102c0711a 100644 --- a/code/game/objects/effects/spawners/random/loot_spawners.dm +++ b/code/game/objects/effects/spawners/random/loot_spawners.dm @@ -134,3 +134,12 @@ /obj/effect/spawner/random/bluespace_tap/food_uncommon = 3, /obj/effect/spawner/random/bluespace_tap/food_rare, ) + +/obj/effect/spawner/random/syndie_mob_loot + loot = list( + /obj/item/reagent_containers/patch/styptic, + /obj/item/reagent_containers/patch/silver_sulf, + /obj/item/food/syndicake, + /obj/item/food/donkpocket, + /obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, + ) diff --git a/code/game/objects/effects/spawners/random/pool/space_loot.dm b/code/game/objects/effects/spawners/random/pool/space_loot.dm index 330791fe8ea..05fedf6472f 100644 --- a/code/game/objects/effects/spawners/random/pool/space_loot.dm +++ b/code/game/objects/effects/spawners/random/pool/space_loot.dm @@ -85,7 +85,7 @@ ) /obj/effect/spawner/random/pool/spaceloot/syndicate/stetchkin - name = "syndicate depot loot, 20% stetchkin" + name = "syndicate depot loot, 80% stetchkin" icon_state = "stetchkin" spawn_loot_chance = 80 point_value = 25 @@ -208,7 +208,6 @@ /obj/item/mod/module/stealth, ) - /obj/effect/spawner/random/pool/spaceloot/syndicate/armory name = "syndicate depot loot, armory" // Combat orientated items that could give the player an advantage if an antag messes with them. @@ -230,6 +229,10 @@ /obj/item/mod/module/stealth, ) +/obj/effect/spawner/random/pool/spaceloot/syndicate/armory/elite/Initialize(mapload) + loot ^= list(/obj/item/mod/control/pre_equipped/traitor_elite) + . = ..() + /obj/effect/spawner/random/pool/spaceloot/syndicate/armory/depot guaranteed = TRUE spawn_inside = /obj/structure/closet/secure_closet/depot/armory @@ -251,7 +254,6 @@ /obj/item/cqc_manual, ) - /obj/effect/spawner/random/pool/spaceloot/syndicate/mixed loot = list( /obj/effect/spawner/random/pool/spaceloot/syndicate/common = 30, @@ -260,6 +262,39 @@ /obj/effect/spawner/random/pool/spaceloot/syndicate/armory = 1, ) +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob + icon = 'icons/effects/spawner_icons.dmi' + icon_state = "syndicate_random" + loot = list( + /obj/effect/spawner/random/pool/spaceloot/syndicate/mob/common = 80, + /obj/effect/spawner/random/pool/spaceloot/syndicate/mob/modsuit = 19, + + // Let the massacre begin + /obj/effect/spawner/random/pool/spaceloot/syndicate/mob/elite, // 1% + ) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob/elite + point_value = 200 // Guaranteed armory-tier loot on death + loot = list(/mob/living/simple_animal/hostile/syndicate/modsuit/elite) + +// Used when we want our mob to be protected from environment pressure +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob/modsuit + icon_state = "syndicate_random_mod" + point_value = 6 // Modsuit chance + loot = list( + /mob/living/simple_animal/hostile/syndicate/modsuit, + /mob/living/simple_animal/hostile/syndicate/modsuit/ranged, + ) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/mob/common + icon_state = "syndicate" + point_value = 3 + loot = list( + /mob/living/simple_animal/hostile/syndicate/ranged = 4, + /mob/living/simple_animal/hostile/syndicate = 3, // Melee is stronger than ranged variant most of the time + /mob/living/simple_animal/hostile/syndicate/shield, + ) + // Only two of these /obj/effect/spawner/random/pool/spaceloot/zoo unique_picks = TRUE @@ -270,11 +305,6 @@ /obj/item/gun/energy/temperature, ) -/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie - point_value = 100 - spawn_loot_chance = 50 - loot = list(/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib) - /obj/effect/spawner/random/pool/spaceloot/moonoutpost19 name = "moon outpost 19 loot spawner" point_value = 30 @@ -315,7 +345,6 @@ spawn_random_offset = TRUE spawn_random_offset_max_pixels = 8 - /obj/effect/spawner/random/pool/spaceloot/mechtransport/storage1 loot = list( /obj/item/mecha_parts/mecha_equipment/repair_droid, @@ -335,4 +364,3 @@ /obj/effect/spawner/random/pool/spaceloot/mechtransport/storage4 loot = list(/obj/item/mecha_parts/core) - diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index d8e4f776581..17e5d73a3d3 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -110,6 +110,12 @@ icon_state = "syndie_headset" item_state = "syndie_headset" +/obj/item/radio/headset/syndicate_fake + name = "syndicate headset" + desc = "A syndicate headset to set on your head." + icon_state = "syndie_headset" + item_state = "syndie_headset" + /obj/item/radio/headset/syndicate/syndteam ks1type = /obj/item/encryptionkey/syndteam diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 9a026b2135b..5df6836396c 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -112,10 +112,11 @@ new /obj/item/reagent_containers/hypospray/autoinjector/epinephrine(src) new /obj/item/flashlight/flare/glowstick/emergency(src) -/obj/item/storage/box/survival_syndi - icon_state = "syndi_box" +/obj/item/storage/box/survival_syndie + icon_state = "syndie_box" + desc = "A sleek, sturdy box." -/obj/item/storage/box/survival_syndi/populate_contents() +/obj/item/storage/box/survival_syndie/populate_contents() new /obj/item/clothing/mask/gas/syndicate(src) new /obj/item/tank/internals/emergency_oxygen/engi/syndi(src) new /obj/item/crowbar/small(src) @@ -123,6 +124,24 @@ new /obj/item/reagent_containers/pill/initropidril(src) new /obj/item/flashlight/flare/glowstick/red(src) +/obj/item/storage/box/survival_syndie/traitor/populate_contents() + new /obj/item/clothing/mask/gas/syndicate(src) + new /obj/item/tank/internals/emergency_oxygen/engi/syndi(src) + new /obj/item/crowbar/small(src) + new /obj/item/reagent_containers/hypospray/autoinjector/epinephrine(src) + new /obj/item/flashlight/flare/glowstick/red(src) + +/obj/item/storage/box/survival_syndie/traitor/loot/populate_contents() + new /obj/item/crowbar/small(src) + new /obj/item/reagent_containers/hypospray/autoinjector/epinephrine(src) + new /obj/item/flashlight/flare/glowstick/red(src) + +/obj/item/storage/box/syndie_kit/loot/populate_contents() + new /obj/effect/spawner/random/syndie_mob_loot(src) + +/obj/item/storage/box/syndie_kit/loot/elite/populate_contents() + new /obj/effect/spawner/random/pool/spaceloot/syndicate/armory/elite(src) + ////////////////// /* Common Boxes */ ////////////////// diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm index 4131c3c071e..f8919de1c21 100644 --- a/code/modules/admin/verbs/striketeam_syndicate.dm +++ b/code/modules/admin/verbs/striketeam_syndicate.dm @@ -131,7 +131,7 @@ GLOBAL_VAR_INIT(sent_syndicate_strike_team, 0) equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(src), ITEM_SLOT_GLOVES) equip_to_slot_or_del(new /obj/item/storage/backpack/security(src), ITEM_SLOT_BACK) - equip_to_slot_or_del(new /obj/item/storage/box/survival_syndi(src), ITEM_SLOT_IN_BACKPACK) + equip_to_slot_or_del(new /obj/item/storage/box/survival_syndie(src), ITEM_SLOT_IN_BACKPACK) equip_to_slot_or_del(new /obj/item/gun/projectile/revolver(src), ITEM_SLOT_IN_BACKPACK) equip_to_slot_or_del(new /obj/item/ammo_box/a357(src), ITEM_SLOT_IN_BACKPACK) diff --git a/code/modules/awaymissions/mob_spawn.dm b/code/modules/awaymissions/mob_spawn.dm index 0edf26f7964..22b0b10b3db 100644 --- a/code/modules/awaymissions/mob_spawn.dm +++ b/code/modules/awaymissions/mob_spawn.dm @@ -207,7 +207,10 @@ var/suit_store = -1 var/hair_style var/facial_hair_style + var/hair_color + var/facial_hair_color var/skin_tone + var/eyes_color var/list/del_types = list(/obj/item/pda, /obj/item/radio/headset) @@ -244,16 +247,28 @@ H.socks = "Nude" var/obj/item/organ/external/head/D = H.get_organ("head") if(istype(D)) + if(eyes_color) + H.change_eye_color(eyes_color) if(hair_style) D.h_style = hair_style else D.h_style = random_hair_style(gender, D.dna.species.name) - D.hair_colour = rand_hex_color() + if(hair_color) + D.hair_colour = hair_color + D.sec_hair_colour = hair_color + else + D.hair_colour = rand_hex_color() + D.sec_hair_colour = D.hair_colour if(facial_hair_style) D.f_style = facial_hair_style else D.f_style = random_facial_hair_style(gender, D.dna.species.name) - D.facial_colour = rand_hex_color() + if(facial_hair_color) + D.facial_colour = facial_hair_color + D.sec_facial_colour = facial_hair_color + else + D.facial_colour = rand_hex_color() + D.sec_facial_colour = D.facial_colour if(skin_tone) H.s_tone = skin_tone else diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 37c3a95a1df..0c8d6a0cd23 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -211,6 +211,12 @@ "Kidan" = 'icons/mob/clothing/species/kidan/eyes.dmi' ) +/obj/item/clothing/glasses/night/syndicate_fake + name = "suspicious night vision goggles" + desc = "A dark red tacticool goggles anyone would go operate with." + icon_state = "securityhudnight" + color = "#d62d20" // I want it to color the on mob's sprite as well, but i don't know how to actually. + /obj/item/clothing/glasses/eyepatch name = "eyepatch" desc = "Yarr." diff --git a/code/modules/mob/living/simple_animal/corpse.dm b/code/modules/mob/living/simple_animal/corpse.dm index 4bfde7a21eb..22c79dcada1 100644 --- a/code/modules/mob/living/simple_animal/corpse.dm +++ b/code/modules/mob/living/simple_animal/corpse.dm @@ -1,64 +1,117 @@ //List of different corpse types -/obj/effect/mob_spawn/human/corpse/syndicatesoldier +// MARK: Syndicate +/obj/effect/mob_spawn/human/corpse/syndicate name = "Syndicate Operative" - mob_name = "Syndicate Operative" - hair_style = "bald" - facial_hair_style = "shaved" - id_job = "Operative" + id_job = "err#unkwn" id_access_list = list(ACCESS_SYNDICATE) - outfit = /datum/outfit/syndicatesoldiercorpse + outfit = /datum/outfit/syndicatecorpse + del_types = list() + disable_pda = TRUE + var/name_changed + var/name_to_add + var/num_to_add -/datum/outfit/syndicatesoldiercorpse +/obj/effect/mob_spawn/human/corpse/syndicate/Initialize(mapload) + if(!name_changed) + name_to_add = pick("Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November", "Oscar", "Papa", "Quebec", "Romeo", "Sierra", "Tango", "Uniform", "Victor", "Whiskey", "X-ray", "Yankee", "Zulu") + num_to_add = rand(1, 1337) + mob_name = "[syndicate_name()] [name_to_add] #[num_to_add]" + name_changed = TRUE + brute_damage = rand(0, 200) + var/hcolor = pick("#000000", "#8B4513", "#FFD700") + var/ecolor = pick("#000000", "#8B4513", "#1E90FF") + hair_color = hcolor + facial_hair_color = hcolor + eyes_color = ecolor + skin_tone = pick(-50, -30, -10, 0, 0, 0, 10) + return ..() + +/datum/outfit/syndicatecorpse name = "Corpse of a Syndicate Operative" uniform = /obj/item/clothing/under/syndicate - suit = /obj/item/clothing/suit/armor/vest + suit = /obj/item/clothing/suit/jacket/bomber/syndicate + glasses = /obj/item/clothing/glasses/night/syndicate_fake shoes = /obj/item/clothing/shoes/combat gloves = /obj/item/clothing/gloves/combat - l_ear = /obj/item/radio/headset - mask = /obj/item/clothing/mask/gas - head = /obj/item/clothing/head/helmet/swat - back = /obj/item/storage/backpack + l_ear = /obj/item/radio/headset/syndicate_fake + mask = /obj/item/clothing/mask/gas/syndicate + head = /obj/item/clothing/head/helmet/swat/syndicate + back = /obj/item/storage/backpack/satchel + belt = /obj/item/storage/belt/utility/syndi_researcher + box = /obj/item/storage/box/survival_syndie/traitor/loot + l_pocket = /obj/item/tank/internals/emergency_oxygen/engi/syndi id = /obj/item/card/id/syndicate_fake + pda = /obj/item/pda/syndicate_fake + internals_slot = ITEM_SLOT_LEFT_POCKET + var/modsuit + var/armory_loot +/datum/outfit/syndicatecorpse/pre_equip(mob/living/carbon/human/H, visualsOnly) + . = ..() + if(modsuit && prob(5)) + box = null + head = null + suit = null + l_pocket = null + back = modsuit + suit_store = /obj/item/tank/internals/oxygen/red + internals_slot = ITEM_SLOT_SUIT_STORE + if(armory_loot) + backpack_contents |= /obj/item/storage/box/syndie_kit/loot/elite + else if(prob(50)) + backpack_contents |= /obj/item/storage/box/syndie_kit/loot -/obj/effect/mob_spawn/human/corpse/syndicatecommando +/datum/outfit/syndicatecorpse/post_equip(mob/living/carbon/human/H, visualsOnly) + . = ..() + if(H?.w_uniform) + var/obj/item/clothing/under/U = H.w_uniform + var/obj/item/clothing/accessory/holster/W = new /obj/item/clothing/accessory/holster(U) + U.accessories += W + W.on_attached(U) + +// MARK: Syndicate mod +/obj/effect/mob_spawn/human/corpse/syndicate/modsuit name = "Syndicate Commando" - mob_name = "Syndicate Commando" - hair_style = "bald" - facial_hair_style = "shaved" - id_job = "Operative" - id_access_list = list(ACCESS_SYNDICATE) - outfit = /datum/outfit/syndicatecommandocorpse + outfit = /datum/outfit/syndicatecorpse/modsuit -/datum/outfit/syndicatecommandocorpse +/obj/effect/mob_spawn/human/corpse/syndicate/modsuit/Initialize(mapload) + if(!name_changed) + name_to_add = pick("Aries", "Leo", "Sagittarius", "Taurus", "Virgo", "Capricorn", "Gemini", "Libra", "Aquarius", "Cancer", "Scorpio", "Pisces", "Rose", "Peony", "Lily", "Daisy", "Zinnia", "Ivy", "Iris", "Petunia", "Violet", "Lilac", "Orchid") + if(prob(95)) + num_to_add = pick("II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX") + mob_name = num_to_add ? "[syndicate_name()] [name_to_add] [num_to_add]" : "[syndicate_name()] [name_to_add]" + name_changed = TRUE + return ..() + +/datum/outfit/syndicatecorpse/modsuit name = "Corpse of a Syndicate Commando" - uniform = /obj/item/clothing/under/syndicate - shoes = /obj/item/clothing/shoes/combat - gloves = /obj/item/clothing/gloves/combat - l_ear = /obj/item/radio/headset - mask = /obj/item/clothing/mask/gas/syndicate - back = /obj/item/mod/control/pre_equipped/traitor - r_pocket = /obj/item/tank/internals/emergency_oxygen - id = /obj/item/card/id/syndicate_fake + modsuit = /obj/item/mod/control/pre_equipped/traitor -/obj/effect/mob_spawn/human/corpse/syndicatequartermaster +// MARK: Syndicate elite mod +/obj/effect/mob_spawn/human/corpse/syndicate/modsuit/elite + name = "Syndicate Overseer" + outfit = /datum/outfit/syndicatecorpse/modsuit/elite + +/obj/effect/mob_spawn/human/corpse/syndicate/modsuit/elite/Initialize(mapload) + if(!name_changed) + name_to_add = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord", "Berzerk", "Reaper", "Beast", "Hellwalker", "Slayer", "Oathbreaker", "Supreme Commander", "Overseer", "Butcher", "Executioner", "Judge", "Head of Shitcurity", "Unchained Predator", "Outlander", "DM1-5", "Scourge of Hell", "Doom") + mob_name = "[syndicate_name()] [name_to_add]" + name_changed = TRUE + return ..() + +/datum/outfit/syndicatecorpse/modsuit/elite + name = "Corpse of a Syndicate Overseer" + modsuit = /obj/item/mod/control/pre_equipped/traitor_elite + armory_loot = TRUE + +// MARK: Syndicate depot QM +/obj/effect/mob_spawn/human/corpse/syndicate/modsuit/elite/depot name = "Syndicate Quartermaster" - mob_name = "Syndicate Quartermaster" - hair_style = "bald" - facial_hair_style = "shaved" - id_job = "Operative" - id_access_list = list(ACCESS_SYNDICATE) - outfit = /datum/outfit/syndicatequartermastercorpse + outfit = /datum/outfit/syndicatecorpse/modsuit/elite/depot -/datum/outfit/syndicatequartermastercorpse +/datum/outfit/syndicatecorpse/modsuit/elite/depot name = "Corpse of a Syndicate Quartermaster" - uniform = /obj/item/clothing/under/syndicate - shoes = /obj/item/clothing/shoes/combat - gloves = /obj/item/clothing/gloves/combat - l_ear = /obj/item/radio/headset - mask = /obj/item/clothing/mask/gas/syndicate - r_pocket = /obj/item/tank/internals/emergency_oxygen - id = /obj/item/card/id/syndicate_fake + armory_loot = FALSE /obj/effect/mob_spawn/human/corpse/clown/corpse roundstart = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm b/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm index 72c9092f354..0e67511ff03 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm @@ -1,136 +1,655 @@ +#define BLOOD_HELMET "helmetblood" +#define BLOOD_MASK "maskblood" +#define BLOOD_ARMOR "armorblood" +#define BLOOD_SUIT "suitblood" +#define BLOOD_HANDS "bloodyhands" +#define BLOOD_SHOES "shoeblood" + +#define MELEE_WEAPON_NONE "slapper" +#define MELEE_WEAPON_ESWORD "sword" +#define MELEE_WEAPON_DSWORD "dsword" + +#define RANGED_WEAPON_PISTOL "gun" +#define RANGED_WEAPON_C20R "c20r" +#define RANGED_WEAPON_M90 "m90" +#define RANGED_WEAPON_SR "sr" +#define RANGED_WEAPON_SR_IDLE "sr-idle" + +#define SOUND_MOD 'sound/mecha/mechmove03.ogg' +#define SOUND_SMG 'sound/weapons/gunshots/gunshot_smg.ogg' +#define SOUND_AR 'sound/weapons/gunshots/gunshot_rifle.ogg' +#define SOUND_SR 'sound/weapons/gunshots/gunshot_sniper.ogg' + +#define SYNDICATE "syndicate" +#define RAIDER "syndicate_mod" +#define JAEGER "syndicate_elite" + +#define VISOR_MASK "mask" +#define VISOR_RAIDER "armor_booster" +#define VISOR_JAEGER "elite_armor_booster" + +#define ESHIELD (1 << 0) // Do we have an energy shield in our hands that will reflect any energy projectiles? +#define SWORD (1 << 1) // Whether we play activation/deactivation sound of e/dsword +#define MODSUIT (1 << 2) // Do we wear a modsuit? +#define ARMOR_BOOSTER (1 << 3) // If our armor booster currently active. Affects `damage_coeff` and overlay, used alongside `modsuit` only +#define HEALING (1 << 4) // Are we currently healing ourselves? +#define CRITICAL (1 << 5) // Are we in a critical condition? +#define ADRENAL (1 << 6) // Do we have an adrenal bio-chip? + +////////////////////////////// +// MARK: SYNDICATE MOB +////////////////////////////// /mob/living/simple_animal/hostile/syndicate name = "Syndicate Operative" desc = "Death to Nanotrasen." icon = 'icons/mob/simple_human.dmi' - icon_state = "syndicate" - icon_living = "syndicate" - icon_dead = "syndicate_dead" // Does not actually exist. del_on_death. - icon_gib = "syndicate_gib" // Does not actually exist. del_on_death. - mob_biotypes = MOB_ORGANIC | MOB_HUMANOID - damage_coeff = list("brute" = 1, "fire" = 1, "tox" = 0, "clone" = 0, "stamina" = 0, "oxy" = 0) - speak_chance = 0 - turns_per_move = 5 + icon_state = SYNDICATE + icon_living = SYNDICATE + attacktext = "slashes" response_help = "pokes the" response_disarm = "shoves the" response_harm = "hits the" - speed = 0 - maxHealth = 150 - health = 150 - harm_intent_damage = 5 - melee_damage_lower = 15 - melee_damage_upper = 15 - attacktext = "punches" - attack_sound = 'sound/weapons/punch1.ogg' + attack_sound = 'sound/weapons/blade1.ogg' + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) // We know how to use gasmasks + faction = list(SYNDICATE) + move_to_delay = 2.99 // Faster than human by 0.01 + del_on_death = TRUE + mob_biotypes = MOB_ORGANIC | MOB_HUMANOID + move_resist = MOVE_FORCE_STRONG + footstep_type = FOOTSTEP_MOB_SHOE + sentience_type = SENTIENCE_OTHER a_intent = INTENT_HARM stat_attack = UNCONSCIOUS - unsuitable_atmos_damage = 15 - faction = list("syndicate") + status_flags = 0 check_friendly_fire = TRUE - status_flags = CANPUSH - loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) - del_on_death = TRUE - sentience_type = SENTIENCE_OTHER - footstep_type = FOOTSTEP_MOB_SHOE robust_searching = TRUE + turns_per_move = 5 + speed = 0 + maxHealth = 200 + health = 200 + unsuitable_atmos_damage = 2 // 4 actually + damage_coeff = list(BRUTE = 0.9, BURN = 0.9, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) // Imitates our armor + melee_damage_lower = 30 + melee_damage_upper = 30 + armour_penetration_percentage = 50 + loot = list( + /obj/effect/decal/cleanable/blood/innards, + /obj/effect/decal/cleanable/blood, + /obj/effect/gibspawner/generic, + /obj/effect/gibspawner/generic, + ) + // Bitflags! + var/syndie_flags = 0 + // What do we perform melee attacks with + var/melee_type = MELEE_WEAPON_ESWORD + // What do we perform ranged attacks with + var/ranged_type + // Corpse we spawn on death() + var/corpse = /obj/effect/mob_spawn/human/corpse/syndicate + // Weapon icon overlay we add when we have a target to attack + var/weapon + // Idle icon of our weapon (See elite mob with SR for example) + var/weapon_idle + // Overlay for our swat mask/armor booster visor + var/visor = VISOR_MASK + // %Chance to reflect an energy projectile. Used alongside `MELEE_WEAPON_ESWORD` only + var/reflect_chance = 10 + // %Chance to deflect a melee hit. Used alongside `MELEE_WEAPON_DSWORD` only + var/deflect_chance = 15 + // %Chance to fully block a hit + var/parry_chance = 10 + // Icon we display on melee attack/parry + var/attack_icon + // For how long we do nothing + var/idle_cycle = 0 + // Should we apply bloody mask? Used in AttackingTarget(), contains target's blood color + var/bloody + // For how long we have been under emergency effect? + var/emergency_cycle = 0 + // Color of our blade + var/sword_color + // Colors for our blade + var/list/static/colormap = list( + 1 = LIGHT_COLOR_GREEN, + 2 = LIGHT_COLOR_RED, + 3 = LIGHT_COLOR_LIGHTBLUE, + 4 = LIGHT_COLOR_PURPLE, + ) + COOLDOWN_DECLARE(emergency_heal_cooldown) + COOLDOWN_DECLARE(emote_react) /mob/living/simple_animal/hostile/syndicate/Initialize(mapload) . = ..() - if(prob(50)) - loot |= /obj/item/salvage/loot/syndicate + if(syndie_flags & MODSUIT) + death_sound = SOUND_MOD + update_icon(UPDATE_OVERLAYS) + if(loot) // Prevents us from adding loot if there is none yet + if(prob(50)) + loot |= /obj/item/salvage/loot/syndicate + loot |= corpse + +/mob/living/simple_animal/hostile/syndicate/proc/apply_blood() + var/list/static/bloody_parts + if(syndie_flags & MODSUIT) + bloody_parts = list( + BLOOD_HELMET, + BLOOD_ARMOR, + BLOOD_HANDS, + BLOOD_SHOES, + ) + else + bloody_parts = list( + BLOOD_MASK, + BLOOD_HELMET, + BLOOD_SUIT, + BLOOD_HANDS, + BLOOD_SHOES, + ) + + for(var/bloody_part in bloody_parts) + var/mutable_appearance/bloodsies = mutable_appearance('icons/effects/blood.dmi', icon_state = bloody_part) + bloodsies.color = bloody + add_overlay(bloodsies) + + // Other overlays should be always above blood + cut_overlay(weapon) + cut_overlay(weapon_idle) + cut_overlay("eshield") + + update_icon(UPDATE_OVERLAYS) + +/mob/living/simple_animal/hostile/syndicate/proc/apply_visor() + if(!(syndie_flags & MODSUIT) || syndie_flags & ARMOR_BOOSTER) + cut_overlay("[visor]-off") + add_overlay(visor) + else if(syndie_flags & MODSUIT && !(syndie_flags & ARMOR_BOOSTER)) + cut_overlay(visor) + add_overlay("[visor]-off") + +/mob/living/simple_animal/hostile/syndicate/proc/apply_weapon() + if(!attack_icon) + if(melee_type == MELEE_WEAPON_NONE) + attack_icon = MELEE_WEAPON_NONE + else + sword_color = rand(1,4) + attack_icon = "[melee_type][sword_color]" + + if(target) + if(weapon_idle) + cut_overlay(weapon_idle) + if(ranged) + if(!weapon) + weapon = ranged_type + add_overlay(weapon) + else + if(melee_type != MELEE_WEAPON_NONE) + if(!weapon) + weapon = "[sword_color][melee_type]" + add_overlay(weapon) + if(sword_color) + set_light(2, l_color = colormap[sword_color]) + if(!(syndie_flags & SWORD)) + syndie_flags |= SWORD + else + if(sword_color) + set_light(0) + if(weapon) + cut_overlay(weapon) + if(weapon_idle) + add_overlay(weapon_idle) + if(syndie_flags & SWORD) + syndie_flags &= ~SWORD + +/mob/living/simple_animal/hostile/syndicate/proc/apply_eshield() + if(syndie_flags & ESHIELD) + add_overlay("eshield") + +/mob/living/simple_animal/hostile/syndicate/proc/apply_heal(amount, heal_sound) + adjustHealth(-amount) + if(heal_sound) + playsound(src, pick('sound/goonstation/items/mender.ogg', 'sound/goonstation/items/mender2.ogg'), 50, TRUE) + if(health == maxHealth && syndie_flags & HEALING) + syndie_flags &= ~HEALING + idle_cycle = 0 + react_sound() + +/mob/living/simple_animal/hostile/syndicate/proc/emergency_heal() + if(!(syndie_flags & CRITICAL) && COOLDOWN_FINISHED(src, emergency_heal_cooldown)) + syndie_flags |= CRITICAL + COOLDOWN_START(src, emergency_heal_cooldown, 60 SECONDS) + if(syndie_flags & ADRENAL) + move_to_delay = ranged ? 2.5 : 1.8 + if(!ranged) + dodging = FALSE + +/mob/living/simple_animal/hostile/syndicate/proc/react_sound() + if(!COOLDOWN_FINISHED(src, emote_react)) + return + if(prob(round(100-(health/maxHealth*100))*0.25)) + COOLDOWN_START(src, emote_react, 10 SECONDS) + if(syndie_flags & CRITICAL && syndie_flags & ADRENAL) + playsound(src, 'sound/effects/mob_effects/knuckles.ogg', 50, TRUE) + custom_emote(EMOTE_VISIBLE, "cracks its fingers.") + else if(health >= maxHealth*0.75) + custom_emote(EMOTE_VISIBLE, "yawns...") + else if(health >= maxHealth*0.375) + custom_emote(EMOTE_VISIBLE, "sighs.") + else if(health >= maxHealth*0.125) + custom_emote(EMOTE_VISIBLE, "chokes!") + else + custom_emote(EMOTE_VISIBLE, "moans!") + +/mob/living/simple_animal/hostile/syndicate/proc/jedi_spin() + for(var/i in list(NORTH, SOUTH, EAST, WEST, EAST, SOUTH, NORTH, SOUTH, EAST, WEST, EAST, SOUTH)) + setDir(i) + if(i == WEST) + SpinAnimation(7, 1) + sleep(1) + +/mob/living/simple_animal/hostile/syndicate/update_overlays() + . = ..() + apply_visor() + apply_eshield() + apply_weapon() + +/mob/living/simple_animal/hostile/syndicate/handle_environment(datum/gas_mixture/readonly_environment) + . = ..() + var/pressure = readonly_environment.return_pressure() + var/enough_pressure = FALSE + if(pressure > HAZARD_LOW_PRESSURE && pressure < HAZARD_HIGH_PRESSURE) + enough_pressure = TRUE + if(syndie_flags & MODSUIT) + if(!enough_pressure && syndie_flags & ARMOR_BOOSTER) + syndie_flags &= ~ARMOR_BOOSTER + damage_coeff[BRUTE] += 0.2 + damage_coeff[BURN] += 0.1 + playsound(src, SOUND_MOD, 25, TRUE) + apply_visor() + else if(enough_pressure && !(syndie_flags & ARMOR_BOOSTER)) + syndie_flags |= ARMOR_BOOSTER + damage_coeff[BRUTE] -= 0.2 + damage_coeff[BURN] -= 0.1 + playsound(src, SOUND_MOD, 25, TRUE) + apply_visor() + else if(!enough_pressure) + adjustHealth(unsuitable_atmos_damage) + +/mob/living/simple_animal/hostile/syndicate/ListTargetsLazy() + // The normal ListTargetsLazy ignores walls, which is very bad. So we override it. + return ListTargets() + +/mob/living/simple_animal/hostile/syndicate/AIShouldSleep(list/possible_targets) + FindTarget(possible_targets, TRUE) + return FALSE /mob/living/simple_animal/hostile/syndicate/Aggro() . = ..() if(target) - playsound(loc, 'sound/misc/for_the_syndicate.ogg', 70, TRUE) + playsound(src, 'sound/misc/for_the_syndicate.ogg', 70, TRUE) + if(melee_type != MELEE_WEAPON_NONE && !(syndie_flags & SWORD)) + playsound(src, 'sound/weapons/saberon.ogg', 35, TRUE) + update_icon(UPDATE_OVERLAYS) -///////////////Sword and shield//////////// +/mob/living/simple_animal/hostile/syndicate/AttackingTarget() + if(ranged) + if(ranged_cooldown <= world.time) + OpenFire(target) + return + . = ..() + if(.) + if(!ranged && !bloody && ishuman(target) && melee_damage_upper && prob(25)) + var/mob/living/carbon/human/victim = target + bloody = victim.dna.species.blood_color + apply_blood() + if(melee_type == MELEE_WEAPON_DSWORD && prob(50)) + jedi_spin() -/mob/living/simple_animal/hostile/syndicate/melee - melee_damage_lower = 25 - melee_damage_upper = 30 - icon_state = "syndicate_sword" - icon_living = "syndicate_sword" - attacktext = "slashes" - attack_sound = 'sound/weapons/blade1.ogg' - armour_penetration_percentage = 40 - armour_penetration_flat = 10 - status_flags = 0 - var/melee_block_chance = 20 - var/ranged_block_chance = 35 +/mob/living/simple_animal/hostile/syndicate/Shoot(atom/targeted_atom) + if(QDELETED(targeted_atom) || targeted_atom == targets_from.loc || targeted_atom == targets_from) + return + var/turf/startloc = get_turf(targets_from) + var/turf/target_turf = get_turf(targeted_atom) + if(!target_turf) + return + if(casingtype) + // I know that is ABSOLUTELY terrible way to do that, but.. i don't know how to make it properly. I wasted a lot of time trying to, but only this is working somewhat good enough. + var/dx = abs(target_turf.x - startloc.x) + var/dy = abs(target_turf.y - startloc.y) + if(target_turf.x < startloc.x && target_turf.y > startloc.y) + if(dy > dx) + target_turf.pixel_x = 14 + target_turf.pixel_y = 14 + else if(dy < dx) + target_turf.pixel_x = -14 + target_turf.pixel_y = -14 + else if(target_turf.x < startloc.x && target_turf.y < startloc.y) + if(dy > dx) + target_turf.pixel_x = 14 + target_turf.pixel_y = -14 + else if(dy < dx) + target_turf.pixel_x = -14 + target_turf.pixel_y = 14 + else if(target_turf.x > startloc.x && target_turf.y > startloc.y) + if(dy > dx) + target_turf.pixel_x = -14 + target_turf.pixel_y = 14 + else if(dy < dx) + target_turf.pixel_x = 14 + target_turf.pixel_y = -14 + else if(target_turf.x > startloc.x && target_turf.y < startloc.y) + if(dy > dx) + target_turf.pixel_x = -14 + target_turf.pixel_y = -14 + else if(dy < dx) + target_turf.pixel_x = 14 + target_turf.pixel_y = 14 + var/obj/item/ammo_casing/casing = new casingtype(startloc) + playsound(src, projectilesound, 100, 1) + casing.fire(targeted_atom, src, zone_override = ran_zone(), firer_source_atom = src) + target_turf.pixel_x = initial(target_turf.pixel_x) + target_turf.pixel_y = initial(target_turf.pixel_y) -/mob/living/simple_animal/hostile/syndicate/melee/attack_by(obj/item/O, mob/living/user, params) - if(prob(melee_block_chance)) - visible_message("[src] blocks [O] with its shield!") +/mob/living/simple_animal/hostile/syndicate/LoseTarget() + . = ..() + if(syndie_flags & SWORD && melee_type != MELEE_WEAPON_NONE) + playsound(src, 'sound/weapons/saberoff.ogg', 35, TRUE) + update_icon(UPDATE_OVERLAYS) + +/mob/living/simple_animal/hostile/syndicate/Life(seconds, times_fired) + . = ..() + if(stat != DEAD) + if(syndie_flags & CRITICAL) + emergency_cycle++ + apply_heal(syndie_flags & ADRENAL ? 2 : 1) // Second breath + if(emergency_cycle >= 15) + syndie_flags &= ~CRITICAL + emergency_cycle = 0 + if(syndie_flags & ADRENAL) + move_to_delay = initial(move_to_delay) + if(!ranged) + dodging = TRUE + if(!target && maxHealth > health && !(syndie_flags & HEALING)) + if(idle_cycle >= 15) + syndie_flags |= HEALING + react_sound() + else + idle_cycle++ + + else if(target) + if(syndie_flags & HEALING) + syndie_flags &= ~HEALING + if(idle_cycle > 0) + idle_cycle = 0 + + else if(syndie_flags & HEALING) + var/datum/callback/cb = CALLBACK(src, PROC_REF(apply_heal), 8, TRUE) + var/delay = SSnpcpool.wait / 2 + for(var/i in 1 to 2) + addtimer(cb, (i - 1)*delay) + +/mob/living/simple_animal/hostile/syndicate/adjustHealth(damage, updating_health = TRUE) + . = ..() + if(damage > 0) + if(prob(round(100-(health/maxHealth*100))) && health <= maxHealth*0.25) + emergency_heal() + if(syndie_flags & HEALING) + syndie_flags &= ~HEALING + if(idle_cycle > 0) + idle_cycle = 0 + if(health < maxHealth*0.4) + react_sound() + +// Huge copypaste starts. Any ideas on how to shrink it down? +/mob/living/simple_animal/hostile/syndicate/do_attack_animation(atom/A, visual_effect_icon, used_item = attack_icon, no_effect) + if(!no_effect && (visual_effect_icon || used_item)) + do_item_attack_animation(A, visual_effect_icon, used_item) + + if(A == src) + return + var/pixel_x_diff = 0 + var/pixel_y_diff = 0 + var/turn_dir = 1 + + var/direction = get_dir(src, A) + if(direction & NORTH) + pixel_y_diff = 8 + turn_dir = prob(50) ? -1 : 1 + else if(direction & SOUTH) + pixel_y_diff = -8 + turn_dir = prob(50) ? -1 : 1 + + if(direction & EAST) + pixel_x_diff = 8 + else if(direction & WEST) + pixel_x_diff = -8 + turn_dir = -1 + + var/matrix/initial_transform = matrix(transform) + var/matrix/rotated_transform = transform.Turn(5 * turn_dir) + animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform = rotated_transform, time = 0.1 SECONDS, easing = CUBIC_EASING) + animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform = initial_transform, time = 0.2 SECONDS, easing = SINE_EASING) + +/mob/living/simple_animal/hostile/syndicate/do_item_attack_animation(atom/A, visual_effect_icon, used_item) + var/image/I + if(visual_effect_icon) + I = image('icons/effects/effects.dmi', A, visual_effect_icon, A.layer + 0.1) + else if(used_item) + I = image(icon, A, used_item, A.layer + 0.1) + I.plane = GAME_PLANE + + I.transform *= 0.75 + I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + + var/direction = get_dir(src, A) + if(direction & NORTH) + I.pixel_y = -16 + else if(direction & SOUTH) + I.pixel_y = 16 + + if(direction & EAST) + I.pixel_x = -16 + else if(direction & WEST) + I.pixel_x = 16 + + if(!direction) + I.pixel_z = 16 + + if(!I) + return + + var/list/viewing = list() + for(var/mob/M in viewers(A)) + if(M.client && M.client.prefs.toggles2 & PREFTOGGLE_2_ITEMATTACK) + viewing |= M.client + + I.appearance_flags |= RESET_TRANSFORM | KEEP_APART + flick_overlay(I, viewing, 7) + + var/t_color = "#ffffff" + if(ismob(src) && ismob(A) && !used_item) + var/mob/M = src + t_color = M.a_intent == INTENT_HARM ? "#ff0000" : "#ffffff" + animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 0.3 SECONDS, color = t_color) + animate(time = 0.1 SECONDS) + animate(alpha = 0, time = 0.3 SECONDS, easing = CIRCULAR_EASING | EASE_OUT) +// Huge copypaste ends + +/mob/living/simple_animal/hostile/syndicate/attack_hand(mob/living/user) + if(melee_type == MELEE_WEAPON_DSWORD && prob(deflect_chance)) + visible_message("[src] deflects [user]'s punch with its double-bladed sword!") + do_attack_animation(src) + user.changeNext_move(CLICK_CD_MELEE) + user.attack_animal(src) + playsound(src, 'sound/weapons/parry.ogg', clamp(maxHealth-health, 40, 120)) + return FINISH_ATTACK + + if(prob(parry_chance)) + visible_message("[src] parries [user]!") + do_attack_animation(src) user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src) + playsound(src, 'sound/weapons/parry.ogg', clamp(maxHealth-health, 40, 120)) return FINISH_ATTACK return ..() -/mob/living/simple_animal/hostile/syndicate/melee/bullet_act(obj/item/projectile/Proj) +/mob/living/simple_animal/hostile/syndicate/attack_by(obj/item/O, mob/living/user, params) + if(melee_type == MELEE_WEAPON_DSWORD && prob(deflect_chance)) + visible_message("[src] deflects [O] with its double-bladed sword!") + do_attack_animation(src) + user.changeNext_move(CLICK_CD_MELEE) + user.attack_animal(src) + playsound(src, 'sound/weapons/parry.ogg', clamp(maxHealth-health, 40, 120)) + return FINISH_ATTACK + + if(prob(parry_chance)) + visible_message("[src] parries [O]!") + do_attack_animation(src) + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src) + playsound(src, 'sound/weapons/parry.ogg', clamp(maxHealth-health, 40, 120)) + return FINISH_ATTACK + + return ..() + +/mob/living/simple_animal/hostile/syndicate/bullet_act(obj/item/projectile/Proj) if(!Proj) return - if(prob(ranged_block_chance)) - visible_message("[src] blocks [Proj] with its shield!") + if(((melee_type == MELEE_WEAPON_DSWORD || syndie_flags & ESHIELD) || (melee_type == MELEE_WEAPON_ESWORD && prob(reflect_chance))) && Proj.is_reflectable(REFLECTABILITY_ENERGY)) + if(melee_type == MELEE_WEAPON_ESWORD) + do_attack_animation(src) + playsound(src, 'sound/weapons/effects/ric3.ogg', clamp(maxHealth-health, 40, 120), TRUE) + Proj.reflect_back(src) + visible_message("[src] reflects [Proj] with its [syndie_flags & ESHIELD ? "shield" : "sword"]!") + return -1 + + if(melee_type != MELEE_WEAPON_NONE && prob(parry_chance)) + do_attack_animation(src) + visible_message("[src] parries [Proj]!") + playsound(src, 'sound/weapons/parry.ogg', clamp(maxHealth-health, 40, 120)) return return ..() -/mob/living/simple_animal/hostile/syndicate/melee/autogib - loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier, - /obj/item/salvage/loot/syndicate, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) +////////////////////////////// +// MARK: ESHIELD +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/shield + syndie_flags = ESHIELD -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot - name = "Syndicate Operative" - force_threshold = 6 // Prevents people using punches to bypass eshield - robust_searching = TRUE // Together with stat_attack, ensures dionae/etc that regen are killed properly - universal_speak = TRUE - icon_state = "syndicate_swordonly" - icon_living = "syndicate_swordonly" - melee_block_chance = 0 - ranged_block_chance = 0 - del_on_death = TRUE +////////////////////////////// +// MARK: RANGED +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/ranged + melee_type = MELEE_WEAPON_NONE + ranged = TRUE + ranged_type = RANGED_WEAPON_C20R + projectilesound = SOUND_SMG + casingtype = /obj/item/ammo_casing/c45/nostamina + rapid = 2 + retreat_distance = 5 + minimum_distance = 5 + parry_chance = 20 + +////////////////////////////// +// MARK: MODSUIT +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/modsuit + name = "Syndicate Commando" + damage_coeff = list(BRUTE = 0.7, BURN = 0.9, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) + maxbodytemp = FIRE_SUIT_MAX_TEMP_PROTECT + minbodytemp = 0 + icon_state = RAIDER + icon_living = RAIDER + visor = VISOR_RAIDER + syndie_flags = MODSUIT + reflect_chance = 15 + parry_chance = 15 + corpse = /obj/effect/mob_spawn/human/corpse/syndicate/modsuit + var/eshield_prob = 15 // Chance to be spawned with an eshield + +/mob/living/simple_animal/hostile/syndicate/modsuit/Initialize(mapload) + if(prob(eshield_prob)) + syndie_flags |= ESHIELD + . = ..() + +/mob/living/simple_animal/hostile/syndicate/modsuit/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) + return TRUE + +////////////////////////////// +// MARK: MODSUIT RANGED +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/modsuit/ranged + melee_type = MELEE_WEAPON_NONE + ranged = TRUE + ranged_type = RANGED_WEAPON_C20R + projectilesound = SOUND_SMG + casingtype = /obj/item/ammo_casing/c45/nostamina + rapid = 3 + retreat_distance = 5 + minimum_distance = 5 + parry_chance = 20 + +////////////////////////////// +// MARK: ELITE MODSUIT +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/modsuit/elite + name = "Syndicate Overseer" + damage_coeff = list(BRUTE = 0.6, BURN = 0.6, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) + maxbodytemp = FIRE_IMMUNITY_MAX_TEMP_PROTECT + icon_state = JAEGER + icon_living = JAEGER + visor = VISOR_JAEGER + syndie_flags = MODSUIT | ADRENAL + eshield_prob = 0 + melee_type = MELEE_WEAPON_DSWORD + melee_damage_lower = 34 + melee_damage_upper = 34 + parry_chance = 30 + corpse = /obj/effect/mob_spawn/human/corpse/syndicate/modsuit/elite + +/mob/living/simple_animal/hostile/syndicate/modsuit/elite/Initialize(mapload) + if(prob(50)) + melee_type = MELEE_WEAPON_NONE + ranged = TRUE + ranged_type = RANGED_WEAPON_SR + weapon_idle = RANGED_WEAPON_SR_IDLE + projectilesound = SOUND_SR + casingtype = /obj/item/ammo_casing/penetrator + retreat_distance = 2 + minimum_distance = 2 + . = ..() + +////////////////////////////// +// MARK: DEPOT +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/depot var/area/syndicate_depot/core/depotarea - var/raised_alert = FALSE - var/alert_on_death = FALSE + var/raised_alert + var/alert_on_death var/alert_on_timeout = TRUE var/alert_on_spacing = TRUE - var/alert_on_shield_breach = FALSE - var/seen_enemy = FALSE - var/seen_enemy_name = null - var/seen_revived_enemy = FALSE + var/alert_on_shield_breach + var/seen_enemy + var/seen_enemy_name + var/seen_revived_enemy var/aggro_cycles = 0 var/scan_cycles = 0 - var/shield_key = FALSE + var/shield_key var/turf/spawn_turf -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/Initialize(mapload) +/mob/living/simple_animal/hostile/syndicate/depot/Initialize(mapload) . = ..() - name = "[name] [pick(GLOB.last_names)]" depotarea = get_area(src) spawn_turf = get_turf(src) -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/ListTargetsLazy() - // The normal ListTargetsLazy ignores walls, which is very bad in the case of depot mobs. So we override it. - return ListTargets() - -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/Aggro() +/mob/living/simple_animal/hostile/syndicate/depot/Aggro() . = ..() if(!istype(depotarea)) return if(target) if(!seen_enemy) seen_enemy = TRUE - if(!ranged) - playsound(loc, 'sound/weapons/saberon.ogg', 35, TRUE) if(alert_on_shield_breach) if(length(depotarea.shield_list)) raise_alert("[name] reports that [target] is trying to breach the armory shield!") @@ -154,7 +673,7 @@ // This prevents someone from aggroing a depot mob, then hiding in a locker, perfectly safe, while the mob stands there getting killed by their friends. LoseTarget() -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/handle_automated_action() +/mob/living/simple_animal/hostile/syndicate/depot/handle_automated_action() . = ..() if(!.) return @@ -191,17 +710,13 @@ else scan_cycles++ -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/AIShouldSleep(list/possible_targets) - FindTarget(possible_targets, TRUE) - return FALSE - -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/proc/raise_alert(reason) +/mob/living/simple_animal/hostile/syndicate/depot/proc/raise_alert(reason) if(istype(depotarea) && (!raised_alert || seen_revived_enemy) && !depotarea.used_self_destruct) raised_alert = TRUE say("Intruder!") depotarea.increase_alert(reason) -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/drop_loot() +/mob/living/simple_animal/hostile/syndicate/depot/drop_loot() // If a depot syndicate dies after the depot has been destroyed, assume it // was gibbed as part of the destruction and don't drop its loot. if(istype(depotarea) && depotarea.destroyed) @@ -209,7 +724,7 @@ return ..() -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/death() +/mob/living/simple_animal/hostile/syndicate/depot/death() if(!istype(depotarea)) return ..() if(alert_on_death) @@ -224,162 +739,129 @@ new /obj/effect/gibspawner/human(get_turf(src)) return ..() -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/CanPass(atom/movable/mover, border_dir) +/mob/living/simple_animal/hostile/syndicate/depot/CanPass(atom/movable/mover, border_dir) if(isliving(mover)) var/mob/living/blocker = mover if(faction_check_mob(blocker)) - return 1 + return TRUE return ..() -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer - name = "Syndicate Officer" - icon_state = "syndicate_sword" - icon_living = "syndicate_sword" - melee_block_chance = 20 - ranged_block_chance = 35 - alert_on_death = TRUE - -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer/Initialize(mapload) - . = ..() - if(prob(50)) - // 50% chance of switching to ranged variant. - attacktext = "punches" - attack_sound = 'sound/weapons/cqchit1.ogg' - ranged = TRUE - rapid = 3 - retreat_distance = 5 - minimum_distance = 3 - ranged_block_chance = 0 - icon_state = "syndicate_pistol" - icon_living = "syndicate_pistol" - projectiletype = /obj/item/projectile/bullet/armourpiercing - projectilesound = 'sound/weapons/gunshots/gunshot_pistol.ogg' - -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory - name = "Syndicate Quartermaster" - icon_state = "syndicate_stormtrooper_sword" - icon_living = "syndicate_stormtrooper_sword" - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - armour_penetration_percentage = 50 // same as e-sword +////////////////////////////// +// MARK: DEPOT MODSUIT +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/depot/modsuit + name = "Syndicate Commando" + damage_coeff = list(BRUTE = 0.7, BURN = 0.9, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) + maxbodytemp = FIRE_SUIT_MAX_TEMP_PROTECT minbodytemp = 0 - maxHealth = 250 - health = 250 - melee_block_chance = 40 - ranged_block_chance = 35 // same as officer's - alert_on_shield_breach = TRUE - loot = list(/obj/effect/mob_spawn/human/corpse/syndicatequartermaster, /obj/effect/decal/cleanable/blood/innards, /obj/effect/decal/cleanable/blood, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic) + icon_state = RAIDER + icon_living = RAIDER + visor = VISOR_RAIDER + syndie_flags = MODSUIT + reflect_chance = 15 + parry_chance = 15 + corpse = /obj/effect/mob_spawn/human/corpse/syndicate/modsuit + var/eshield_prob = 75 // Chance to be spawned with an eshield -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) - return TRUE // he should be able to chase us in space - -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/Initialize(mapload) +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/Initialize(mapload) + if(prob(eshield_prob)) + syndie_flags |= ESHIELD . = ..() - if(prob(50)) - // 50% chance of switching to extremely dangerous ranged variant - attacktext = "punches" - attack_sound = 'sound/weapons/cqchit1.ogg' - ranged = TRUE - retreat_distance = 2 - minimum_distance = 2 - ranged_block_chance = 0 - icon_state = "syndicate_stormtrooper_shotgun" - icon_living = "syndicate_stormtrooper_shotgun" - speed = 2 - projectiletype = /obj/item/projectile/bullet/sniper/penetrator // Ignores cover. - projectilesound = 'sound/weapons/gunshots/gunshot_sniper.ogg' - loot |= /obj/item/salvage/loot/syndicate - return INITIALIZE_HINT_LATELOAD -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/LateInitialize() - if(istype(depotarea)) - var/list/key_candidates = list() - for(var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer/O in GLOB.alive_mob_list) - key_candidates += O - if(length(key_candidates)) - var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer/O = pick(key_candidates) - O.shield_key = TRUE - depotarea.shields_up() +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) + return TRUE -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/death() // i hope it's all right - if(!istype(depotarea)) - return ..() - if(!length(depotarea.shield_list)) // not opening lockers without getting shields down - depotarea.unlock_lockers() - return ..() - -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space - name = "Syndicate Backup" - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - icon_state = "syndicate_space_sword" - icon_living = "syndicate_space_sword" - speed = 1 +////////////////////////////// +// MARK: DEPOT BACKUP +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/backup wander = FALSE alert_on_spacing = FALSE // So it chasing players in space doesn't make depot explode. alert_on_timeout = FALSE // So random fauna doesn't make depot explode. + corpse = null loot = list() // Explodes, doesn't drop loot. -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) - return TRUE - -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space/death() +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/backup/death() visible_message("[src] explodes!") - playsound(loc, 'sound/items/timer.ogg', 30, FALSE) + playsound(src, 'sound/items/timer.ogg', 30, FALSE) explosion(src, 0, 4, 4, flame_range = 2, adminlog = FALSE, cause = "[name] autogib") qdel(src) -/mob/living/simple_animal/hostile/syndicate/melee/space - name = "Syndicate Commando" - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - icon_state = "syndicate_space_sword" - icon_living = "syndicate_space_sword" - speed = 1.5 - death_sound = 'sound/mecha/mechmove03.ogg' - loot = list(/obj/effect/mob_spawn/human/corpse/syndicatecommando, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) +////////////////////////////// +// MARK: DEPOT OFFICER +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/depot/officer + name = "Syndicate Officer" + syndie_flags = ESHIELD + alert_on_death = TRUE + parry_chance = 20 -/mob/living/simple_animal/hostile/syndicate/melee/space/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) - return TRUE +/mob/living/simple_animal/hostile/syndicate/depot/officer/Initialize(mapload) + if(prob(50)) + // 50% chance of switching to ranged variant. + melee_type = MELEE_WEAPON_NONE + ranged = TRUE + ranged_type = RANGED_WEAPON_M90 + projectilesound = SOUND_AR + casingtype = /obj/item/ammo_casing/a556 + rapid = 3 + retreat_distance = 5 + minimum_distance = 3 + . = ..() -/mob/living/simple_animal/hostile/syndicate/ranged - ranged = TRUE - rapid = 2 - retreat_distance = 5 - minimum_distance = 5 - icon_state = "syndicate_smg" - icon_living = "syndicate_smg" - projectilesound = 'sound/weapons/gunshots/gunshot.ogg' - casingtype = /obj/item/ammo_casing/c45 +////////////////////////////// +// MARK: DEPOT QM +////////////////////////////// +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/elite + name = "Syndicate Quartermaster" + damage_coeff = list(BRUTE = 0.6, BURN = 0.6, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) + maxbodytemp = FIRE_IMMUNITY_MAX_TEMP_PROTECT + icon_state = JAEGER + icon_living = JAEGER + visor = VISOR_JAEGER + alert_on_shield_breach = TRUE + syndie_flags = MODSUIT | ADRENAL + eshield_prob = 0 + melee_type = MELEE_WEAPON_DSWORD + melee_damage_lower = 34 + melee_damage_upper = 34 + parry_chance = 30 + corpse = /obj/effect/mob_spawn/human/corpse/syndicate/modsuit/elite/depot -/mob/living/simple_animal/hostile/syndicate/ranged/space - icon_state = "syndicate_space_smg" - icon_living = "syndicate_space_smg" - name = "Syndicate Commando" - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - speed = 1.5 - death_sound = 'sound/mecha/mechmove03.ogg' - loot = list(/obj/effect/mob_spawn/human/corpse/syndicatecommando, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/elite/Initialize(mapload) + if(prob(50)) + // 50% chance of switching to ranged variant. + melee_type = MELEE_WEAPON_NONE + ranged = TRUE + ranged_type = RANGED_WEAPON_SR + weapon_idle = RANGED_WEAPON_SR_IDLE + projectilesound = SOUND_SR + casingtype = /obj/item/ammo_casing/penetrator // Ignores cover. + retreat_distance = 2 + minimum_distance = 2 + . = ..() + return INITIALIZE_HINT_LATELOAD -/mob/living/simple_animal/hostile/syndicate/ranged/space/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) - return TRUE +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/elite/LateInitialize() + if(istype(depotarea)) + var/list/key_candidates = list() + for(var/mob/living/simple_animal/hostile/syndicate/depot/officer/O in GLOB.alive_mob_list) + key_candidates += O + if(length(key_candidates)) + var/mob/living/simple_animal/hostile/syndicate/depot/officer/O = pick(key_candidates) + O.shield_key = TRUE + depotarea.shields_up() -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib - loot = list(/obj/item/salvage/loot/syndicate, - /obj/effect/mob_spawn/human/corpse/syndicatecommando, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) +/mob/living/simple_animal/hostile/syndicate/depot/modsuit/elite/death() + if(!istype(depotarea)) + return ..() + if(!length(depotarea.shield_list)) // Not opening lockers without getting shields down + depotarea.unlock_lockers() + return ..() +////////////////////////////// +// MARK: VISCERATOR +////////////////////////////// /mob/living/simple_animal/hostile/viscerator name = "viscerator" desc = "A small, twin-bladed machine capable of inflicting very deadly lacerations." @@ -396,7 +878,7 @@ melee_damage_upper = 15 attacktext = "cuts" attack_sound = 'sound/weapons/bladeslice.ogg' - faction = list("syndicate") + faction = list(SYNDICATE) atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 mob_size = MOB_SIZE_TINY @@ -409,3 +891,41 @@ /mob/living/simple_animal/hostile/viscerator/Initialize(mapload) . = ..() AddComponent(/datum/component/swarming) + +#undef BLOOD_HELMET +#undef BLOOD_MASK +#undef BLOOD_ARMOR +#undef BLOOD_SUIT +#undef BLOOD_HANDS +#undef BLOOD_SHOES + +#undef MELEE_WEAPON_NONE +#undef MELEE_WEAPON_ESWORD +#undef MELEE_WEAPON_DSWORD + +#undef RANGED_WEAPON_PISTOL +#undef RANGED_WEAPON_C20R +#undef RANGED_WEAPON_M90 +#undef RANGED_WEAPON_SR +#undef RANGED_WEAPON_SR_IDLE + +#undef SOUND_MOD +#undef SOUND_SMG +#undef SOUND_AR +#undef SOUND_SR + +#undef SYNDICATE +#undef RAIDER +#undef JAEGER + +#undef VISOR_MASK +#undef VISOR_RAIDER +#undef VISOR_JAEGER + +#undef ESHIELD +#undef SWORD +#undef MODSUIT +#undef ARMOR_BOOSTER +#undef HEALING +#undef CRITICAL +#undef ADRENAL diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm index c7b7099a357..5d535f3c519 100644 --- a/code/modules/mod/mod_types.dm +++ b/code/modules/mod/mod_types.dm @@ -270,8 +270,7 @@ /obj/item/mod/control/pre_equipped/traitor/Initialize(mapload) . = ..() - new /obj/item/clothing/mask/gas/syndicate(bag) - new /obj/item/tank/internals/emergency_oxygen/engi/syndi(bag) + new /obj/item/storage/box/survival_syndie/traitor(bag) /obj/item/mod/control/pre_equipped/traitor_elite starting_frequency = MODLINK_FREQ_SYNDICATE @@ -292,8 +291,7 @@ /obj/item/mod/control/pre_equipped/traitor_elite/Initialize(mapload) . = ..() - new /obj/item/clothing/mask/gas/syndicate(bag) - new /obj/item/tank/internals/emergency_oxygen/engi/syndi(bag) + new /obj/item/storage/box/survival_syndie/traitor(bag) /obj/item/mod/control/pre_equipped/nuclear starting_frequency = MODLINK_FREQ_SYNDICATE diff --git a/code/modules/pda/pdas.dm b/code/modules/pda/pdas.dm index 05e1be0b5d2..7bb4aea2527 100644 --- a/code/modules/pda/pdas.dm +++ b/code/modules/pda/pdas.dm @@ -147,7 +147,12 @@ ..() var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) if(M) - M.m_hidden = 1 + M.m_hidden = TRUE + +/obj/item/pda/syndicate_fake + icon_state = "pda-syndi" + name = "Military PDA" + default_pen = /obj/item/pen/multi/syndicate /obj/item/pda/chaplain icon_state = "pda-chaplain" diff --git a/code/modules/procedural_mapping/mapGenerators/syndicate_mapgen.dm b/code/modules/procedural_mapping/mapGenerators/syndicate_mapgen.dm index a29ea754436..f1cf72d2d96 100644 --- a/code/modules/procedural_mapping/mapGenerators/syndicate_mapgen.dm +++ b/code/modules/procedural_mapping/mapGenerators/syndicate_mapgen.dm @@ -17,8 +17,7 @@ /datum/map_generator_module/splatter_layer/syndie_mobs clusterCheckFlags = MAP_GENERATOR_CLUSTER_CHECK_SAME_ATOMS - spawnableAtoms = list(/mob/living/simple_animal/hostile/syndicate = 30, \ - /mob/living/simple_animal/hostile/syndicate/melee = 20, \ + spawnableAtoms = list(/mob/living/simple_animal/hostile/syndicate = 50, \ /mob/living/simple_animal/hostile/syndicate/ranged = 20, \ /mob/living/simple_animal/hostile/viscerator = 30) spawnableTurfs = list() diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm index b8adad970ed..07c6378ed2a 100644 --- a/code/modules/projectiles/ammunition/ammo_casings.dm +++ b/code/modules/projectiles/ammunition/ammo_casings.dm @@ -138,7 +138,7 @@ muzzle_flash_range = MUZZLE_FLASH_RANGE_NORMAL /obj/item/ammo_casing/c45/nostamina - projectile_type = /obj/item/projectile/bullet/midbullet3 + projectile_type = /obj/item/projectile/bullet/weakbullet3 /obj/item/ammo_casing/n762 name = "7.62x38mmR round" diff --git a/icons/effects/spawner_icons.dmi b/icons/effects/spawner_icons.dmi index 9ba31a537ca..91f4b0fde68 100644 Binary files a/icons/effects/spawner_icons.dmi and b/icons/effects/spawner_icons.dmi differ diff --git a/icons/mob/simple_human.dmi b/icons/mob/simple_human.dmi index 30a715e13cd..4b7bfccbe49 100644 Binary files a/icons/mob/simple_human.dmi and b/icons/mob/simple_human.dmi differ diff --git a/icons/obj/boxes.dmi b/icons/obj/boxes.dmi index e0c018cb6d6..502423c891a 100644 Binary files a/icons/obj/boxes.dmi and b/icons/obj/boxes.dmi differ diff --git a/tools/UpdatePaths/Scripts/28706_syndicate_mobs.txt b/tools/UpdatePaths/Scripts/28706_syndicate_mobs.txt new file mode 100644 index 00000000000..d20cb3f967e --- /dev/null +++ b/tools/UpdatePaths/Scripts/28706_syndicate_mobs.txt @@ -0,0 +1,14 @@ +/obj/item/storage/box/survival_syndi : /obj/item/storage/box/survival_syndie{@OLD} +/mob/living/simple_animal/hostile/syndicate/melee : /mob/living/simple_animal/hostile/syndicate{@OLD} +/mob/living/simple_animal/hostile/syndicate/melee/autogib : /mob/living/simple_animal/hostile/syndicate{@OLD} +/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot : /mob/living/simple_animal/hostile/syndicate/depot{@OLD} +/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer : /mob/living/simple_animal/hostile/syndicate/depot/officer{@OLD} +/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory : /mob/living/simple_animal/hostile/syndicate/depot/modsuit/elite{@OLD} +/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space : /mob/living/simple_animal/hostile/syndicate/depot/modsuit/backup +/mob/living/simple_animal/hostile/syndicate/melee/space : /mob/living/simple_animal/hostile/syndicate/modsuit{@OLD} +/mob/living/simple_animal/hostile/syndicate/ranged/space/@SUBTYPES : /mob/living/simple_animal/hostile/syndicate/modsuit/ranged{@OLD} +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie : /obj/effect/spawner/random/pool/spaceloot/syndicate/mob/modsuit{@OLD} +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/corpse : /obj/effect/mob_spawn/human/corpse/syndicate/modsuit{@OLD} +/obj/effect/mob_spawn/human/corpse/syndicatesoldier : /obj/effect/mob_spawn/human/corpse/syndicate{@OLD} +/obj/effect/mob_spawn/human/corpse/syndicatecommando : /obj/effect/mob_spawn/human/corpse/syndicate/modsuit{@OLD} +/obj/effect/mob_spawn/human/corpse/syndicatequartermaster : /obj/effect/mob_spawn/human/corpse/syndicate/modsuit/elite{@OLD}