diff --git a/_maps/barrenquilla_mining.json b/_maps/barrenquilla_mining.json index f472088ea7f..dca325610c0 100644 --- a/_maps/barrenquilla_mining.json +++ b/_maps/barrenquilla_mining.json @@ -2,7 +2,7 @@ "map_name": "Barrenquilla Mining Facility", "map_path": "map_files/Barrenquilla_Mining", "map_file": "Barrenquilla_Mining_Facility.dmm", - "announce_text": "A faint distress signal has been picked up by our scanners, which have tracked the source to LO145. Through use of emergency bluespace drive tech, the ###SHIPNAME### has jumped within range of the outpost. Senior officers are present and will need to be evacuated in order to completely finish your mission. TGMC, gear up and get ready to respond!", + "announce_text": "Наши сканеры зафиксировали слабый сигнал бедствия, который привёл нас к LO145. Благодаря блюспейс технологиям, мы оказались рядом с аванпостом. Товарищи, приготовьтесь к битве!", "disk_sets": { "basic": 1 }, diff --git a/_maps/bigred_v2.json b/_maps/bigred_v2.json index 3c34c0a9785..ed27a991c71 100644 --- a/_maps/bigred_v2.json +++ b/_maps/bigred_v2.json @@ -6,7 +6,7 @@ "basic": 1 }, "quickbuilds": 1800, - "announce_text": "A second generation colony has had a beacon transmitting the same signal, nonstop. Attempts to hail the colony over comms have proved futile. Because the ship was at a nearby drydock, it has been dispatched to figure out what's wrong. TGMC, prepare to deploy!", + "announce_text": "На колонии 2-ого поколения был активирован аварийный маяк, безостановочно передающий один и тот же сигнал. Попытки связаться оказались тщетными. Поскольку ваш корабль находился в близлежащих доках, вас отправляют выяснить, что за чертовщина там творится. Товарищи, приготовиться к высадке!", "traits":[{ "weather_sandstorm": true }] diff --git a/_maps/deltastation.json b/_maps/deltastation.json index e4f037c72bb..9225035c56e 100644 --- a/_maps/deltastation.json +++ b/_maps/deltastation.json @@ -5,6 +5,6 @@ "disk_sets": { "basic": 1 }, - "announce_text": "The ship's comms array detected an emergency evacuation signal from a Delta class research station owned by a private corporation. The message indicated that the station had collided with a large asteroid and was overrun with hostile lifeforms. As part of peacekeeping operations the ship is nearing the station to begin clearing operations. TGMC, get equipped and prepare for boarding action!", + "announce_text": "Корабельная система связи засекла сигнал о срочной эвакуации с исследовательской станции класса «Дельта», принадлежащей частной корпорации 'Вейланд-Ютани'. В сообщении говорилось, что станция столкнулась с крупным астероидом и захвачена враждебными формами жизни. В рамках миротворческих операций корабль приближается к станции, чтобы начать очистку. Товарищи, экипируйтесь и приготовьтесь к высадке!", "armor": "prison" } diff --git a/_maps/desparity.json b/_maps/desparity.json index 8dc84f0238b..de42c1a48db 100644 --- a/_maps/desparity.json +++ b/_maps/desparity.json @@ -6,7 +6,7 @@ "basic": 1 }, "armor": "jungle", - "announce_text": "An emergency broadcast has been picked up by our scanners, triangulated to a jungle outpost near LV624, known as Desparity. Through use of bluespace drive tech, the ship has jumped within range of the colony. TGMC, gear up and get ready to respond!", + "announce_text": "Наши сканеры засекли экстренное сообщение, которое было триангулировано на аванпосте в джунглях возле LV624, известном как Деспарити. Товарищи, снаряжайтесь и готовьтесь к высадке!", "traits":[{ "weather_acidrain": false }] diff --git a/_maps/gelida_iv.json b/_maps/gelida_iv.json index 8d026a70860..a38651f2671 100644 --- a/_maps/gelida_iv.json +++ b/_maps/gelida_iv.json @@ -10,7 +10,7 @@ }, "armor": "ice", "quickbuilds": 1600, - "announce_text": "Our comms array has detected an automated emergency signal broadcasting over a frequency reserved for the highest level of emergencies. The message was traced to the northern reaches of the research colony Gelida IV. The ship is moving into the sector with thrusters at max throttle. TGMC, get briefed and then move out!", + "announce_text": "Наша система связи засекла автоматический аварийный сигнал, передаваемый на частоте, предназначенной для чрезвычайных ситуаций уровня биологических заражений. Сообщение было отслежено до северных районов исследовательской колонии Гелида IV. Корабль движется в сектор на максимальном ходу. Товарищи, пройдите инструктаж и выдвигайтесь!", "traits":[{ "weather_snowstorm": true }] diff --git a/_maps/ice_colony_v2.json b/_maps/ice_colony_v2.json index 110cac8134c..75dfe818586 100644 --- a/_maps/ice_colony_v2.json +++ b/_maps/ice_colony_v2.json @@ -10,7 +10,7 @@ }, "armor": "ice", "quickbuilds": 1600, - "announce_text": "A garbled, unintelligible communications message was broadcasted over a general frequency, and picked up by our comms relay. The message appears to have come from a second generation settlement, located on an ice cold planet. The ship is moving into the sector with thrusters at max throttle. TGMC, get briefed and then move out!", + "announce_text": "На общей частоте было передано запутанное, неразборчивое сообщение, которое принял наш ретранслятор. Судя по всему, сообщение пришло из поселения второго поколения, расположенного на ледяной планете. Корабль движется в сектор на максимальном ходу. Товарищи, пройдите инструктаж и выдвигайтесь!", "traits":[{ "weather_snowstorm": true }] diff --git a/_maps/icy_caves.json b/_maps/icy_caves.json index 5625b3abfe6..545fb5ae61a 100644 --- a/_maps/icy_caves.json +++ b/_maps/icy_caves.json @@ -10,7 +10,7 @@ }, "armor": "ice", "quickbuilds": 1200, - "announce_text": "A garbled, unintelligible communications message was broadcasted over a general frequency, and picked up by our comms relay. The message appears to have come from a mining outpost, located on an ice cold planet. The ship is moving into the sector with thrusters at max throttle. TGMC, get briefed and then move out!", + "announce_text": "На общей частоте было передано запутанное, неразборчивое сообщение, которое принял наш ретранслятор. Судя по всему, сообщение поступило с шахтерского форпоста, расположенного на ледяной планете. Корабль движется в сектор на максимальном ходу. Товарищи, пройдите инструктаж и выдвигайтесь!", "traits":[{ "weather_snowstorm": true }] diff --git a/_maps/kutjevo.json b/_maps/kutjevo.json index 153ec6279a2..764a44fe7b1 100644 --- a/_maps/kutjevo.json +++ b/_maps/kutjevo.json @@ -6,5 +6,5 @@ "basic": 1 }, "quickbuilds": 1800, - "announce_text": "An automated distress signal has been received from Nanotrasen colony Kutjevo Refinery, known for botanical research, export, and raw materials processing and refinement. The ###SHIPNAME### has been dispatched to investigate." + "announce_text": "С нефтеперерабатывающего завода колонии НаноТрейзен в Кутьево, известного своими ботаническими исследованиями, экспортом и переработкой сырья, был получен автоматический сигнал бедствия. Для расследования было отправлено наше судно." } diff --git a/_maps/last_stand.json b/_maps/last_stand.json index 430fe6cc852..65899b0ef61 100644 --- a/_maps/last_stand.json +++ b/_maps/last_stand.json @@ -2,5 +2,5 @@ "map_name": "Last Stand", "map_path": "map_files/Last_Stand", "map_file": "Last_Stand.dmm", - "announce_text": "A faint distress signal has been picked up by our scanners, which have tracked the source to Batallion 140's Supreme Command Center. Through use of emergency bluespace drive tech, the ship has jumped within range of the outpost. Senior officers are present and will need to be evacuated in order to completely finish your mission. TGMC, gear up and get ready to respond!" + "announce_text": "Наши сканеры засекли слабый сигнал бедствия и отследили его источник до Высшего командного центра батальона 140. Используя блюспейс технологии, корабль прыгнул в пределы досягаемости аванпоста. Там находятся старшие офицеры, которых необходимо эвакуировать, чтобы полностью завершить вашу миссию. Товарищи, снарядитесь и приготовьтесь к высадке!" } diff --git a/_maps/lawanka.json b/_maps/lawanka.json index 223f6f20ebb..a9f8659c8f9 100644 --- a/_maps/lawanka.json +++ b/_maps/lawanka.json @@ -6,5 +6,5 @@ "basic": 1 }, "quickbuilds": 1800, - "announce_text": "An AI from a Nanotrasen sponsored Research Colony has been sending a distress signal, nonstop. Nanotrasen has hired us to reclaim the Colony in any form. TGMC, prepare to deploy!" + "announce_text": "ИИ из исследовательской колонии, спонсируемой НаноТрейзен, безостановочно посылает сигнал бедствия. Нанотрайзен нанял нас, чтобы мы вернули колонию в любом виде. Товарищи, приготовиться к высадке!" } diff --git a/_maps/lv624.json b/_maps/lv624.json index ca8505f21b3..4d1715717ea 100644 --- a/_maps/lv624.json +++ b/_maps/lv624.json @@ -7,7 +7,7 @@ }, "armor": "jungle", "quickbuilds": 1400, - "announce_text": "A faint distress signal has been picked up by our scanners, which have tracked the source to a third generation colony, known as LV-624. Through use of bluespace drive tech, the ship has jumped within range of the colony. TGMC, gear up and get ready to respond!", + "announce_text": "Наши сканеры засекли слабый сигнал бедствия и определили, что его источником является колония третьего поколения, известная как LV-624. Используя блюспейс технологии, корабль прыгнул в зону досягаемости колонии. Товарищи, экипируйтесь и приготовьтесь к атаке!", "traits":[{ "weather_acidrain": true }] diff --git a/_maps/magmoor_digsite_iv.json b/_maps/magmoor_digsite_iv.json index 0a531926dbd..625284d3172 100644 --- a/_maps/magmoor_digsite_iv.json +++ b/_maps/magmoor_digsite_iv.json @@ -6,5 +6,5 @@ "basic": 1 }, "quickbuilds": 1800, - "announce_text": "A faint distress signal has been picked up by our scanners, which have tracked the source to a mining and archaeological site, known as Magmoor Digsite IV. Through use of bluespace drive tech, the ship has jumped within range of the colony. TGMC, gear up and get ready to respond!" + "announce_text": "Наши сканеры засекли слабый сигнал бедствия и определили, что его источник находится в месте добычи полезных ископаемых и археологических раскопок, известном как Точка Раскопок Магмура IV. Используя блюспейс технологии, корабль прыгнул в зону досягаемости колонии. Товарищи, приготовьтесь к высадке!" } diff --git a/_maps/map_files/Talos/TGS_Talos.dmm b/_maps/map_files/Talos/TGS_Talos.dmm index 5d05be20f9f..a2cab25d1ee 100644 --- a/_maps/map_files/Talos/TGS_Talos.dmm +++ b/_maps/map_files/Talos/TGS_Talos.dmm @@ -326,12 +326,12 @@ /area/mainship/hallways/port_hallway) "ahQ" = ( /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/wood, /area/mainship/living/bridgebunks) @@ -399,8 +399,8 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/siding/metal, /obj/structure/sign/semiotic/cryo{ - pixel_y = -32; - pixel_x = 8 + pixel_x = 8; + pixel_y = -32 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/port_hallway) @@ -516,9 +516,9 @@ "anQ" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -551,8 +551,8 @@ dir = 4 }, /obj/structure/sign/semiotic/storage{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /obj/effect/turf_decal/warning_stripes/fulltile, /turf/open/floor/mainship/metal/full, @@ -587,9 +587,9 @@ "aoA" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -759,9 +759,9 @@ "arx" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -1091,8 +1091,8 @@ /obj/structure/table/fancywoodentable, /obj/item/radio/intercom/general, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/item/flashlight/lamp, /turf/open/floor/wood, @@ -1185,8 +1185,8 @@ dir = 1 }, /obj/structure/sign/semiotic/storage{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/mainship/metal/full, /area/mainship/engineering/engineering_workshop) @@ -1355,8 +1355,8 @@ /area/mainship/hallways/bow_hallway) "aEs" = ( /obj/structure/sign/semiotic/high_voltage{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/effect/turf_decal/siding/metal{ dir = 9 @@ -1383,8 +1383,8 @@ "aEC" = ( /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/plating, /area/mainship/hull/port_hull) @@ -1562,9 +1562,9 @@ "aLe" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -1675,8 +1675,8 @@ "aQS" = ( /obj/machinery/vending/coffee, /obj/structure/sign/semiotic/coffee{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal, /area/mainship/squads/bravo) @@ -1900,8 +1900,8 @@ /area/mainship/living/cafeteria) "bca" = ( /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /turf/open/floor/wood, /area/mainship/living/pilotbunks) @@ -1940,8 +1940,8 @@ /obj/machinery/disposal, /obj/structure/disposalpipe/trunk, /obj/structure/sign/semiotic/bathwomens{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/starboard_emb) @@ -2068,9 +2068,9 @@ "bhE" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -2517,8 +2517,8 @@ "buA" = ( /obj/machinery/vending/marineFood, /obj/structure/sign/semiotic/food_storage{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/wood, /area/mainship/medical/surgery_hallway) @@ -2650,12 +2650,12 @@ "byf" = ( /obj/structure/table/black, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/orange/full, /area/mainship/command/cic) @@ -2737,12 +2737,12 @@ "bAn" = ( /obj/structure/table/black, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/red/full, /area/mainship/command/cic) @@ -2858,9 +2858,9 @@ "bFB" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -3004,8 +3004,8 @@ "bIW" = ( /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/plating, /area/mainship/hull/starboard_hull) @@ -3098,9 +3098,9 @@ "bLZ" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -3732,9 +3732,9 @@ "cdc" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -3805,8 +3805,8 @@ /area/mainship/hallways/starboard_hallway) "ceH" = ( /obj/structure/sign/semiotic/north{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /obj/structure/sign/semiotic/landingzone{ pixel_x = -17; @@ -3917,8 +3917,8 @@ dir = 1 }, /obj/structure/sign/semiotic/east{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/structure/sign/semiotic/high_voltage{ pixel_y = 24 @@ -3928,9 +3928,9 @@ "chQ" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -4085,8 +4085,8 @@ /area/mainship/living/pilotbunks) "clZ" = ( /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /obj/structure/sink/bathroom, /turf/open/floor/plating/plating_catwalk/dark, @@ -4284,9 +4284,9 @@ "csB" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -4479,9 +4479,9 @@ "cyW" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -4647,12 +4647,12 @@ dir = 1 }, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/bow_hallway) @@ -4772,13 +4772,17 @@ /area/mainship/squads/alpha) "cHf" = ( /obj/machinery/vending/uniform_supply, +/obj/machinery/keycard_auth{ + dir = 8; + pixel_x = 30 + }, /turf/open/floor/wood, /area/mainship/living/pilotbunks) "cHi" = ( /obj/machinery/vending/marineFood, /obj/structure/sign/semiotic/food_storage{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/wood, /area/mainship/medical/upper_medical) @@ -5011,9 +5015,9 @@ "cQd" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -5396,8 +5400,8 @@ pixel_y = -25 }, /obj/structure/sign/semiotic/escapepod{ - pixel_y = -25; - pixel_x = 15 + pixel_x = 15; + pixel_y = -25 }, /obj/effect/turf_decal/siding/metal, /turf/open/floor/mainship/metal, @@ -6058,9 +6062,9 @@ "dvE" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -6274,8 +6278,8 @@ "dCu" = ( /obj/effect/turf_decal/siding/metal, /obj/structure/sign/semiotic/high_voltage{ - pixel_y = -25; - pixel_x = 15 + pixel_x = 15; + pixel_y = -25 }, /obj/structure/sign/semiotic/electronics{ pixel_y = -25 @@ -6649,6 +6653,9 @@ /area/mainship/living/basketball) "dNS" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer1/alt, +/obj/machinery/keycard_auth{ + pixel_y = 30 + }, /turf/open/floor/wood, /area/mainship/command/corporateliaison) "dNU" = ( @@ -6680,6 +6687,12 @@ }, /turf/open/floor/prison/cleanmarked, /area/mainship/hallways/hangar/droppod) +"dOs" = ( +/obj/machinery/keycard_auth{ + pixel_y = 30 + }, +/turf/open/floor/mainship/tcomms, +/area/mainship/command/telecomms) "dOt" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3{ dir = 1 @@ -7077,8 +7090,8 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer1/alt{ dir = 4 @@ -7209,8 +7222,8 @@ /obj/structure/cable, /obj/item/radio/intercom/general{ dir = 1; - pixel_y = -19; - pixel_x = -8 + pixel_x = -8; + pixel_y = -19 }, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/hallways/hangar) @@ -7551,9 +7564,9 @@ "eqT" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -7603,8 +7616,8 @@ }, /obj/structure/sink/bathroom, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/bravo) @@ -7727,8 +7740,8 @@ "ewv" = ( /obj/structure/sink/bathroom, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /obj/machinery/light/mainship{ dir = 4 @@ -7774,8 +7787,8 @@ dir = 1 }, /obj/structure/sign/semiotic/east{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/structure/sign/semiotic/high_voltage{ pixel_y = 24 @@ -7986,9 +7999,9 @@ "eEt" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -8146,8 +8159,8 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden/layer1{ dir = 9 @@ -8475,16 +8488,16 @@ "eRD" = ( /obj/item/radio/intercom/general{ dir = 1; - pixel_y = -19; - pixel_x = -8 + pixel_x = -8; + pixel_y = -19 }, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/hallways/hangar) "eRE" = ( /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/plating, /area/mainship/hull/upper_hull) @@ -8543,9 +8556,9 @@ "eUa" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -8569,8 +8582,8 @@ /area/mainship/hallways/hangar) "eUl" = ( /obj/machinery/door/airlock/multi_tile/mainship/blackgeneric/glass{ - name = "\improper Pilot's Office"; dir = 2; + name = "\improper Pilot's Office"; req_one_access = list(44) }, /obj/structure/cable, @@ -8648,9 +8661,9 @@ "eVY" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -8749,12 +8762,12 @@ "eYL" = ( /obj/machinery/computer/cryopod, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/structure/sign/semiotic/terminal{ pixel_x = 32 @@ -8943,8 +8956,8 @@ dir = 4 }, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/alpha) @@ -9059,8 +9072,8 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/alpha) @@ -9183,8 +9196,8 @@ /area/mainship/hallways/port_hallway) "fjo" = ( /obj/structure/sign/semiotic/storage{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/mainship/metal/full, /area/mainship/command/cic) @@ -9327,8 +9340,8 @@ "foF" = ( /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/plating, /area/mainship/hull/port_hull) @@ -9367,6 +9380,9 @@ /obj/effect/turf_decal/woodsiding{ dir = 10 }, +/obj/machinery/keycard_auth{ + pixel_x = -30 + }, /turf/open/floor/carpet, /area/mainship/living/numbertwobunks) "fpE" = ( @@ -9660,9 +9676,9 @@ "fxC" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -9857,8 +9873,8 @@ "fEc" = ( /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal/green, /area/mainship/medical/upper_medical) @@ -9880,8 +9896,8 @@ /obj/structure/sink/bathroom, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/alt, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/alpha) @@ -10046,8 +10062,8 @@ pixel_y = -17 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/cafeteria) @@ -10229,8 +10245,8 @@ dir = 1 }, /obj/structure/sign/semiotic/escapepod{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/structure/sign/semiotic/west{ pixel_y = 24 @@ -10351,8 +10367,8 @@ /area/mainship/hull/port_hull) "fVX" = ( /obj/structure/sign/semiotic/food_storage{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /obj/machinery/vending/snack, /turf/open/floor/mainship/metal, @@ -10360,9 +10376,9 @@ "fWu" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -10653,9 +10669,9 @@ "glD" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -12318,8 +12334,8 @@ "htq" = ( /obj/structure/sink/bathroom, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/delta) @@ -12406,8 +12422,8 @@ /obj/structure/sink/bathroom, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/alt, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/bravo) @@ -12418,6 +12434,7 @@ /obj/structure/sign/semiotic/medical{ pixel_x = 32 }, +/obj/machinery/recharger, /turf/open/floor/mainship/metal/green, /area/mainship/medical/upper_medical) "hwU" = ( @@ -12434,8 +12451,8 @@ /obj/structure/largecrate/supply/supplies/mre, /obj/effect/turf_decal/warning_stripes/cargo, /obj/structure/sign/semiotic/water{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/hangar) @@ -12654,8 +12671,8 @@ pixel_y = 24 }, /obj/structure/sign/semiotic/escapepod{ - pixel_y = 39; - pixel_x = 15 + pixel_x = 15; + pixel_y = 39 }, /obj/structure/sign/semiotic/west{ pixel_y = 31 @@ -12795,8 +12812,8 @@ "hIQ" = ( /obj/machinery/vending/marineFood, /obj/structure/sign/semiotic/food_storage{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/charlie) @@ -12923,12 +12940,12 @@ dir = 5 }, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/carpet, /area/mainship/command/corporateliaison) @@ -13031,8 +13048,8 @@ pixel_y = 6 }, /obj/item/toy/prize/phazon{ - pixel_y = 14; - pixel_x = 11 + pixel_x = 11; + pixel_y = 14 }, /turf/open/floor/plating, /area/mainship/hull/starboard_hull) @@ -13925,13 +13942,13 @@ /area/mainship/hallways/hangar) "ixd" = ( /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/effect/landmark/start/latejoin_squad/alpha, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/squads/alpha) @@ -14129,8 +14146,8 @@ pixel_y = 32 }, /obj/structure/sign/semiotic/ref_chem_storage{ - pixel_y = 32; - pixel_x = -14 + pixel_x = -14; + pixel_y = 32 }, /turf/open/floor/mainship/metal/green, /area/mainship/medical/lounge) @@ -14218,8 +14235,8 @@ dir = 1 }, /obj/structure/sign/semiotic/fire_haz{ - pixel_y = 32; - pixel_x = -18 + pixel_x = -18; + pixel_y = 32 }, /turf/open/floor/mainship/metal/green, /area/mainship/medical/lounge) @@ -14639,9 +14656,9 @@ "iSG" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -14702,8 +14719,8 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /obj/machinery/light/mainship{ dir = 4 @@ -14873,8 +14890,8 @@ "jag" = ( /obj/machinery/vending/snack, /obj/structure/sign/semiotic/food_storage{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal, /area/mainship/command/cic) @@ -14896,9 +14913,9 @@ "jap" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -15089,8 +15106,8 @@ }, /obj/effect/landmark/start/latejoin_squad/bravo, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/squads/bravo) @@ -15184,8 +15201,8 @@ "jiX" = ( /obj/machinery/vending/coffee, /obj/structure/sign/semiotic/coffee{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal, /area/mainship/squads/delta) @@ -15466,8 +15483,8 @@ dir = 4 }, /obj/structure/sign/semiotic/north{ - pixel_y = 7; - pixel_x = 32 + pixel_x = 32; + pixel_y = 7 }, /obj/structure/sign/semiotic/bridge{ pixel_x = 32; @@ -15560,12 +15577,12 @@ }, /obj/machinery/camera/autoname, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/alt, /turf/open/floor/mainship/metal, @@ -15614,8 +15631,8 @@ dir = 1 }, /obj/structure/sign/semiotic/east{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/structure/sign/semiotic/high_voltage{ pixel_y = 24 @@ -15631,13 +15648,13 @@ /area/mainship/medical/surgery_hallway) "jwO" = ( /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/bed/chair/comfy/alpha, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/red/full, /area/mainship/hallways/hangar) @@ -16058,8 +16075,8 @@ /area/mainship/hallways/aft_hallway) "jMS" = ( /obj/structure/sign/semiotic/coffee{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /obj/machinery/vending/coffee, /turf/open/floor/mainship/metal, @@ -16486,8 +16503,8 @@ }, /obj/effect/turf_decal/warning_stripes/fulltile, /obj/structure/sign/semiotic/north{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /obj/structure/sign/semiotic/escapepod{ pixel_x = -17; @@ -16660,8 +16677,8 @@ /area/mainship/hallways/starboard_umbilical) "kgK" = ( /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /obj/structure/sink/bathroom, /turf/open/floor/plating/plating_catwalk/dark, @@ -16710,9 +16727,9 @@ "khT" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -16979,11 +16996,12 @@ /turf/open/floor/mainship/metal/full, /area/mainship/hallways/bow_hallway) "koH" = ( +/obj/machinery/floor_warn_light/self_destruct, /obj/item/defibrillator, /obj/item/defibrillator, /obj/item/defibrillator, /obj/structure/table/mainship, -/obj/machinery/floor_warn_light/self_destruct, +/obj/machinery/recharger, /turf/open/floor/mainship/metal/green, /area/mainship/medical/lounge) "kpR" = ( @@ -17001,8 +17019,8 @@ /area/mainship/hallways/port_hallway) "kqo" = ( /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/hallways/hangar) @@ -17547,8 +17565,8 @@ "kHo" = ( /obj/machinery/vending/marineFood, /obj/structure/sign/semiotic/food_storage{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal/full, /area/mainship/hallways/aft_hallway) @@ -17627,8 +17645,8 @@ "kJi" = ( /obj/item/radio/intercom/general{ dir = 1; - pixel_y = -19; - pixel_x = -8 + pixel_x = -8; + pixel_y = -19 }, /obj/structure/bed/chair/comfy/delta{ dir = 1 @@ -18057,9 +18075,9 @@ "kUp" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -18105,9 +18123,9 @@ "kVF" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -18158,8 +18176,8 @@ pixel_y = -25 }, /obj/structure/sign/semiotic/escapepod{ - pixel_y = -25; - pixel_x = 15 + pixel_x = 15; + pixel_y = -25 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/starboard_hallway) @@ -18272,8 +18290,8 @@ }, /obj/structure/window/reinforced, /obj/structure/sign/semiotic/galley{ - pixel_y = 29; - pixel_x = 7 + pixel_x = 7; + pixel_y = 29 }, /turf/open/floor/grass, /area/mainship/hallways/aft_hallway) @@ -18600,8 +18618,8 @@ pixel_y = 24 }, /obj/structure/sign/semiotic/escapepod{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/port_hallway) @@ -18713,8 +18731,8 @@ dir = 1 }, /obj/machinery/door/airlock/mainship/generic{ - name = "Kitchen"; - dir = 1 + dir = 1; + name = "Kitchen" }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden/layer1, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ @@ -18780,8 +18798,8 @@ /obj/effect/decal/cleanable/dirt, /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/plating, /area/mainship/hull/upper_hull) @@ -18837,8 +18855,8 @@ }, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer1/alt, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = 32 + pixel_x = 32; + pixel_y = 7 }, /turf/open/floor/wood, /area/mainship/squads/charlie) @@ -18851,8 +18869,8 @@ /obj/effect/decal/cleanable/cobweb, /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/plating, /area/mainship/hull/upper_hull) @@ -18891,8 +18909,8 @@ /area/mainship/engineering/port_atmos) "lsJ" = ( /obj/structure/sign/semiotic/food_storage{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /obj/machinery/vending/cigarette, /turf/open/floor/mainship/metal, @@ -18964,8 +18982,8 @@ dir = 1 }, /obj/structure/sign/semiotic/water{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/plating, /area/mainship/hull/upper_hull) @@ -19089,9 +19107,9 @@ "lvY" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -19228,8 +19246,8 @@ dir = 4 }, /obj/structure/sign/semiotic/north{ - pixel_y = 7; - pixel_x = 32 + pixel_x = 32; + pixel_y = 7 }, /obj/structure/sign/semiotic/bridge{ pixel_x = 32; @@ -19265,9 +19283,9 @@ /area/mainship/squads/alpha) "lzz" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /obj/effect/turf_decal/siding/metal{ dir = 8 @@ -19307,8 +19325,8 @@ pixel_y = 8 }, /obj/structure/sign/semiotic/flightcontrol{ - pixel_y = 8; - pixel_x = -18 + pixel_x = -18; + pixel_y = 8 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/bow_hallway) @@ -19425,9 +19443,9 @@ "lEC" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -19442,12 +19460,12 @@ "lEO" = ( /obj/structure/bedsheetbin, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/metal, /area/mainship/squads/delta) @@ -19822,9 +19840,9 @@ /area/mainship/hallways/hangar/droppod) "lNm" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /turf/open/floor/stairs/dark/right, /area/mainship/hull/port_hull) @@ -20108,8 +20126,8 @@ pixel_y = -25 }, /obj/structure/sign/semiotic/escapepod{ - pixel_y = -25; - pixel_x = 15 + pixel_x = 15; + pixel_y = -25 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/port_hallway) @@ -20350,8 +20368,8 @@ dir = 4 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/item/radio/intercom/general, /turf/open/floor/mainship/metal, @@ -20396,12 +20414,12 @@ "mgh" = ( /obj/effect/turf_decal/warning_stripes/cargo/yellow, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/metal, /area/mainship/squads/charlie) @@ -20610,8 +20628,8 @@ }, /obj/structure/cable, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/hallways/hangar) @@ -20644,6 +20662,10 @@ dir = 8 }, /obj/machinery/computer/crew, +/obj/machinery/keycard_auth{ + dir = 8; + pixel_x = 30 + }, /turf/open/floor/wood, /area/mainship/medical/lower_medical) "mpD" = ( @@ -20979,12 +21001,12 @@ /area/mainship/hull/starboard_hull) "mye" = ( /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/tcomms, /area/mainship/command/telecomms) @@ -21004,8 +21026,8 @@ /obj/effect/spawner/random/misc/folder, /obj/item/eftpos{ eftpos_name = "Cargo Bay EFTPOS scanner"; - pixel_y = 1; - pixel_x = 4 + pixel_x = 4; + pixel_y = 1 }, /obj/item/tool/hand_labeler{ pixel_x = -4 @@ -21087,8 +21109,8 @@ pixel_y = -8 }, /obj/structure/sign/semiotic/north{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/aft_hallway) @@ -21266,8 +21288,8 @@ dir = 1 }, /obj/structure/sign/semiotic/high_voltage{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/structure/sign/semiotic/electronics{ pixel_y = 24 @@ -21616,8 +21638,8 @@ "mOq" = ( /obj/machinery/vending/coffee, /obj/structure/sign/semiotic/coffee{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/wood, /area/mainship/medical/surgery_hallway) @@ -22005,9 +22027,9 @@ "mYr" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -22064,8 +22086,8 @@ }, /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/plating, /area/mainship/hull/port_hull) @@ -22232,9 +22254,9 @@ /area/space) "ngt" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /obj/effect/turf_decal/siding/metal{ dir = 4 @@ -22483,9 +22505,9 @@ "nnX" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -22760,8 +22782,8 @@ pixel_y = -17 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /turf/open/floor/mainship/metal/full, /area/mainship/engineering/engineering_workshop) @@ -23148,8 +23170,8 @@ /obj/effect/turf_decal/warning_stripes/cargo/yellow, /obj/item/radio/intercom/general{ dir = 1; - pixel_y = -19; - pixel_x = -8 + pixel_x = -8; + pixel_y = -19 }, /obj/structure/sign/semiotic/intercom{ pixel_y = -25 @@ -23159,9 +23181,9 @@ "nJt" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -23665,9 +23687,9 @@ /area/mainship/hallways/starboard_hallway) "nUR" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /turf/open/floor/stairs/dark/left, /area/mainship/hull/port_hull) @@ -23716,9 +23738,9 @@ "nVN" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -23981,9 +24003,9 @@ /area/mainship/squads/req) "oex" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /obj/machinery/camera/autoname{ dir = 4 @@ -24569,9 +24591,9 @@ "oxS" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -24634,9 +24656,9 @@ "oBC" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -24671,8 +24693,8 @@ dir = 1 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/cafeteria) @@ -24683,8 +24705,8 @@ }, /obj/effect/landmark/start/latejoin_squad/bravo, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = 32 + pixel_x = 32; + pixel_y = 7 }, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/squads/bravo) @@ -24947,12 +24969,12 @@ /area/mainship/squads/req) "oJM" = ( /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/effect/turf_decal/woodsiding{ dir = 5 @@ -24995,9 +25017,6 @@ /obj/item/attachable/suppressor, /obj/item/armor_module/storage/uniform/holster, /obj/item/portable_vendor/corporate, -/obj/machinery/keycard_auth{ - pixel_x = -30 - }, /obj/effect/turf_decal/woodsiding{ dir = 9 }, @@ -25005,13 +25024,13 @@ /area/mainship/command/corporateliaison) "oLY" = ( /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/bed/chair/comfy/bravo, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/orange/full, /area/mainship/hallways/hangar) @@ -25057,8 +25076,8 @@ }, /obj/effect/spawner/random/misc/plant, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = 32 + pixel_x = 32; + pixel_y = 7 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/cafeteria) @@ -25412,8 +25431,8 @@ dir = 4 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /turf/open/floor/carpet, /area/mainship/living/numbertwobunks) @@ -25427,12 +25446,12 @@ "paw" = ( /obj/effect/turf_decal/warning_stripes/cargo/yellow, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/metal, /area/mainship/squads/delta) @@ -25583,12 +25602,12 @@ /area/mainship/living/numbertwobunks) "per" = ( /obj/structure/sign/semiotic/ammunition{ - pixel_y = 1; - pixel_x = -17 + pixel_x = -17; + pixel_y = 1 }, /obj/structure/sign/semiotic/laser{ - pixel_y = 15; - pixel_x = -17 + pixel_x = -17; + pixel_y = 15 }, /obj/effect/turf_decal/siding/dark{ dir = 8 @@ -25691,9 +25710,9 @@ /area/mainship/hallways/bow_hallway) "phy" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /obj/machinery/camera/autoname{ dir = 8 @@ -26016,8 +26035,8 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/charlie) @@ -26110,9 +26129,9 @@ "psl" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -26227,8 +26246,8 @@ dir = 4 }, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/delta) @@ -26241,8 +26260,8 @@ pixel_y = -17 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/cafeteria) @@ -26263,8 +26282,8 @@ /area/mainship/engineering/ce_room) "pvW" = ( /obj/structure/sign/semiotic/south{ - pixel_y = -8; - pixel_x = -17 + pixel_x = -17; + pixel_y = -8 }, /obj/structure/sign/semiotic/landingzone{ pixel_x = -17; @@ -26435,9 +26454,9 @@ "pAq" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -26619,8 +26638,8 @@ "pFV" = ( /obj/machinery/light/mainship, /obj/structure/sign/semiotic/conference_room{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal/lino, /area/mainship/hallways/bow_hallway) @@ -26781,8 +26800,8 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /obj/effect/ai_node, /turf/open/floor/plating/plating_catwalk/dark, @@ -26790,8 +26809,8 @@ "pLD" = ( /obj/machinery/vending/marineFood, /obj/structure/sign/semiotic/food_storage{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/cafeteria) @@ -26804,8 +26823,8 @@ }, /obj/machinery/camera/autoname, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /turf/open/floor/carpet, /area/mainship/living/numbertwobunks) @@ -26828,8 +26847,8 @@ "pMR" = ( /obj/machinery/vending/snack, /obj/structure/sign/semiotic/food_storage{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/alpha) @@ -27008,8 +27027,8 @@ /area/mainship/squads/req) "pQZ" = ( /obj/structure/sign/semiotic/exhaust{ - pixel_y = -21; - pixel_x = -17 + pixel_x = -17; + pixel_y = -21 }, /obj/structure/sign/semiotic/fire_haz{ pixel_x = -17; @@ -27029,9 +27048,9 @@ "pRM" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -27236,8 +27255,8 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/delta) @@ -27281,6 +27300,13 @@ /obj/structure/bedsheetbin, /turf/open/floor/mainship/metal, /area/mainship/squads/alpha) +"qak" = ( +/obj/machinery/keycard_auth{ + dir = 8; + pixel_x = 30 + }, +/turf/open/floor/wood, +/area/mainship/living/commandbunks) "qas" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/simple/cyan/hidden/layer1{ @@ -27303,8 +27329,8 @@ dir = 1 }, /obj/structure/sign/semiotic/cryo{ - pixel_y = 32; - pixel_x = 8 + pixel_x = 8; + pixel_y = 32 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/starboard_hallway) @@ -27552,12 +27578,12 @@ /obj/machinery/disposal, /obj/structure/disposalpipe/trunk, /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/commandbunks) @@ -28025,8 +28051,8 @@ dir = 4 }, /obj/structure/sign/semiotic/water{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/plating, /area/mainship/hull/starboard_hull) @@ -28346,9 +28372,9 @@ "qER" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -28374,9 +28400,9 @@ }, /obj/effect/turf_decal/siding/metal, /obj/machinery/door_control{ + dir = 1; id = "Brig Lockdown"; name = "Brig Lockdown"; - dir = 1; pixel_x = -6; pixel_y = -16 }, @@ -29301,6 +29327,9 @@ /obj/structure/closet/secure_closet/req_officer, /obj/item/whistle, /obj/item/megaphone, +/obj/machinery/keycard_auth{ + pixel_x = -30 + }, /turf/open/floor/carpet, /area/mainship/squads/req) "ril" = ( @@ -29451,9 +29480,6 @@ /turf/open/floor/mainship/metal, /area/mainship/engineering/engineering_workshop) "rpb" = ( -/obj/machinery/keycard_auth{ - pixel_x = -30 - }, /obj/effect/turf_decal/woodsiding{ dir = 4 }, @@ -29480,8 +29506,8 @@ pixel_y = -25 }, /obj/structure/sign/semiotic/escapepod{ - pixel_y = -25; - pixel_x = 15 + pixel_x = 15; + pixel_y = -25 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/starboard_hallway) @@ -29651,8 +29677,8 @@ "rwf" = ( /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/plating, /area/mainship/living/numbertwobunks) @@ -29686,13 +29712,13 @@ /area/mainship/living/grunt_rnr) "rxt" = ( /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/effect/landmark/start/latejoin_squad/charlie, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/squads/charlie) @@ -29718,8 +29744,8 @@ "ryd" = ( /obj/machinery/vending/marineFood, /obj/structure/sign/semiotic/food_storage{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/cafeteria) @@ -30047,8 +30073,8 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer1/alt{ dir = 1 @@ -30122,9 +30148,9 @@ "rIX" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ layer = 3.2 @@ -30827,9 +30853,9 @@ "sfi" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -31292,8 +31318,8 @@ "ssL" = ( /obj/structure/sink/bathroom, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /obj/machinery/light/mainship{ dir = 4 @@ -31401,12 +31427,12 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /obj/item/tool/wet_sign{ - pixel_y = 20; - pixel_x = -6 + pixel_x = -6; + pixel_y = 20 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/bravo) @@ -31963,9 +31989,9 @@ /area/mainship/engineering/port_atmos) "sOW" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /obj/machinery/light/mainship{ dir = 8 @@ -32233,8 +32259,8 @@ pixel_y = 1 }, /obj/structure/sign/semiotic/waterhazard{ - pixel_y = 18; - pixel_x = 32 + pixel_x = 32; + pixel_y = 18 }, /turf/open/floor/prison/whitepurple{ dir = 5 @@ -32245,8 +32271,8 @@ /obj/effect/turf_decal/woodsiding, /obj/item/ashtray/glass, /obj/item/storage/fancy/cigarettes/kpack{ - pixel_y = 10; - pixel_x = 13 + pixel_x = 13; + pixel_y = 10 }, /obj/item/clothing/mask/cigarette, /turf/open/floor/carpet, @@ -32272,9 +32298,9 @@ "sYF" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -33335,9 +33361,9 @@ /area/mainship/living/starboard_garden) "tJx" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /turf/open/floor/stairs/dark/left{ dir = 1 @@ -33352,9 +33378,9 @@ /area/mainship/hull/upper_hull) "tJG" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /obj/machinery/light/mainship{ dir = 4 @@ -33489,9 +33515,9 @@ "tQf" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -33612,8 +33638,8 @@ "tUh" = ( /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/plating, /area/mainship/hull/starboard_hull) @@ -33682,8 +33708,8 @@ "tWw" = ( /obj/item/radio/intercom/general{ dir = 1; - pixel_y = -19; - pixel_x = -8 + pixel_x = -8; + pixel_y = -19 }, /obj/structure/table/black, /obj/structure/sign/semiotic/intercom{ @@ -33700,8 +33726,8 @@ /area/mainship/squads/alpha) "tWH" = ( /obj/structure/sign/semiotic/north{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /obj/structure/sign/semiotic/bridge{ pixel_x = -17; @@ -33756,8 +33782,8 @@ "tYC" = ( /obj/item/radio/intercom/general{ dir = 1; - pixel_y = -19; - pixel_x = -8 + pixel_x = -8; + pixel_y = -19 }, /obj/structure/table/black, /obj/structure/sign/semiotic/intercom{ @@ -33767,8 +33793,8 @@ /area/mainship/command/cic) "tYD" = ( /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /obj/structure/sink/bathroom, /turf/open/floor/plating/plating_catwalk/dark, @@ -34297,8 +34323,8 @@ /area/mainship/squads/alpha) "uou" = ( /obj/structure/largecrate/random/case{ - pixel_y = 5; - pixel_x = 4 + pixel_x = 4; + pixel_y = 5 }, /turf/open/floor/mainship/red, /area/mainship/squads/alpha) @@ -34342,8 +34368,8 @@ /area/mainship/command/cic) "upJ" = ( /obj/structure/sign/semiotic/food_storage{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /obj/machinery/vending/marineFood, /turf/open/floor/mainship/metal, @@ -34381,9 +34407,9 @@ "uqU" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -34700,9 +34726,9 @@ /obj/structure/paper_bin, /obj/item/tool/pen, /obj/machinery/door_control/mainship/cic{ + dir = 8; id = "CIC Checkpoint Shutters"; - name = "CIC Checkpoint Shutters"; - dir = 8 + name = "CIC Checkpoint Shutters" }, /obj/item/tool/pen, /obj/structure/table/black, @@ -34743,8 +34769,8 @@ }, /obj/structure/sink/bathroom, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/charlie) @@ -34878,8 +34904,8 @@ "uGs" = ( /obj/structure/sink/bathroom, /obj/structure/mirror{ - pixel_y = 10; - pixel_x = -1 + pixel_x = -1; + pixel_y = 10 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/bravo) @@ -34924,6 +34950,9 @@ /obj/effect/turf_decal/woodsiding{ dir = 10 }, +/obj/machinery/keycard_auth{ + pixel_x = -30 + }, /turf/open/floor/carpet, /area/mainship/engineering/ce_room) "uIu" = ( @@ -35230,12 +35259,12 @@ "uSa" = ( /obj/structure/table/fancywoodentable, /obj/item/camera_film{ - pixel_y = 3; - pixel_x = -4 + pixel_x = -4; + pixel_y = 3 }, /obj/item/camera{ - pixel_y = 3; - pixel_x = -5 + pixel_x = -5; + pixel_y = 3 }, /obj/item/flashlight/lamp/green{ pixel_x = 7 @@ -35535,8 +35564,8 @@ pixel_y = 24 }, /obj/structure/sign/semiotic/escapepod{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/metal/lino, /area/mainship/hallways/aft_hallway) @@ -35559,8 +35588,8 @@ /area/mainship/hull/upper_hull) "vcY" = ( /obj/machinery/vending/nanomed{ - pixel_y = 4; - pixel_x = -6 + pixel_x = -6; + pixel_y = 4 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/delta) @@ -35645,8 +35674,8 @@ dir = 8 }, /obj/item/toy/plush/moth{ - name = "scared moth plush"; - desc = "A plushie depicting a scared moth. It was trying to eat in peace, but you ruined it!" + desc = "A plushie depicting a scared moth. It was trying to eat in peace, but you ruined it!"; + name = "scared moth plush" }, /turf/open/floor/mainship/tcomms, /area/mainship/command/self_destruct) @@ -36039,8 +36068,8 @@ "vtN" = ( /obj/machinery/vending/marineFood, /obj/structure/sign/semiotic/food_storage{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/req) @@ -36188,8 +36217,8 @@ pixel_y = -25 }, /obj/structure/sign/semiotic/high_voltage{ - pixel_y = -25; - pixel_x = 15 + pixel_x = 15; + pixel_y = -25 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/port_hallway) @@ -36219,8 +36248,8 @@ "vAb" = ( /obj/item/radio/intercom/general{ dir = 1; - pixel_y = -19; - pixel_x = -8 + pixel_x = -8; + pixel_y = -19 }, /obj/structure/bed/chair/comfy/charlie{ dir = 1 @@ -36382,8 +36411,8 @@ dir = 1 }, /obj/structure/mirror{ - pixel_y = -15; - dir = 1 + dir = 1; + pixel_y = -15 }, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer1/alt{ dir = 1 @@ -36432,8 +36461,8 @@ }, /obj/structure/bed/chair/wood, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = -17 + pixel_x = -17; + pixel_y = 7 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/cafeteria) @@ -37041,8 +37070,8 @@ }, /obj/structure/cable, /obj/machinery/door/airlock/multi_tile/mainship/blackgeneric/glass{ - name = "\improper Vehicle Crew Office"; dir = 2; + name = "\improper Vehicle Crew Office"; req_one_access = list(49) }, /obj/machinery/door/firedoor, @@ -37095,8 +37124,8 @@ pixel_y = 24 }, /obj/structure/sign/semiotic/escapepod{ - pixel_y = 39; - pixel_x = 15 + pixel_x = 15; + pixel_y = 39 }, /turf/open/floor/mainship/metal, /area/mainship/hallways/aft_hallway) @@ -37155,6 +37184,13 @@ /obj/structure/cable, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/hallways/hangar) +"wbo" = ( +/obj/structure/table/mainship, +/obj/machinery/recharger, +/turf/open/floor/prison/whitepurple{ + dir = 6 + }, +/area/mainship/medical/medical_science) "wbu" = ( /obj/structure/rack, /obj/effect/spawner/random/misc/table_lighting, @@ -37341,13 +37377,13 @@ /area/mainship/squads/bravo) "whB" = ( /obj/item/radio/intercom/general{ - pixel_y = -20; - pixel_x = -24 + pixel_x = -24; + pixel_y = -20 }, /obj/effect/landmark/start/latejoin_squad/delta, /obj/structure/sign/semiotic/intercom{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/plating/plating_catwalk/dark, /area/mainship/squads/delta) @@ -37579,8 +37615,8 @@ /obj/effect/turf_decal/warning_stripes/cargo/yellow, /obj/item/radio/intercom/general{ dir = 1; - pixel_y = -19; - pixel_x = -8 + pixel_x = -8; + pixel_y = -19 }, /obj/structure/sign/semiotic/intercom{ pixel_y = -25 @@ -37714,8 +37750,8 @@ pixel_y = -25 }, /obj/structure/sign/semiotic/distribution_pipes{ - pixel_y = -25; - pixel_x = 15 + pixel_x = 15; + pixel_y = -25 }, /turf/open/floor/plating, /area/mainship/hull/starboard_hull) @@ -38004,12 +38040,12 @@ dir = 4 }, /obj/structure/sign/semiotic/suit_storage{ - pixel_y = 39; - pixel_x = 15 + pixel_x = 15; + pixel_y = 39 }, /obj/structure/sign/semiotic/distribution_pipes{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /obj/structure/sign/semiotic/electronics{ pixel_y = 24 @@ -38063,9 +38099,9 @@ layer = 3.2 }, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/red{ pixel_y = 13 @@ -38243,9 +38279,9 @@ "wNm" = ( /obj/effect/ai_node, /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /obj/effect/turf_decal/siding/metal{ dir = 6 @@ -38474,9 +38510,9 @@ "wUQ" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/purple{ layer = 3.2 @@ -38558,8 +38594,8 @@ /area/mainship/living/cafeteria) "wXi" = ( /obj/structure/sign/semiotic/exhaust{ - pixel_y = -21; - pixel_x = -17 + pixel_x = -17; + pixel_y = -21 }, /obj/structure/sign/semiotic/fire_haz{ pixel_x = -17; @@ -38616,8 +38652,8 @@ /obj/machinery/light/mainship, /obj/effect/ai_node, /obj/structure/sign/semiotic/east{ - pixel_y = -25; - pixel_x = 15 + pixel_x = 15; + pixel_y = -25 }, /obj/structure/sign/semiotic/high_voltage{ pixel_y = -25 @@ -38758,8 +38794,8 @@ pixel_y = 24 }, /obj/structure/sign/semiotic/ref_bio_storage{ - pixel_y = 24; - pixel_x = 15 + pixel_x = 15; + pixel_y = 24 }, /turf/open/floor/mainship/metal/gray, /area/mainship/medical/surgery_hallway) @@ -38975,8 +39011,8 @@ "xjK" = ( /obj/machinery/light/floor, /obj/structure/sign/semiotic/bathmens{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/mainship/metal/lino, /area/mainship/living/starboard_emb) @@ -39233,8 +39269,8 @@ "xsE" = ( /obj/machinery/vending/marineFood, /obj/structure/sign/semiotic/food_storage{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/alpha) @@ -39395,8 +39431,8 @@ pixel_y = -18 }, /obj/structure/sign/semiotic/intercom{ - pixel_y = 7; - pixel_x = 32 + pixel_x = 32; + pixel_y = 7 }, /turf/open/floor/wood, /area/mainship/squads/alpha) @@ -39536,8 +39572,8 @@ "xBI" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/sign/semiotic/south{ - pixel_y = -8; - pixel_x = -17 + pixel_x = -17; + pixel_y = -8 }, /obj/structure/sign/semiotic/elevator{ pixel_x = -17; @@ -39601,8 +39637,8 @@ }, /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/semiotic/water{ - pixel_y = -25; - pixel_x = 8 + pixel_x = 8; + pixel_y = -25 }, /obj/structure/disposalpipe/segment{ dir = 4 @@ -39971,9 +40007,9 @@ "xNa" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/blue{ layer = 3.2 @@ -40057,9 +40093,9 @@ "xQZ" = ( /obj/structure/bed, /obj/structure/bed{ - pixel_y = 13; layer = 3.5; - max_buckled_mobs = 13 + max_buckled_mobs = 13; + pixel_y = 13 }, /obj/item/bedsheet/yellow{ layer = 3.2 @@ -40200,9 +40236,9 @@ /area/mainship/hull/upper_hull) "xWl" = ( /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /turf/open/floor/stairs/dark/right{ dir = 1 @@ -40329,8 +40365,8 @@ "xZX" = ( /obj/structure/cable, /obj/structure/sign/semiotic/cryo{ - pixel_y = -32; - pixel_x = 8 + pixel_x = 8; + pixel_y = -32 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ dir = 8 @@ -40384,9 +40420,9 @@ "ybg" = ( /obj/effect/ai_node, /obj/structure/window/framed/mainship/hull/canterbury{ - name = "empty space"; + hit_sound = null; invisibility = 100; - hit_sound = null + name = "empty space" }, /obj/effect/turf_decal/siding/metal{ dir = 10 @@ -40412,8 +40448,8 @@ dir = 4 }, /obj/structure/sign/semiotic/coffee{ - pixel_y = 24; - pixel_x = 8 + pixel_x = 8; + pixel_y = 24 }, /turf/open/floor/mainship/metal/full, /area/mainship/squads/charlie) @@ -61115,7 +61151,7 @@ lhv uSU mVy lay -lxr +wbo oYi uHQ lhv @@ -67562,7 +67598,7 @@ pQT pQT pQT pQT -xXP +pdB pdB pdB pdB @@ -68434,7 +68470,7 @@ xzH qQI uNE uJU -qPr +qak toq lSw rEU @@ -69989,7 +70025,7 @@ cEa hjM xzH xPw -vfY +dOs wgv viz rqA diff --git a/_maps/orion_outpost.json b/_maps/orion_outpost.json index 9ee302832db..f5b63c5c375 100644 --- a/_maps/orion_outpost.json +++ b/_maps/orion_outpost.json @@ -7,5 +7,5 @@ }, "armor": "jungle", "quickbuilds": 1000, - "announce_text": "The automatic emergency beacon has activated at the Orion Military Outpost on the moon of Trivonus IV, a xenomorph infestation is likely. TGMC, get prepared and ready for a fight!" + "announce_text": "На военном форпосте Ориона на луне Тривонус IV сработал автоматический аварийный маяк, вероятно нашествие ксеноморфов. Товарищи, приготовиться к бою!" } diff --git a/_maps/oscar_outpost.json b/_maps/oscar_outpost.json index c8adba1b1b1..3616d22b434 100644 --- a/_maps/oscar_outpost.json +++ b/_maps/oscar_outpost.json @@ -2,5 +2,5 @@ "map_name": "Oscar Outpost", "map_path": "map_files/oscar_outpost", "map_file": "oscar_outpost.dmm", - "announce_text": "A faint distress signal has been picked up by our scanners, which have tracked the source to Batallion 167's Supreme Command Center. Through use of emergency bluespace drive tech, the ship has jumped within range of the outpost. Senior officers are present and will need to be evacuated in order to completely finish your mission. TGMC, gear up and get ready to respond!" + "announce_text": "Наши сканеры засекли слабый сигнал бедствия и отследили его источник до Высшего командного центра батальона 167. Используя блюспейс технологии, корабль прыгнул в пределы досягаемости аванпоста. Там находятся старшие офицеры, которых необходимо эвакуировать, чтобы полностью завершить вашу миссию. Товарищи, снарядитесь и приготовьтесь к высадке!" } diff --git a/_maps/prison_station_fop.json b/_maps/prison_station_fop.json index b7e4a741f39..5c770d7395f 100644 --- a/_maps/prison_station_fop.json +++ b/_maps/prison_station_fop.json @@ -7,5 +7,5 @@ }, "armor": "prison", "quickbuilds": 1200, - "announce_text": "A Nanotrasen maximum security prison has activated its distress signal. The ship is swiftly cruising through space, and nearing the vicinity of the prison station. TGMC, get moving!" + "announce_text": "Тюрьма строгого режима НаноТрейзен активировала сигнал бедствия. Корабль стремительно несется по космосу и приближается к тюремной станции. Товарищи, выдвигаемся!" } diff --git a/_maps/research_outpost.json b/_maps/research_outpost.json index 7ef6172481b..f770cda6035 100644 --- a/_maps/research_outpost.json +++ b/_maps/research_outpost.json @@ -6,5 +6,5 @@ "basic": 1 }, "quickbuilds": 1000, - "announce_text": "A research outpost has had a beacon transmitting the same signal, nonstop. Attempts to hail the colony over comms have proved futile. Because the ship was at a nearby drydock, it has been dispatched to figure out what's wrong. TGMC, prepare to deploy!" + "announce_text": "На исследовательском форпосте появился маяк, безостановочно передающий один и тот же сигнал. Попытки связаться с колонией по связи оказались тщетными. Поскольку ваш корабль находился ближе всего, мы отправили вас выяснить в чем дело. Товарищи, приготовиться к высадке!" } diff --git a/_maps/slumbridge.json b/_maps/slumbridge.json index 6228d03ca71..6fa73229dbf 100644 --- a/_maps/slumbridge.json +++ b/_maps/slumbridge.json @@ -6,5 +6,5 @@ "basic": 1 }, "quickbuilds": 2000, - "announce_text": "We've received not one, but four distress signals at once coming from the same location. Ground-penetrating scanners and sensors show an unusual arrangement of a segmented asteroid with artificial gravity online. Not only that, but the four segments look nothing alike. TGMC, prepare for deployment and expect the worst." + "announce_text": "Мы получили не один, а сразу четыре сигнала бедствия из одного и того же места. Наземные сканеры и сенсоры показывают необычное расположение сегментированного астероида с включенной искусственной гравитацией. Мало того, четыре сегмента совершенно не похожи друг на друга. Товарищи, приготовьтесь к высадке и ожидайте худшего." } diff --git a/_maps/vapor_processing.json b/_maps/vapor_processing.json index 0a5a7e531b5..38d75d5c8d1 100644 --- a/_maps/vapor_processing.json +++ b/_maps/vapor_processing.json @@ -5,5 +5,5 @@ "disk_sets": { "basic": 1 }, - "announce_text": "A faint distress signal has been picked up by our scanners, which have tracked the source to a Vapor Processing colony, known as LV-984. Through use of bluespace drive tech, the ship has jumped within range of the colony. TGMC, gear up and get ready to respond!" + "announce_text": "Наши сканеры засекли слабый сигнал бедствия и определили, что его источником является колония по парообработке, известная как LV-984. Используя блюспейс технологии, корабль прыгнул в пределы досягаемости аванпоста. Товарищи, снарядитесь и приготовьтесь к высадке!" } diff --git a/_maps/whiskey_outpost_v2.json b/_maps/whiskey_outpost_v2.json index 5373edafb46..dba854869a0 100644 --- a/_maps/whiskey_outpost_v2.json +++ b/_maps/whiskey_outpost_v2.json @@ -2,5 +2,5 @@ "map_name": "Whiskey Outpost", "map_path": "map_files/Whiskey_Outpost", "map_file": "Whiskey_Outpost_v2.dmm", - "announce_text": "A faint distress signal has been picked up by our scanners, which have tracked the source to Batallion 140's Supreme Command Center. Through use of emergency bluespace drive tech, the ship has jumped within range of the outpost. Senior officers are present and will need to be evacuated in order to completely finish your mission. TGMC, gear up and get ready to respond!" + "announce_text": "Наши сканеры засекли слабый сигнал бедствия и отследили его источник до Высшего командного центра батальона 140. Используя блюспейс технологии, корабль прыгнул в пределы досягаемости колонии. Товарищи, снаряжайтесь и готовьтесь к высадке!" } diff --git a/code/__DEFINES/calibers.dm b/code/__DEFINES/calibers.dm index 24a49d1842b..d8a6479dc75 100644 --- a/code/__DEFINES/calibers.dm +++ b/code/__DEFINES/calibers.dm @@ -19,7 +19,7 @@ #define CALIBER_357 ".357 Magnum" #define CALIBER_454 ".454 Casull" //Mateba #define CALIBER_762X38 "7.62x38mm Rimmed" //UPP -#define CALIBER_12x7 "12.7 Magnum" +#define CALIBER_12X7 "12.7 Magnum" #define CALIBER_44LS ".44 Long Special" #define CALIBER_500 ".500 Nigro Express" @@ -33,8 +33,8 @@ // --- Rifles --- #define CALIBER_10X24_CASELESS "10x24mm caseless" #define CALIBER_10X25_CASELESS "10x25mm caseless" -#define CALIBER_10x27_CASELESS "10x27mm caseless" -#define CALIBER_10x265_CASELESS "10x26.5mm caseless" +#define CALIBER_10X27_CASELESS "10x27mm caseless" +#define CALIBER_10X265_CASELESS "10x26.5mm caseless" #define CALIBER_762X39 "7.62x39mm" #define CALIBER_556X45 "5.56x45mm" #define CALIBER_16G "16 gauge" //Autoshotty, but coded like a rifle so eeh @@ -44,7 +44,7 @@ #define CALIBER_10X28_CASELESS "10x28mm caseless" //Spec scout and OG Smartgun #define CALIBER_762X51 "7.62x51mm" //Minigun #define CALIBER_10X27_INCENDIARY_CASELESS "10x27mm incendiary caseless" -#define CALIBER_10x26_CASELESS "10x26mm caseless" //MG-60 and SG +#define CALIBER_10X26_CASELESS "10x26mm caseless" //MG-60 and SG #define CALIBER_ALIEN "alien alloy" // --- Shotguns --- diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm index 17b451f71fe..95634570355 100644 --- a/code/__DEFINES/cooldowns.dm +++ b/code/__DEFINES/cooldowns.dm @@ -27,6 +27,7 @@ #define COOLDOWN_RACK_BOLT "rack_bolt" #define COOLDOWN_LIGHT "cooldown_light" #define COOLDOWN_JETPACK "jetpack" +#define COOLDOWN_SKILL_ORDERS "skill_orders" #define COOLDOWN_CIC_ORDERS "cic_orders" #define COOLDOWN_HUD_ORDER "hud_order" #define COOLDOWN_CLOAK_IMPLANT "cloak_implant" diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index ca8bfd87804..ec035c4e288 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -802,6 +802,9 @@ #define COMSIG_XENOABILITY_REGENERATE_SKIN "xenoability_regenerate_skin" #define COMSIG_XENOABILITY_CENTRIFUGAL_FORCE "xenoability_centrifugal_force" +#define COMSIG_XENOABILITY_STEELCREST_HEADBUTT "xenoability_steelcrest_bodyswap_headbutt" +#define COMSIG_XENOABILITY_STEELCREST_SOAK "xenoability_steelcrest_soak" + #define COMSIG_XENOABILITY_EMIT_NEUROGAS "xenoability_emit_neurogas" #define COMSIG_XENOABILITY_SELECT_REAGENT "xenoability_select_reagent" #define COMSIG_XENOABILITY_RADIAL_SELECT_REAGENT "xenoability_radial_select_reagent" @@ -1012,7 +1015,11 @@ //Signals for CIC orders #define COMSIG_ORDER_SELECTED "order_selected" -#define COMSIG_ORDER_SENT "order_updated" +#define COMSIG_CIC_ORDER_SENT "order_updated" +#define COMSIG_CIC_ORDER_OFF_CD "order_off_cd" + +#define COMSIG_SKILL_ORDER_SENT "skill_order_updated" +#define COMSIG_SKILL_ORDER_OFF_CD "skill_order_off_cd" //Signals for automatic fire at component #define COMSIG_AUTOMATIC_SHOOTER_START_SHOOTING_AT "start_shooting_at" diff --git a/code/__DEFINES/greyscale_guns.dm b/code/__DEFINES/greyscale_guns.dm index fcfeb35e883..648f85338c8 100644 --- a/code/__DEFINES/greyscale_guns.dm +++ b/code/__DEFINES/greyscale_guns.dm @@ -5,6 +5,7 @@ #define AMMO_BAND_COLOR_INCENDIARY "#9C2219" #define AMMO_BAND_COLOR_EXPLOSIVE "#3f1111" #define AMMO_BAND_COLOR_SABOT "#663618" +#define AMMO_BAND_COLOR_IMPACT "#0052CC" #define GUN_PALETTE_TAN "#3F382E#61574A#807360#978872" #define GUN_PALETTE_RED "#421010#601e1e#762525#9b3a28" diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm index 12a9a9eae0d..a8e4d99fb85 100644 --- a/code/__DEFINES/movespeed_modification.dm +++ b/code/__DEFINES/movespeed_modification.dm @@ -30,6 +30,7 @@ #define MOVESPEED_ID_XENO_CHARGE "XENO_CHARGE_MODIFIER" #define MOVESPEED_ID_ENHANCEMENT "ENHANCEMENT" #define MOVESPEED_ID_CRESTDEFENSE "CRESTDEFENSE" +#define MOVESPEED_ID_FORTIFY "FORTIFY" #define MOVESPEED_ID_WARRIOR_AGILITY "WARRIOR_AGILITY" #define MOVESPEED_ID_FRENZY_AURA "FRENZY_AURA" #define MOVESPEED_ID_XENO_HEMODILE "XENO_HEMODILE" diff --git a/code/__DEFINES/objects.dm b/code/__DEFINES/objects.dm index 4865b3da080..920be09f9da 100644 --- a/code/__DEFINES/objects.dm +++ b/code/__DEFINES/objects.dm @@ -206,11 +206,6 @@ GLOBAL_LIST_INIT(restricted_camera_networks, list( //Those networks can only be #define NIGHTFALL_IMMUNE 3 #define NO_LIGHT_STATE_CHANGE 4 -//Xeno turrets define -#define TURRET_SCAN_RANGE 25 -#define TURRET_SCAN_FREQUENCY 10 SECONDS -#define TURRET_HEALTH_REGEN 8 - //Unmanned vehicle define #define OVERLAY_TURRET (1<<0) #define HAS_HEADLIGHTS (1<<1) diff --git a/code/__DEFINES/overwatch.dm b/code/__DEFINES/overwatch.dm index 884335f68a9..ca375ca1702 100644 --- a/code/__DEFINES/overwatch.dm +++ b/code/__DEFINES/overwatch.dm @@ -1,3 +1,5 @@ -#define ORDER_DURATION 30 SECONDS -#define ORDER_COOLDOWN 30 SECONDS -#define RALLY_ORDER_DURATION 30 SECONDS +#define CIC_ORDER_DURATION 30 SECONDS +#define CIC_ORDER_COOLDOWN 30 SECONDS + +#define SKILL_ORDER_DURATION 30 SECONDS +#define SKILL_ORDER_COOLDOWN 45 SECONDS diff --git a/code/__DEFINES/progress_display.dm b/code/__DEFINES/progress_display.dm index 7de391c9333..bd07f54e878 100644 --- a/code/__DEFINES/progress_display.dm +++ b/code/__DEFINES/progress_display.dm @@ -39,3 +39,4 @@ #define BUSY_ICON_BAR /image/progdisplay/bar #define BUSY_ICON_UNSKILLED /image/progdisplay/unskilled #define BUSY_ICON_ENERGY /image/progdisplay/energy +#define BUSY_ICON_FACEHUGGER /image/progdisplay/facehugger diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index 6b6ee730ee1..7d2feb02846 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -1,8 +1,7 @@ //Xeno structure flags #define IGNORE_WEED_REMOVAL (1<<0) -#define HAS_OVERLAY (1<<1) -#define CRITICAL_STRUCTURE (1<<2) -#define DEPART_DESTRUCTION_IMMUNE (1<<3) +#define CRITICAL_STRUCTURE (1<<1) +#define DEPART_DESTRUCTION_IMMUNE (1<<2) //Weeds defines #define WEED "weed sac" @@ -10,9 +9,6 @@ #define RESTING_WEED "resting weed sac" #define AUTOMATIC_WEEDING "repeating" -#define XENO_TURRET_ACID_ICONSTATE "acid_turret" -#define XENO_TURRET_STICKY_ICONSTATE "resin_turret" - //Plant defines #define HEAL_PLANT "life fruit" #define ARMOR_PLANT "hard fruit" @@ -219,10 +215,7 @@ GLOBAL_LIST_INIT(xeno_utility_upgrades, list( /datum/status_effect/upgrade_trail, )) -#define XENO_UPGRADE_BIOMASS_COST_T1 10 -#define XENO_UPGRADE_BIOMASS_COST_T2 15 -#define XENO_UPGRADE_BIOMASS_COST_T3 20 -#define XENO_UPGRADE_BIOMASS_COST_T4 25 +#define XENO_UPGRADE_COST 25 #define CHARGE_SPEED(charger) (min(charger.valid_steps_taken, charger.max_steps_buildup) * charger.speed_per_step) #define CHARGE_MAX_SPEED (speed_per_step * max_steps_buildup) diff --git a/code/__HELPERS/ai.dm b/code/__HELPERS/ai.dm index 6e9b16d1e4e..bee07945d03 100644 --- a/code/__HELPERS/ai.dm +++ b/code/__HELPERS/ai.dm @@ -63,6 +63,7 @@ if(get_dist(source, nearby_illusion) > distance) continue . += nearby_illusion + ///Returns a list of vehicles via get_dist and same z level method, very cheap compared to range() /proc/cheap_get_tanks_near(atom/movable/source, distance) . = list() @@ -81,6 +82,21 @@ continue . += nearby_tank +///Returns a list of unmanned vehicles via get_dist and same z level method, very cheap compared to range() +/proc/cheap_get_unmanned_vehicles_near(atom/movable/source, distance) + . = list() + var/turf/source_turf = get_turf(source) + if(!source_turf) + return + for(var/obj/vehicle/unmanned/nearby_unmanned_vehicle AS in GLOB.unmanned_vehicles) + if(isnull(nearby_unmanned_vehicle)) + continue + if(source_turf.z != nearby_unmanned_vehicle.z) + continue + if(get_dist(source_turf, nearby_unmanned_vehicle) > distance) + continue + . += nearby_unmanned_vehicle + ///Returns the nearest target that has the right target flag /proc/get_nearest_target(atom/source, distance, target_flags, attacker_faction, attacker_hive) if(!source) diff --git a/code/__HELPERS/announce.dm b/code/__HELPERS/announce.dm index 555e8140388..58d9994f550 100644 --- a/code/__HELPERS/announce.dm +++ b/code/__HELPERS/announce.dm @@ -35,7 +35,6 @@ /proc/assemble_alert(title, subtitle, message, color_override, minor = FALSE) if(!title || !message) return - var/list/alert_strings = list() var/header var/finalized_alert @@ -70,7 +69,7 @@ */ /proc/priority_announce( message, - title = "Announcement", + title = "Оповещение", subtitle = "", type = ANNOUNCEMENT_REGULAR, sound = 'sound/misc/notice2.ogg', @@ -91,12 +90,12 @@ assembly_header = title if(ANNOUNCEMENT_PRIORITY) - assembly_header = "Priority Announcement" + assembly_header = "Приоритетное Оповещение" if(length(title) > 0) assembly_subtitle = title if(ANNOUNCEMENT_COMMAND) - assembly_header = "Command Announcement" + assembly_header = "Оповещение Экипажу" if(subtitle && type != ANNOUNCEMENT_PRIORITY) assembly_subtitle = subtitle @@ -125,7 +124,7 @@ SEND_SOUND(M, s) -/proc/print_command_report(papermessage, papertitle = "paper", announcemessage = "A report has been downloaded and printed out at all communications consoles.", announcetitle = "Incoming Classified Message", announce = TRUE) +/proc/print_command_report(papermessage, papertitle = "paper", announcemessage = "Отчет был загружен и распечатан на всех консолях связи.", announcetitle = "Входящее зашифрованное сообщение", announce = TRUE) if(announce) priority_announce(announcemessage, announcetitle, sound = 'sound/AI/commandreport.ogg') @@ -147,7 +146,7 @@ * * alert - optional, alert or notice? * * receivers - a list of all players to send the message to */ -/proc/minor_announce(message, title = "Attention:", alert, list/receivers = GLOB.alive_human_list) +/proc/minor_announce(message, title = "Внимание:", alert, list/receivers = GLOB.alive_human_list) if(!message) return diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index e4a6884d5ee..57404802845 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -683,208 +683,191 @@ ColorTone(rgb, tone) return BlendRGB(tone, "#ffffff", (gray - tone_gray) / ((255 - tone_gray) || 1)) -/// Creates a single icon from a given /atom or /image. Only the first argument is required. -/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE) - //Define... defines. +/// Create a single [/icon] from a given [/atom] or [/image]. +/// +/// Very low-performance. Should usually only be used for HTML, where BYOND's +/// appearance system (overlays/underlays, etc.) is not available. +/// +/// Only the first argument is required. +/proc/getFlatIcon(image/appearance, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE) + // Loop through the underlays, then overlays, sorting them into the layers list + #define PROCESS_OVERLAYS_OR_UNDERLAYS(flat, process, base_layer) \ + for(var/i in 1 to process.len) { \ + var/image/current = process[i]; \ + if (!current) { \ + continue; \ + } \ + if (current.plane != FLOAT_PLANE && current.plane != appearance.plane) { \ + continue; \ + } \ + var/current_layer = current.layer; \ + if (current_layer < 0) { \ + if (current_layer <= -1000) { \ + return flat; \ + } \ + current_layer = base_layer + appearance.layer + current_layer / 1000; \ + } \ + for (var/index_to_compare_to in 1 to layers.len) { \ + var/compare_to = layers[index_to_compare_to]; \ + if (current_layer < layers[compare_to]) { \ + layers.Insert(index_to_compare_to, current); \ + break; \ + } \ + } \ + layers[current] = current_layer; \ + } + var/static/icon/flat_template = icon('icons/effects/effects.dmi', "nothing") + var/icon/flat = icon(flat_template) + + if(!appearance || appearance.alpha <= 0) + return flat - #define BLANK icon(flat_template) - #define SET_SELF(SETVAR) do { \ - var/icon/SELF_ICON = icon(icon(curicon, curstate, base_icon_dir), "", SOUTH, no_anim ? 1 : null); \ - if(A.alpha < 255) { \ - SELF_ICON.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY);\ - } \ - if(A.color) { \ - if(islist(A.color)){ \ - SELF_ICON.MapColors(arglist(A.color))} \ - else{ \ - SELF_ICON.Blend(A.color, ICON_MULTIPLY)} \ - } \ - ##SETVAR=SELF_ICON;\ - } while (0) - #define INDEX_X_LOW 1 - #define INDEX_X_HIGH 2 - #define INDEX_Y_LOW 3 - #define INDEX_Y_HIGH 4 - - #define flatX1 flat_size[INDEX_X_LOW] - #define flatX2 flat_size[INDEX_X_HIGH] - #define flatY1 flat_size[INDEX_Y_LOW] - #define flatY2 flat_size[INDEX_Y_HIGH] - #define addX1 add_size[INDEX_X_LOW] - #define addX2 add_size[INDEX_X_HIGH] - #define addY1 add_size[INDEX_Y_LOW] - #define addY2 add_size[INDEX_Y_HIGH] - - if(!A || A.alpha <= 0) - return BLANK - - var/noIcon = FALSE if(start) if(!defdir) - defdir = A.dir + defdir = appearance.dir if(!deficon) - deficon = A.icon + deficon = appearance.icon if(!defstate) - defstate = A.icon_state + defstate = appearance.icon_state if(!defblend) - defblend = A.blend_mode + defblend = appearance.blend_mode - var/curicon = A.icon || deficon - var/curstate = A.icon_state || defstate + var/curicon = appearance.icon || deficon + var/curstate = appearance.icon_state || defstate + var/curdir = (!appearance.dir || appearance.dir == SOUTH) ? defdir : appearance.dir - if(!((noIcon = (!curicon)))) + var/render_icon = curicon + + if(render_icon) var/curstates = icon_states(curicon) if(!(curstate in curstates)) if("" in curstates) curstate = "" else - noIcon = TRUE // Do not render this object. + render_icon = FALSE - var/curdir var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have - //These should use the parent's direction (most likely) - if(!A.dir || A.dir == SOUTH) - curdir = defdir - else - curdir = A.dir - - //Try to remove/optimize this section ASAP, CPU hog. - //Determines if there's directionals. - if(!noIcon && curdir != SOUTH) - var/exist = FALSE - var/static/list/checkdirs = list(NORTH, EAST, WEST) - for(var/i in checkdirs) //Not using GLOB for a reason. - if(length(icon_states(icon(curicon, curstate, i)))) - exist = TRUE - break - if(!exist) - base_icon_dir = SOUTH - // + if(render_icon) + //Try to remove/optimize this section if you can, it's a CPU hog. + //Determines if there're directionals. + if(curdir != SOUTH) + // icon states either have 1, 4 or 8 dirs. We only have to check + // one of NORTH, EAST or WEST to know that this isn't a 1-dir icon_state since they just have SOUTH. + if(!length(icon_states(icon(curicon, curstate, NORTH)))) + base_icon_dir = SOUTH + + var/list/icon_dimensions = get_icon_dimensions(curicon) + var/icon_width = icon_dimensions["width"] + var/icon_height = icon_dimensions["height"] + if(icon_width != 32 || icon_height != 32) + flat.Scale(icon_width, icon_height) if(!base_icon_dir) base_icon_dir = curdir ASSERT(!BLEND_DEFAULT) //I might just be stupid but lets make sure this define is 0. - var/curblend = A.blend_mode || defblend + var/curblend = appearance.blend_mode || defblend - if(length(A.overlays) || length(A.underlays)) - var/icon/flat = BLANK + if(length(appearance.overlays) || length(appearance.underlays)) // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed var/list/layers = list() var/image/copy // Add the atom's icon itself, without pixel_x/y offsets. - if(!noIcon) - copy = image(icon = curicon, icon_state = curstate, layer = A.layer, dir = base_icon_dir) - copy.color = A.color - copy.alpha = A.alpha + if(render_icon) + copy = image(icon = curicon, icon_state = curstate, layer = appearance.layer, dir = base_icon_dir) + copy.color = appearance.color + copy.alpha = appearance.alpha copy.blend_mode = curblend - layers[copy] = A.layer - - // Loop through the underlays, then overlays, sorting them into the layers list - for(var/process_set in 0 to 1) - var/list/process = process_set ? A.overlays : A.underlays - for(var/i in 1 to length(process)) - var/image/current = process[i] - if(!current) - continue - if(current.plane != FLOAT_PLANE && current.plane != A.plane) - continue - var/current_layer = current.layer - if(current_layer < 0) - if(current_layer <= -1000) - return flat - current_layer = process_set + A.layer + current_layer * 0.001 - - for(var/p in 1 to length(layers)) - var/image/cmp = layers[p] - if(current_layer < layers[cmp]) - layers.Insert(p, current) - break - layers[current] = current_layer - - //sortTim(layers, GLOBAL_PROC_REF(cmp_image_layer_asc)) + layers[copy] = appearance.layer + + PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.underlays, 0) + PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.overlays, 1) var/icon/add // Icon of overlay being added - // Current dimensions of flattened icon - var/list/flat_size = list(1, flat.Width(), 1, flat.Height()) - // Dimensions of overlay being added - var/list/add_size[4] + var/flatX1 = 1 + var/flatX2 = flat.Width() + var/flatY1 = 1 + var/flatY2 = flat.Height() + + var/addX1 = 0 + var/addX2 = 0 + var/addY1 = 0 + var/addY2 = 0 - for(var/V in layers) - var/image/I = V - if(I.alpha == 0) + for(var/image/layer_image as anything in layers) + if(layer_image.alpha == 0) continue - if(I == copy) // 'I' is an /image based on the object being flattened. + if(layer_image ) // 'layer_image ' is an /image based on the object being flattened. curblend = BLEND_OVERLAY - add = icon(I.icon, I.icon_state, base_icon_dir) + add = icon(layer_image.icon, layer_image.icon_state, base_icon_dir) else // 'I' is an appearance object. - add = getFlatIcon(image(I), curdir, curicon, curstate, curblend, FALSE, no_anim) + add = getFlatIcon(image(layer_image ), curdir, curicon, curstate, curblend, FALSE, no_anim) if(!add) continue + // Find the new dimensions of the flat icon to fit the added overlay - add_size = list( - min(flatX1, I.pixel_x+1), - max(flatX2, I.pixel_x+add.Width()), - min(flatY1, I.pixel_y+1), - max(flatY2, I.pixel_y+add.Height()) + addX1 = min(flatX1, layer_image.pixel_x + 1) + addX2 = max(flatX2, layer_image.pixel_x + add.Width()) + addY1 = min(flatY1, layer_image.pixel_y + 1) + addY2 = max(flatY2, layer_image.pixel_y + add.Height()) + + if( + addX1 != flatX1 \ + && addX2 != flatX2 \ + && addY1 != flatY1 \ + && addY2 != flatY2 \ ) - - if(flat_size ~! add_size) // Resize the flattened icon so the new icon fits flat.Crop( - addX1 - flatX1 + 1, - addY1 - flatY1 + 1, - addX2 - flatX1 + 1, - addY2 - flatY1 + 1 + addX1 - flatX1 + 1, + addY1 - flatY1 + 1, + addX2 - flatX1 + 1, + addY2 - flatY1 + 1 ) - flat_size = add_size.Copy() + flatX1 = addX1 + flatX2 = addY1 + flatY1 = addX2 + flatY2 = addY2 // Blend the overlay into the flattened icon - flat.Blend(add, blendMode2iconMode(curblend), I.pixel_x + 2 - flatX1, I.pixel_y + 2 - flatY1) + flat.Blend(add, blendMode2iconMode(curblend), layer_image.pixel_x + 2 - flatX1, layer_image.pixel_y + 2 - flatY1) - if(A.color) - if(islist(A.color)) - flat.MapColors(arglist(A.color)) + if(appearance.color) + if(islist(appearance.color)) + flat.MapColors(arglist(appearance.color)) else - flat.Blend(A.color, ICON_MULTIPLY) + flat.Blend(appearance.color, ICON_MULTIPLY) - if(A.alpha < 255) - flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) + if(appearance.alpha < 255) + flat.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY) if(no_anim) //Clean up repeated frames var/icon/cleaned = new /icon() cleaned.Insert(flat, "", SOUTH, 1, 0) - . = cleaned + return cleaned else - . = icon(flat, "", SOUTH) - else //There's no overlays. - if(!noIcon) - SET_SELF(.) - - //Clear defines - #undef flatX1 - #undef flatX2 - #undef flatY1 - #undef flatY2 - #undef addX1 - #undef addX2 - #undef addY1 - #undef addY2 - - #undef INDEX_X_LOW - #undef INDEX_X_HIGH - #undef INDEX_Y_LOW - #undef INDEX_Y_HIGH - - #undef BLANK - #undef SET_SELF + return icon(flat, "", SOUTH) + else if (render_icon) // There's no overlays. + var/icon/final_icon = icon(icon(curicon, curstate, base_icon_dir), "", SOUTH, no_anim ? TRUE : null) + if (appearance.alpha < 255) + final_icon.Blend(rgb(255,255,255, appearance.alpha), ICON_MULTIPLY) + + if (appearance.color) + if (islist(appearance.color)) + final_icon.MapColors(arglist(appearance.color)) + else + final_icon.Blend(appearance.color, ICON_MULTIPLY) + + return final_icon + + #undef PROCESS_OVERLAYS_OR_UNDERLAYS /proc/getHologramIcon(icon/A, safety = TRUE)//If safety is on, a new icon is not created. var/icon/flat_icon = safety ? A : new(A)//Has to be a new icon to not constantly change the same icon. @@ -1276,3 +1259,10 @@ GLOBAL_LIST_EMPTY(transformation_animation_objects) image_to_center.pixel_y = y_offset return image_to_center + +/// Returns a list containing the width and height of an icon file +/proc/get_icon_dimensions(icon_path) + if (isnull(GLOB.icon_dimensions[icon_path])) + var/icon/my_icon = icon(icon_path) + GLOB.icon_dimensions[icon_path] = list("width" = my_icon.Width(), "height" = my_icon.Height()) + return GLOB.icon_dimensions[icon_path] diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index e9784de76da..f1b19ad81a2 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -116,6 +116,24 @@ if(SOUTHWEST) return "southwest" +/proc/dir2rutext(direction) + switch(direction) + if(NORTH) + return "север" + if(SOUTH) + return "юг" + if(EAST) + return "восток" + if(WEST) + return "запад" + if(NORTHEAST) + return "северо-восток" + if(SOUTHEAST) + return "юго-восток" + if(NORTHWEST) + return "северо-запад" + if(SOUTHWEST) + return "юго-запад" //Turns a direction into text /proc/dir2text_short(direction) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 8733730f816..1cfd6b3674d 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1077,9 +1077,9 @@ will handle it, but: var/pixel_y_offset = AM.pixel_y + M.get_y_shift() //Irregular objects - var/icon/AMicon = icon(AM.icon, AM.icon_state) - var/AMiconheight = AMicon.Height() - var/AMiconwidth = AMicon.Width() + var/list/icon_dimensions = get_icon_dimensions(AM.icon) + var/AMiconheight = icon_dimensions["height"] + var/AMiconwidth = icon_dimensions["width"] if(AMiconheight != world.icon_size || AMiconwidth != world.icon_size) pixel_x_offset += ((AMiconwidth/world.icon_size)-1)*(world.icon_size*0.5) pixel_y_offset += ((AMiconheight/world.icon_size)-1)*(world.icon_size*0.5) diff --git a/code/_globalvars/lists/icons.dm b/code/_globalvars/lists/icons.dm new file mode 100644 index 00000000000..ff60e6bc8d9 --- /dev/null +++ b/code/_globalvars/lists/icons.dm @@ -0,0 +1,2 @@ +/// Cache of the width and height of icon files, to avoid repeating the same expensive operation +GLOBAL_LIST_EMPTY(icon_dimensions) diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 49af82f6f4e..bee4e1f738c 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -224,7 +224,7 @@ /obj/structure/xeno/silo/AIMiddleClick(mob/living/silicon/ai/user) user.ai_ping(src, COOLDOWN_AI_PING_EXTRA_LOW) -/obj/structure/xeno/xeno_turret/AIMiddleClick(mob/living/silicon/ai/user) +/obj/structure/xeno/turret/AIMiddleClick(mob/living/silicon/ai/user) user.ai_ping(src, COOLDOWN_AI_PING_EXTRA_LOW) /obj/structure/xeno/evotower/AIMiddleClick(mob/living/silicon/ai/user) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index ff080acd59d..0ed74e9c7ee 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -410,8 +410,13 @@ if(selected_ability.target_flags & flagname && !istype(A, typepath)){\ /mob/living/carbon/human/ShiftClickOn(atom/A) if(client.prefs.toggles_gameplay & MIDDLESHIFTCLICKING) return ..() - var/obj/item/held_thing = get_active_held_item() + if(selected_ability) + A = ability_target(A) + if(selected_ability.can_use_ability(A)) + selected_ability.use_ability(A) + return TRUE + var/obj/item/held_thing = get_active_held_item() if(held_thing && SEND_SIGNAL(held_thing, COMSIG_ITEM_SHIFTCLICKON, A, src) & COMPONENT_ITEM_CLICKON_BYPASS) return FALSE return ..() diff --git a/code/_onclick/hud/screen_objects/menu_text_objects.dm b/code/_onclick/hud/screen_objects/menu_text_objects.dm index f73bdc8a3c5..59ad66e0ee6 100644 --- a/code/_onclick/hud/screen_objects/menu_text_objects.dm +++ b/code/_onclick/hud/screen_objects/menu_text_objects.dm @@ -88,11 +88,11 @@ update_text() /atom/movable/screen/text/lobby/clickable/join_game/update_text() - var/mob/new_player/player = hud.mymob if(SSticker?.current_state > GAME_STATE_PREGAME) maptext = "ПРИСОЕДИНИТЬСЯ" icon_state = "join" return + var/mob/new_player/player = hud.mymob maptext = "ВЫ: [player.ready ? "" : "НЕ "]ГОТОВЫ" icon_state = player.ready ? "ready" : "unready" diff --git a/code/_onclick/hud/screen_objects/screen_objects.dm b/code/_onclick/hud/screen_objects/screen_objects.dm index 8b46ebdf282..13a5e3e75a5 100644 --- a/code/_onclick/hud/screen_objects/screen_objects.dm +++ b/code/_onclick/hud/screen_objects/screen_objects.dm @@ -796,17 +796,17 @@ /atom/movable/screen/arrow/attack_order_arrow name = "attack order arrow" icon_state = "Attack_arrow" - duration = ORDER_DURATION + duration = CIC_ORDER_DURATION /atom/movable/screen/arrow/rally_order_arrow name = "Rally order arrow" icon_state = "Rally_arrow" - duration = RALLY_ORDER_DURATION + duration = CIC_ORDER_DURATION /atom/movable/screen/arrow/defend_order_arrow name = "Defend order arrow" icon_state = "Defend_arrow" - duration = ORDER_DURATION + duration = CIC_ORDER_DURATION /atom/movable/screen/arrow/hunter_mark_arrow name = "hunter mark arrow" diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 15baa335184..cf6f0cde388 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -19,9 +19,6 @@ /datum/config_entry/keyed_list/min_pop/ValidateListEntry(key_name, key_value) return key_name in config.modes -/datum/config_entry/string/alert_delta - config_entry_value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill." - /datum/config_entry/number/revival_brain_life config_entry_value = -1 integer = FALSE diff --git a/code/controllers/subsystem/evacuation.dm b/code/controllers/subsystem/evacuation.dm index 27db35ff841..afa0ff8028d 100644 --- a/code/controllers/subsystem/evacuation.dm +++ b/code/controllers/subsystem/evacuation.dm @@ -86,7 +86,7 @@ SUBSYSTEM_DEF(evacuation) evac_time = world.time evac_status = EVACUATION_STATUS_INITIATING SEND_GLOBAL_SIGNAL(COMSIG_GLOB_EVACUATION_STARTED) - priority_announce("Emergency evacuation has been triggered. Please proceed to the escape pods. Evacuation in [EVACUATION_AUTOMATIC_DEPARTURE/600] minutes.", title = "Emergency Evacuation", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/evacuate.ogg', color_override = "orange") + priority_announce("Процесс экстренной эвакуации был запущен. Пожалуйста, проследуйте к спасательным капсулам. Запуск капсул состоится через [EVACUATION_AUTOMATIC_DEPARTURE/600] минут.", title = "Экстренная Эвакуация", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/evacuate.ogg', color_override = "orange") xeno_message("A wave of adrenaline ripples through the hive. The fleshy creatures are trying to escape!") pod_list = SSshuttle.escape_pods.Copy() for(var/obj/docking_port/mobile/escape_pod/pod AS in pod_list) @@ -98,7 +98,7 @@ SUBSYSTEM_DEF(evacuation) if(evac_status != EVACUATION_STATUS_INITIATING) return FALSE evac_status = EVACUATION_STATUS_IN_PROGRESS - priority_announce("WARNING: Evacuation order confirmed. Launching escape pods.", title = "Emergency Evacuation", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/evacuation_confirmed.ogg', color_override = "orange") + priority_announce("Приказ об эвакуации подтвержден. Запуск спасательных капсул.", title = "Экстренная Активация", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/evacuation_confirmed.ogg', color_override = "orange") return TRUE @@ -108,7 +108,7 @@ SUBSYSTEM_DEF(evacuation) GLOB.enter_allowed = TRUE evac_time = null evac_status = EVACUATION_STATUS_STANDING_BY - priority_announce("Evacuation has been cancelled.", title = "Emergency Evacuation", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/evacuate_cancelled.ogg', color_override = "orange") + priority_announce("Процесс эвакуации был отменен. Произвожу восстановление первичных систем...", title = "Экстренная Эвакуация", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/evacuate_cancelled.ogg', color_override = "orange") for(var/obj/docking_port/mobile/escape_pod/pod AS in pod_list) pod.unprep_for_launch() return TRUE @@ -123,7 +123,7 @@ SUBSYSTEM_DEF(evacuation) . = "NOW" /datum/controller/subsystem/evacuation/proc/announce_evac_completion() - priority_announce("ATTENTION: Evacuation complete.", title = "Emergency Evacuation", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/evacuation_complete.ogg', color_override = "orange") + priority_announce("Эвакуация завершена. Оставшемуся экипажу требуется завершить миссию.", title = "Эвакуация Завершена", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/evacuation_complete.ogg', color_override = "orange") evac_status = EVACUATION_STATUS_COMPLETE @@ -158,7 +158,7 @@ SUBSYSTEM_DEF(evacuation) I.toggle(TRUE) dest_master.toggle(TRUE) dest_index = 1 - priority_announce("The emergency destruct system has been deactivated.", title = "Self Destruct System", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/selfdestruct_deactivated.ogg', color_override = "purple") + priority_announce("Протокол самоуничтожения деактивирован. Перезапуск систем.", title = "Протокол Самоуничтожения", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/selfdestruct_deactivated.ogg', color_override = "purple") if(evac_status == EVACUATION_STATUS_STANDING_BY) GLOB.marine_main_ship.set_security_level(SEC_LEVEL_RED, TRUE) for(var/obj/machinery/floor_warn_light/self_destruct/light AS in alarm_lights) @@ -177,7 +177,7 @@ SUBSYSTEM_DEF(evacuation) dest_master.visible_message(span_warning("WARNING: Unable to trigger detonation. Please arm all control rods.")) return FALSE - priority_announce("DANGER. DANGER. Self destruct system activated. DANGER. DANGER. Self destruct in progress. DANGER. DANGER.", title = "Self Destruct System", type = ANNOUNCEMENT_PRIORITY, color_override = "purple") + priority_announce("ТРЕВОГА. ТРЕВОГА. ПРОТОКОЛ САМОУНИЧТОЖЕНИЯ ЗАВЕРШЕН. ТРЕВОГА. ТРЕВОГА. ДЕТОНАЦИЯ.", title = "Протокол Самоуничтожения", type = ANNOUNCEMENT_PRIORITY, color_override = "purple") GLOB.enter_allowed = FALSE dest_status = NUKE_EXPLOSION_IN_PROGRESS playsound(dest_master, 'sound/machines/alarm.ogg', 75, 0, 30) diff --git a/code/datums/actions/action.dm b/code/datums/actions/action.dm index 3c350c1fe53..788b28fd68a 100644 --- a/code/datums/actions/action.dm +++ b/code/datums/actions/action.dm @@ -26,6 +26,8 @@ KEYBINDINGS var/action_type = ACTION_CLICK ///Used for keeping track of the addition of the selected/active frames var/toggled = FALSE + ///Is this action explicitly hidden from the owner + var/hidden = FALSE /datum/action/New(Target) target = Target @@ -66,8 +68,9 @@ KEYBINDINGS SHOULD_CALL_PARENT(TRUE) qdel(src) +///Whether the owner can see this action /datum/action/proc/should_show() - return TRUE + return !hidden ///Depending on the action type , toggles the selected/active frame to show without allowing stacking multiple overlays /datum/action/proc/set_toggle(value) @@ -186,7 +189,6 @@ KEYBINDINGS owner.actions += src if(owner.client) owner.client.screen += button - owner.update_action_buttons() owner.actions_by_path[type] = src for(var/type in keybinding_signals) var/signal = keybinding_signals[type] @@ -197,6 +199,7 @@ KEYBINDINGS update_map_text(our_kb.get_keys_formatted(M.client), signal) SEND_SIGNAL(M, ACTION_GIVEN) + owner.update_action_buttons() /datum/action/proc/remove_action(mob/M) for(var/type in keybinding_signals) @@ -207,9 +210,9 @@ KEYBINDINGS M.client.screen -= button M.actions_by_path[type] = null M.actions -= src - M.update_action_buttons() owner = null SEND_SIGNAL(M, ACTION_REMOVED) + M.update_action_buttons() ///Should a AI element occasionally see if this ability should be used? /datum/action/proc/ai_should_start_consider() diff --git a/code/datums/actions/innate.dm b/code/datums/actions/innate.dm index 7deb8d282ef..3a8b59aad03 100644 --- a/code/datums/actions/innate.dm +++ b/code/datums/actions/innate.dm @@ -12,12 +12,6 @@ Deactivate() return TRUE - -/datum/action/innate/give_action() - . = ..() - update_button_icon() - - /datum/action/innate/proc/Activate() return diff --git a/code/datums/actions/item_action.dm b/code/datums/actions/item_action.dm index cc7d21e3928..5a4dbe99115 100644 --- a/code/datums/actions/item_action.dm +++ b/code/datums/actions/item_action.dm @@ -59,6 +59,10 @@ . = ..() set_toggle(!toggled) +/datum/action/item_action/toggle/remove_action(mob/M) + deselect() + return ..() + /datum/action/item_action/toggle/suit_toggle keybinding_signals = list(KEYBINDING_NORMAL = COMSIG_KB_SUITLIGHT) @@ -79,7 +83,6 @@ /datum/action/item_action/firemode/New() . = ..() holder_gun = holder_item - update_button_icon() /datum/action/item_action/firemode/update_button_icon() diff --git a/code/datums/actions/item_toggles.dm b/code/datums/actions/item_toggles.dm index 9804364b421..3d2b5bc30af 100644 --- a/code/datums/actions/item_toggles.dm +++ b/code/datums/actions/item_toggles.dm @@ -38,3 +38,7 @@ else visual_references[VREF_MUTABLE_LINKED_OBJ] = null return ..() + +/datum/action/ability/activable/item_toggle/remove_action(mob/M) + deselect() + return ..() diff --git a/code/datums/actions/observer_action.dm b/code/datums/actions/observer_action.dm index 238007007e8..5b32fa278e6 100644 --- a/code/datums/actions/observer_action.dm +++ b/code/datums/actions/observer_action.dm @@ -122,6 +122,22 @@ var/list/area_namecounts = list() var/name + for(var/obj/structure/xeno/turret/potential_turret AS in GLOB.xeno_resin_turrets_by_hive[XENO_HIVE_NORMAL]) + if(dead_owner.z != potential_turret.z) + continue + if(!istype(potential_turret, /obj/structure/xeno/turret/facehugger)) + continue + var/area/area = get_area(potential_turret) + if(area in area_names) + area_namecounts[area]++ + name = "[potential_turret.name] at [area] ([area_namecounts[area]])" + else + area_names.Add(area) + area_namecounts[area] = 1 + name = "[potential_turret.name] at [get_area(potential_turret)]" + + spawn_point[name] = potential_turret + for(var/mob/living/carbon/xenomorph/potential_xeno AS in GLOB.alive_xeno_list) if(dead_owner.z != potential_xeno.z) continue diff --git a/code/datums/actions/order_action.dm b/code/datums/actions/order_action.dm index 47d49aa0808..887c5bd9a36 100644 --- a/code/datums/actions/order_action.dm +++ b/code/datums/actions/order_action.dm @@ -13,11 +13,11 @@ /datum/action/innate/order/give_action(mob/M) . = ..() - RegisterSignal(M, COMSIG_ORDER_SENT, PROC_REF(update_button_icon)) + RegisterSignals(M, list(COMSIG_CIC_ORDER_SENT, COMSIG_CIC_ORDER_OFF_CD), PROC_REF(update_button_icon)) /datum/action/innate/order/remove_action(mob/M) . = ..() - UnregisterSignal(M, COMSIG_ORDER_SENT) + UnregisterSignal(M, list(COMSIG_CIC_ORDER_SENT, COMSIG_CIC_ORDER_OFF_CD)) /datum/action/innate/order/Activate() active = TRUE @@ -48,14 +48,14 @@ /datum/action/innate/order/proc/send_order(atom/target, datum/squad/squad, faction = FACTION_TERRAGOV) if(!can_use_action()) return - to_chat(owner ,span_ordercic("You ordered marines to [verb_name] [get_area(target.loc)]!")) + to_chat(owner ,span_ordercic("Вы приказали морпехам [verb_name] [get_area(target.loc)]!")) owner.playsound_local(owner, "sound/effects/CIC_order.ogg", 10, 1) if(visual_type) target = get_turf(target) new visual_type(target, faction) - TIMER_COOLDOWN_START(owner, COOLDOWN_CIC_ORDERS, ORDER_COOLDOWN) - SEND_SIGNAL(owner, COMSIG_ORDER_SENT) - addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_all_icons_orders)), ORDER_COOLDOWN) + TIMER_COOLDOWN_START(owner, COOLDOWN_CIC_ORDERS, CIC_ORDER_COOLDOWN) + SEND_SIGNAL(owner, COMSIG_CIC_ORDER_SENT) + addtimer(CALLBACK(src, PROC_REF(on_cooldown_finish)), CIC_ORDER_COOLDOWN + 1) if(squad) for(var/mob/living/carbon/human/marine AS in squad.marines_list) marine.receive_order(target, arrow_type, verb_name, faction) @@ -65,11 +65,9 @@ human.receive_order(target, arrow_type, verb_name, faction) return TRUE -///Update all icons of orders action of the mob -/mob/proc/update_all_icons_orders() - for(var/datum/action/action AS in actions) - if(istype(action, /datum/action/innate/order)) - action.update_button_icon() +///Lets any other orders know when we're off CD +/datum/action/innate/order/proc/on_cooldown_finish() + SEND_SIGNAL(owner, COMSIG_CIC_ORDER_OFF_CD, src) /** * Proc to give a marine an order @@ -98,12 +96,12 @@ var/atom/movable/screen/arrow/arrow_hud = new arrow_type arrow_hud.add_hud(src, target) playsound_local(src, "sound/effects/CIC_order.ogg", 20, 1) - to_chat(src,span_ordercic("Command is urging you to [verb_name] [get_area(get_turf(target))]!")) + to_chat(src,span_ordercic("Командование приказывает вам [verb_name] [get_area(get_turf(target))]!")) /datum/action/innate/order/attack_order name = "Send Attack Order" action_icon_state = "attack" - verb_name = "attack the enemy at" + verb_name = "АТАКОВАТЬ" arrow_type = /atom/movable/screen/arrow/attack_order_arrow visual_type = /obj/effect/temp_visual/order/attack_order @@ -114,6 +112,9 @@ ) /datum/action/innate/order/attack_order/personal/should_show() + . = ..() + if(!.) + return return owner.skills.getRating(skill_name) >= skill_min /datum/action/innate/order/attack_order/personal/action_activate() @@ -125,7 +126,7 @@ /datum/action/innate/order/defend_order name = "Send Defend Order" action_icon_state = "defend" - verb_name = "defend our position in" + verb_name = "ОБОРОНЯТЬ" arrow_type = /atom/movable/screen/arrow/defend_order_arrow visual_type = /obj/effect/temp_visual/order/defend_order @@ -135,6 +136,9 @@ ) /datum/action/innate/order/defend_order/personal/should_show() + . = ..() + if(!.) + return return owner.skills.getRating(skill_name) >= skill_min /datum/action/innate/order/defend_order/personal/action_activate() @@ -146,7 +150,7 @@ /datum/action/innate/order/retreat_order name = "Send Retreat Order" action_icon_state = "retreat" - verb_name = "retreat from" + verb_name = "ОТСТУПАТЬ из" visual_type = /obj/effect/temp_visual/order/retreat_order /datum/action/innate/order/retreat_order/personal @@ -155,6 +159,9 @@ ) /datum/action/innate/order/retreat_order/personal/should_show() + . = ..() + if(!.) + return return owner.skills.getRating(skill_name) >= skill_min /datum/action/innate/order/retreat_order/personal/action_activate() @@ -166,7 +173,7 @@ /datum/action/innate/order/rally_order name = "Send Rally Order" action_icon_state = "rally" - verb_name = "rally to" + verb_name = "СОБРАТЬСЯ в" arrow_type = /atom/movable/screen/arrow/rally_order_arrow visual_type = /obj/effect/temp_visual/order/rally_order @@ -176,6 +183,9 @@ ) /datum/action/innate/order/rally_order/personal/should_show() + . = ..() + if(!.) + return return owner.skills.getRating(skill_name) >= skill_min /datum/action/innate/order/rally_order/personal/action_activate() diff --git a/code/datums/actions/skill.dm b/code/datums/actions/skill.dm index d0c1433e4c6..cc20ca9215d 100644 --- a/code/datums/actions/skill.dm +++ b/code/datums/actions/skill.dm @@ -3,7 +3,10 @@ var/skill_min /datum/action/skill/should_show() - return can_use_action() + . = ..() + if(!.) + return + return owner.skills.getRating(skill_name) >= skill_min /datum/action/skill/can_use_action() return owner.skills.getRating(skill_name) >= skill_min diff --git a/code/datums/actions/species_actions/robot_action.dm b/code/datums/actions/species_actions/robot_action.dm new file mode 100644 index 00000000000..e3ef5ac6b4e --- /dev/null +++ b/code/datums/actions/species_actions/robot_action.dm @@ -0,0 +1,21 @@ +///Lets a robot repair itself over time at the cost of being stunned and blind +/datum/action/repair_self + name = "Activate autorepair" + action_icon_state = "suit_configure" + keybinding_signals = list( + KEYBINDING_NORMAL = COMSIG_KB_ROBOT_AUTOREPAIR, + ) + +/datum/action/repair_self/can_use_action() + . = ..() + if(!.) + return + return !owner.incapacitated() + +/datum/action/repair_self/action_activate() + . = ..() + if(!. || !ishuman(owner)) + return + var/mob/living/carbon/human/howner = owner + howner.apply_status_effect(STATUS_EFFECT_REPAIR_MODE, 10 SECONDS) + howner.balloon_alert_to_viewers("Repairing") diff --git a/code/datums/components/deployable_item.dm b/code/datums/components/deployable_item.dm index 25cab18ea7a..92992defdd1 100644 --- a/code/datums/components/deployable_item.dm +++ b/code/datums/components/deployable_item.dm @@ -63,7 +63,7 @@ var/obj/deployed_machine if(user) - if(!ishuman(user) || HAS_TRAIT(item_to_deploy, TRAIT_NODROP)) + if(!ishuman(user) || HAS_TRAIT(item_to_deploy, TRAIT_NODROP) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) return if(LinkBlocked(get_turf(user), location)) @@ -145,11 +145,12 @@ if(!undeployed_item) CRASH("[src] is missing it's internal item.") - if(!user) CRASH("[source] has sent the signal COMSIG_ITEM_UNDEPLOY to [undeployed_item] without the arg 'user'") if(!ishuman(user)) return + if(HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) + return var/obj/machinery/deployable/mounted/sentry/sentry if(issentry(deployed_machine)) sentry = deployed_machine diff --git a/code/datums/elements/strippable.dm b/code/datums/elements/strippable.dm index 37210f1477a..37f2943a0f4 100644 --- a/code/datums/elements/strippable.dm +++ b/code/datums/elements/strippable.dm @@ -271,7 +271,10 @@ /// A utility function for `/datum/strippable_item`s to start unequipping an item from a mob. /datum/strippable_item/proc/start_unequip_mob(obj/item/item, mob/source, mob/user, strip_delay) - if(!do_after(user, strip_delay || item.strip_delay, NONE, source, BUSY_ICON_FRIENDLY)) + var/display_icon = BUSY_ICON_GENERIC + if(istype(item, /obj/item/clothing/mask/facehugger)) + display_icon = BUSY_ICON_FACEHUGGER + if(!do_after(user, strip_delay || item.strip_delay, NONE, source, display_icon)) return FALSE return TRUE diff --git a/code/datums/emergency_calls/emergency_call.dm b/code/datums/emergency_calls/emergency_call.dm index 9257815968d..db3973b4322 100644 --- a/code/datums/emergency_calls/emergency_call.dm +++ b/code/datums/emergency_calls/emergency_call.dm @@ -7,7 +7,7 @@ var/name = "" var/mob_max = 10 var/mob_min = 1 - var/dispatch_message = "An encrypted signal has been received from a nearby vessel. Stand by." //Message displayed to marines once the signal is finalized. + var/dispatch_message = "Получен зашифрованный сигнал с ближайшего судна. Ожидайте подмогу." //Message displayed to marines once the signal is finalized. var/objectives = "" //Objectives to display to the members. var/list/datum/mind/members = list() //Currently-joined members. var/list/datum/mind/candidates = list() //Potential candidates for enlisting. @@ -78,8 +78,8 @@ for(var/i in GLOB.observer_list) var/mob/dead/observer/M = i - to_chat(M, "
[span_attack("An emergency beacon has been activated. Use the Ghost > Join Response Team verb to join!")]
") - to_chat(M, "[span_attack("You cannot join if you have Ghosted before this message.")]
") + to_chat(M, "
[span_attack("Сигнал бедствия был активирован. Используйте Ghost > Join Response Team чтобы присоединиться!")]
") + to_chat(M, "[span_attack("Вы не можете присоединиться, если вы стали Призраком до появления этого сообщения.")]
") /datum/game_mode/proc/activate_distress(datum/emergency_call/chosen_call) @@ -101,27 +101,27 @@ var/datum/emergency_call/distress = SSticker?.mode?.picked_call //Just to simplify things a bit if(is_banned_from(usr.ckey, ROLE_ERT)) - to_chat(usr, span_danger("You are jobbanned from the emergency reponse team!")) + to_chat(usr, span_danger("Вы были ограничены в этой роли!")) return if(!istype(distress) || !SSticker.mode.waiting_for_candidates || distress.mob_max < 1) - to_chat(usr, span_warning("No distress beacons that need candidates are active. You will be notified if that changes.")) + to_chat(usr, span_warning("Отсутствуют сигналы бедствия нуждающиеся в кандидатах. Вы будете оповещены, если что-то изменится.")) return var/deathtime = world.time - GLOB.key_to_time_of_role_death[key] if(deathtime < 600 && !check_other_rights(usr.client, R_ADMIN, FALSE)) //They have ghosted after the announcement. - to_chat(usr, span_warning("You ghosted too recently. Try again later.")) + to_chat(usr, span_warning("Вы слишком недавно стали призраком. Попробуйте еще раз позже.")) return if(usr.mind in distress.candidates) - to_chat(usr, span_warning("You are already a candidate for this emergency response team.")) + to_chat(usr, span_warning("Вы уже один из кандидатов. Ждите высадки.")) return if(distress.add_candidate(usr)) - to_chat(usr, span_boldnotice("You are now a candidate in the emergency response team! If there are enough candidates, you may be picked to be part of the team.")) + to_chat(usr, span_boldnotice("Теперь вы кандидат в команду экстренного реагирования! Если кандидатов будет достаточно, вас могут выбрать в команду.")) else - to_chat(usr, span_warning("Something went wrong while adding you into the candidate list!")) + to_chat(usr, span_warning("Что-то пошло не так при добавлении вас в список кандидатов!")) /datum/emergency_call/proc/reset() if(candidate_timer) @@ -152,7 +152,7 @@ message_admins("Distress beacon: '[name]' activated. Looking for candidates.") if(announce) - priority_announce("A distress beacon has been launched from the [SSmapping.configs[SHIP_MAP].map_name].", title = "Distress Beacon", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/distressbeacon.ogg', color_override = "orange") + priority_announce("Сигнал бедствия запущен. Ожидание ответа...", title = "Сигнал Бедствия", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/distressbeacon.ogg', color_override = "orange") SSticker.mode.on_distress_cooldown = TRUE @@ -170,11 +170,11 @@ continue if(M.current) //If they still have a body if(!isaghost(M.current) && M.current.stat != DEAD) // and not dead or admin ghosting, - to_chat(M.current, span_warning("You didn't get selected to join the distress team because you aren't dead.")) + to_chat(M.current, span_warning("Вы не были выбраны в команду спасения, потому что вы не мертвы.")) continue if(name == "Xenomorphs" && is_banned_from(ckey(M.key), ROLE_XENOMORPH)) if(M.current) - to_chat(M, span_warning("You didn't get selected to join the distress team because you are jobbanned from Xenomorph.")) + to_chat(M, span_warning("Вас не выбрали для участия в операции бедствия, потому что вам забанили роль Xenomorph.")) continue valid_candidates += M @@ -187,7 +187,7 @@ candidates.Cut() if(announce) - priority_announce("The distress signal has not received a response, the launch tubes are now recalibrating.", "Distress Beacon") + priority_announce("Ответа на сигнал бедствия не поступило. Системы запуска заняты перекалибровкой.", "Сигнал Бедствия", sound = 'sound/AI/distressbeacon_none.ogg') SSticker.mode.picked_call = null SSticker.mode.on_distress_cooldown = TRUE @@ -204,14 +204,14 @@ for(var/datum/mind/M in valid_candidates) if(M.current) - to_chat(M.current, span_warning("You didn't get selected to join the distress team. Better luck next time!")) + to_chat(M.current, span_warning("Вас не выбрали в команду. Повезет в следующий раз!")) message_admins("Distress beacon: [length(valid_candidates)] valid candidates were not selected.") else picked_candidates = valid_candidates // save some time message_admins("Distress beacon: All valid candidates were selected.") if(announce) - priority_announce(dispatch_message, "Distress Beacon", sound = 'sound/AI/distressreceived.ogg') + priority_announce(dispatch_message, "Сигнал Бедствия", sound = 'sound/AI/distressreceived.ogg') message_admins("Distress beacon: [name] finalized, starting spawns.") diff --git a/code/datums/gamemodes/crash.dm b/code/datums/gamemodes/crash.dm index dc2df2e9f2c..36629b372ed 100644 --- a/code/datums/gamemodes/crash.dm +++ b/code/datums/gamemodes/crash.dm @@ -121,14 +121,7 @@ /datum/game_mode/infestation/crash/announce() to_chat(world, span_round_header("The current map is - [SSmapping.configs[GROUND_MAP].map_name]!")) - priority_announce( - message = "Scheduled for landing in T-10 Minutes. Prepare for landing. Known hostiles near LZ. Detonation Protocol Active, planet disposable. Marines disposable.", - title = "Good morning, marines.", - type = ANNOUNCEMENT_PRIORITY, - color_override = "red" - ) - playsound(shuttle, 'sound/machines/warning-buzzer.ogg', 75, 0, 30) - + priority_announce("Высадка запланирована через 10 минут. Приготовьтесь к посадке. Предварительное сканирование показывает наличие агрессивных форм биологической жизни. Ваша следующая миссия - заполучить коды доступа и активировать ядерную боеголовку.", title = "Доброе утро, товарищи!", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/crash_start.ogg', color_override = "red") /datum/game_mode/infestation/crash/process() . = ..() diff --git a/code/datums/gamemodes/infestation.dm b/code/datums/gamemodes/infestation.dm index 3628fb64391..f78be8ff1be 100644 --- a/code/datums/gamemodes/infestation.dm +++ b/code/datums/gamemodes/infestation.dm @@ -28,12 +28,12 @@ new /obj/structure/mineral_door/resin(i) for(var/i in GLOB.xeno_tunnel_spawn_turfs) var/obj/structure/xeno/tunnel/new_tunnel = new /obj/structure/xeno/tunnel(i, XENO_HIVE_NORMAL) - new_tunnel.name = "[get_area_name(new_tunnel)] tunnel" + new_tunnel.name = "[get_area_name(new_tunnel)] туннель" new_tunnel.tunnel_desc = "["[get_area_name(new_tunnel)]"] (X: [new_tunnel.x], Y: [new_tunnel.y])" for(var/i in GLOB.xeno_jelly_pod_turfs) new /obj/structure/xeno/resin_jelly_pod(i, XENO_HIVE_NORMAL) for(var/i in GLOB.xeno_turret_turfs) - new /obj/structure/xeno/xeno_turret(i, XENO_HIVE_NORMAL) + new /obj/structure/xeno/turret(i, XENO_HIVE_NORMAL) /datum/game_mode/infestation/process() if(round_finished) @@ -46,7 +46,7 @@ // make sure you don't turn 0 into a false positive #define BIOSCAN_DELTA(count, delta) count ? max(0, count + rand(-delta, delta)) : 0 -#define BIOSCAN_LOCATION(show_locations, location) (show_locations && location ? ", including one in [hostLocationP]":"") +#define BIOSCAN_LOCATION(show_locations, location) (show_locations && location ? ", включая одного в [hostLocationP]":"") #define AI_SCAN_DELAY 15 SECONDS @@ -57,10 +57,10 @@ #ifndef TESTING var/mob/living/silicon/ai/bioscanning_ai = usr if((bioscanning_ai.last_ai_bioscan + COOLDOWN_AI_BIOSCAN) > world.time) - to_chat(bioscanning_ai, "Bioscan instruments are still recalibrating from their last use.") + to_chat(bioscanning_ai, "Приборы биосканирования все еще проходят перекалибровку с момента последнего использования.") return bioscanning_ai.last_ai_bioscan = world.time - to_chat(bioscanning_ai, span_warning("Scanning for hostile lifeforms...")) + to_chat(bioscanning_ai, span_warning("Сканирование на предмет наличия враждебных форм жизни...")) if(!do_after(usr, AI_SCAN_DELAY, NONE, usr, BUSY_ICON_GENERIC)) //initial windup time until firing begins bioscanning_ai.last_ai_bioscan = 0 return @@ -110,51 +110,51 @@ var/mob/M = i SEND_SOUND(M, S) to_chat(M, assemble_alert( - title = "Queen Mother Report", - subtitle = "The Queen Mother reaches into your mind...", - message = "To my children and their Queen,
I sense [numHostsShipr ? "approximately [numHostsShipr]":"no"] host[numHostsShipr > 1 ? "s":""] in the metal hive[BIOSCAN_LOCATION(show_locations, hostLocationS)], [numHostsPlanet || "none"] scattered elsewhere[BIOSCAN_LOCATION(show_locations, hostLocationP)] and [numHostsTransitr ? "approximately [numHostsTransitr]":"no"] host[numHostsTransitr > 1 ? "s":""] on the metal bird in transit.", + title = "Сообщение от Главной Королевы", + subtitle = "Главная Королева проникает в ваш разум с расстояния в сотни миров...", + message = "Мои дети и их Королева, я [numHostsShipr ? "":"не"] чувствую [numHostsShipr ? "примерно [numHostsShipr]":""] потенциальных носителей в их металлическом улье [BIOSCAN_LOCATION(show_locations, hostLocationS)], за его пределами их ["всего [numHostsPlanet]" || "нет"] [BIOSCAN_LOCATION(show_locations, hostLocationP)] и [numHostsTransitr ? "примерно [numHostsTransitr]":"вообще нету"] на металлической птице.", color_override = "purple" )) - var/name = "[MAIN_AI_SYSTEM] Bioscan Status" - var/input = {"Bioscan complete. Sensors indicate [numXenosShip || "no"] unknown lifeform signature[numXenosShip > 1 ? "s":""] present on the ship[BIOSCAN_LOCATION(show_locations, xenoLocationS)], [numXenosPlanetr ? "approximately [numXenosPlanetr]":"no"] signature[numXenosPlanetr > 1 ? "s":""] located elsewhere[BIOSCAN_LOCATION(show_locations, xenoLocationP)] and [numXenosTransit || "no"] unknown lifeform signature[numXenosTransit > 1 ? "s":""] in transit."} - var/ai_name = "[usr] Bioscan Status" + var/name = "[MAIN_AI_SYSTEM]: Статус Биосканирования" + var/input = {"Биосканирование завершено. Датчики показывают [numXenosShip || "отсуствие"] неизвестных форм жизни на корабле[BIOSCAN_LOCATION(show_locations, xenoLocationS)], [numXenosPlanetr ? "примерно [numXenosPlanetr]":"отсуствие"] сигнатур на земле[BIOSCAN_LOCATION(show_locations, xenoLocationP)] и [numXenosTransit || "отсуствие"] неизвестных форм жизни на шаттлах."} + var/ai_name = "[usr]: Статус Биосканирования" if(ai_operator) priority_announce(input, ai_name, sound = 'sound/AI/bioscan.ogg', color_override = "grey", receivers = (GLOB.alive_human_list + GLOB.ai_list)) - log_game("Bioscan. Humans: [numHostsPlanet] on the planet[hostLocationP ? " Location:[hostLocationP]":""] and [numHostsShip] on the ship.[hostLocationS ? " Location: [hostLocationS].":""] Xenos: [numXenosPlanetr] on the planet and [numXenosShip] on the ship[xenoLocationP ? " Location:[xenoLocationP]":""] and [numXenosTransit] in transit.") + log_game("Биосканирование. Люди: [numHostsPlanet] на земле[hostLocationP ? " Место:[hostLocationP]":""] и [numHostsShip] на корабле.[hostLocationS ? " Место: [hostLocationS].":""] Ксеноморфы: [numXenosPlanetr] на земле и [numXenosShip] на корабле[xenoLocationP ? " Место:[xenoLocationP]":""] и [numXenosTransit] на перелётах.") switch(GLOB.current_orbit) if(1) - to_chat(usr, span_warning("Signal analysis reveals excellent detail about hostile movements and numbers.")) + to_chat(usr, span_warning("Анализ сигналов позволяет получить подробную информацию о передвижениях противника и его численности.")) return if(3) - to_chat(usr, span_warning("Minor corruption detected in our bioscan instruments due to ship elevation, some information about hostile activity may be incorrect.")) + to_chat(usr, span_warning("В наших приборах биосканирования обнаружены незначительные ошибки из-за подъема судна, некоторая информация о враждебной активности может быть неверной.")) return if(5) - to_chat(usr, span_warning("Major corruption detected in our bioscan readings due to ship elevation, information heavily corrupted.")) + to_chat(usr, span_warning("В наших показаниях биосканирования обнаружены серьезные ошибки из-за уровня орбиты корабля, информация может сильно отличаться от правды.")) return if(announce_humans) priority_announce(input, name, sound = 'sound/AI/bioscan.ogg', color_override = "grey", receivers = (GLOB.alive_human_list + GLOB.ai_list)) // Hide this from observers, they have their own detailed alert. if(send_fax) - var/fax_message = generate_templated_fax("Combat Information Center", "[MAIN_AI_SYSTEM] Bioscan Status", "", input, "", MAIN_AI_SYSTEM) - send_fax(null, null, "Combat Information Center", "[MAIN_AI_SYSTEM] Bioscan Status", fax_message, FALSE) + var/fax_message = generate_templated_fax("Боевой Информационный Центр", "[MAIN_AI_SYSTEM]: Статус Биосканирования", "", input, "", MAIN_AI_SYSTEM) + send_fax(null, null, "Боевой Информационный Центр", "[MAIN_AI_SYSTEM]: Статус Биосканирования", fax_message, FALSE) - log_game("Bioscan. Humans: [numHostsPlanet] on the planet[hostLocationP ? " Location:[hostLocationP]":""] and [numHostsShip] on the ship.[hostLocationS ? " Location: [hostLocationS].":""] Xenos: [numXenosPlanetr] on the planet and [numXenosShip] on the ship[xenoLocationP ? " Location:[xenoLocationP]":""] and [numXenosTransit] in transit.") + log_game("Биосканирование. Люди: [numHostsPlanet] на земле[hostLocationP ? " Место:[hostLocationP]":""] и [numHostsShip] на корабле.[hostLocationS ? " Место: [hostLocationS].":""] Ксеноморфы: [numXenosPlanetr] на земле и [numXenosShip] на корабле[xenoLocationP ? " Место:[xenoLocationP]":""] и [numXenosTransit] на перелётах.") for(var/i in GLOB.observer_list) var/mob/M = i to_chat(M, assemble_alert( - title = "Detailed Bioscan", - message = {"[numXenosPlanet] xeno\s on the planet. -[numXenosShip] xeno\s on the ship. -[numXenosTransit] xeno\s in transit. - -[numHostsPlanet] human\s on the planet. -[numHostsShip] human\s on the ship. -[numHostsTransit] human\s in transit."}, + title = "Детальная Информация", + message = {"[numXenosPlanet] ксеноморфов на земле. +[numXenosShip] ксеноморфов на корабле. +[numXenosTransit] ксеноморфов на перелётах. + +[numHostsPlanet] людей на земле. +[numHostsShip] людей на корабле. +[numHostsTransit] людей на перелётах."}, color_override = "purple" )) @@ -178,37 +178,37 @@ var/num_humans_ship = living_player_list[3] if(SSevacuation.dest_status == NUKE_EXPLOSION_FINISHED) - message_admins("Round finished: [MODE_GENERIC_DRAW_NUKE]") //ship blows, no one wins + message_admins("Раунд завершен: [MODE_GENERIC_DRAW_NUKE]") //ship blows, no one wins round_finished = MODE_GENERIC_DRAW_NUKE return TRUE if(round_stage == INFESTATION_DROPSHIP_CAPTURED_XENOS) - message_admins("Round finished: [MODE_INFESTATION_X_MINOR]") + message_admins("Раунд завершен: [MODE_INFESTATION_X_MINOR]") round_finished = MODE_INFESTATION_X_MINOR return TRUE if(!num_humans) if(!num_xenos) - message_admins("Round finished: [MODE_INFESTATION_DRAW_DEATH]") //everyone died at the same time, no one wins + message_admins("Раунд завершен: [MODE_INFESTATION_DRAW_DEATH]") //everyone died at the same time, no one wins round_finished = MODE_INFESTATION_DRAW_DEATH return TRUE - message_admins("Round finished: [MODE_INFESTATION_X_MAJOR]") //xenos wiped out ALL the marines without hijacking, xeno major victory + message_admins("Раунд завершен: [MODE_INFESTATION_X_MAJOR]") //xenos wiped out ALL the marines without hijacking, xeno major victory round_finished = MODE_INFESTATION_X_MAJOR return TRUE if(!num_xenos) if(round_stage == INFESTATION_MARINE_CRASHING) - message_admins("Round finished: [MODE_INFESTATION_M_MINOR]") //marines lost the ground operation but managed to wipe out Xenos on the ship at a greater cost, minor victory + message_admins("Раунд завершен: [MODE_INFESTATION_M_MINOR]") //marines lost the ground operation but managed to wipe out Xenos on the ship at a greater cost, minor victory round_finished = MODE_INFESTATION_M_MINOR return TRUE - message_admins("Round finished: [MODE_INFESTATION_M_MAJOR]") //marines win big + message_admins("Раунд завершен: [MODE_INFESTATION_M_MAJOR]") //marines win big round_finished = MODE_INFESTATION_M_MAJOR return TRUE if(round_stage == INFESTATION_MARINE_CRASHING && !num_humans_ship) if(SSevacuation.human_escaped > SSevacuation.initial_human_on_ship * 0.5) - message_admins("Round finished: [MODE_INFESTATION_X_MINOR]") //xenos have control of the ship, but most marines managed to flee + message_admins("Раунд завершен: [MODE_INFESTATION_X_MINOR]") //xenos have control of the ship, but most marines managed to flee round_finished = MODE_INFESTATION_X_MINOR return - message_admins("Round finished: [MODE_INFESTATION_X_MAJOR]") //xenos wiped our marines, xeno major victory + message_admins("Раунд завершен: [MODE_INFESTATION_X_MAJOR]") //xenos wiped our marines, xeno major victory round_finished = MODE_INFESTATION_X_MAJOR return TRUE return FALSE @@ -279,7 +279,7 @@ SEND_SOUND(M, ghost_track) - log_game("[round_finished]\nGame mode: [name]\nRound time: [duration2text()]\nEnd round player population: [length(GLOB.clients)]\nTotal xenos spawned: [GLOB.round_statistics.total_xenos_created]\nTotal humans spawned: [GLOB.round_statistics.total_humans_created]") + log_game("[round_finished]\nРежим: [name]\nВремя раунда: [duration2text()]\nКоличество игроков в конце раунда: [length(GLOB.clients)]\nРождено ксеноморфов: [GLOB.round_statistics.total_xenos_created]\nПроизведено людей: [GLOB.round_statistics.total_humans_created]") /datum/game_mode/infestation/can_start(bypass_checks = FALSE) . = ..() @@ -296,7 +296,7 @@ xeno_candidate = TRUE break if(!xeno_candidate && !bypass_checks) - to_chat(world, "Unable to start [name]. No xeno candidate found.") + to_chat(world, "Невозможно начать [name]. Кандидат в ксеносы не найден.") return FALSE /datum/game_mode/infestation/pre_setup() @@ -309,9 +309,9 @@ return priority_announce( - title = "High Command Update", - subtitle = "Good morning, marines.", - message = "Cryosleep disengaged by TGMC High Command.

ATTN: [SSmapping.configs[SHIP_MAP].map_name].
[SSmapping.configs[GROUND_MAP].announce_text]", + title = "Оповещение Высшего Командования", + subtitle = "Доброе утро, товарищи!", + message = "Криосон отключен генштабом.

ATTN: [SSmapping.configs[SHIP_MAP].map_name].
[SSmapping.configs[GROUND_MAP].announce_text]", color_override = "red" ) @@ -330,7 +330,7 @@ /datum/game_mode/infestation/proc/on_nuclear_diffuse(obj/machinery/nuclearbomb/bomb, mob/living/carbon/xenomorph/X) SIGNAL_HANDLER - priority_announce("WARNING. WARNING. Planetary Nuke deactivated. WARNING. WARNING. Self destruct failed. WARNING. WARNING.", "Planetary Warhead Disengaged", type = ANNOUNCEMENT_PRIORITY) + priority_announce("ВНИМАНИЕ. ВНИМАНИЕ. Планетарная ядерная бомба деактивирована. ВНИМАНИЕ. ВНИМАНИЕ. Самоуничтожение не удалось. ВНИМАНИЕ. ВНИМАНИЕ.", type = ANNOUNCEMENT_PRIORITY) /datum/game_mode/infestation/proc/on_nuclear_explosion(datum/source, z_level) SIGNAL_HANDLER @@ -341,12 +341,12 @@ SIGNAL_HANDLER var/datum/hive_status/normal/HS = GLOB.hive_datums[XENO_HIVE_NORMAL] var/area_name = get_area_name(nuke) - HS.xeno_message("An overwhelming wave of dread ripples throughout the hive... A nuke has been activated[area_name ? " in [area_name]":""]!") + HS.xeno_message("Волна ужаса прокатывается по улью... Они активировали ядерную бомбу[area_name ? " в [area_name]":""]!") HS.set_all_xeno_trackers(nuke) /datum/game_mode/infestation/proc/play_cinematic(z_level) GLOB.enter_allowed = FALSE - priority_announce("DANGER. DANGER. Planetary Nuke Activated. DANGER. DANGER. Self destruct in progress. DANGER. DANGER.", "Planetary Warhead Detonation Confirmed", type = ANNOUNCEMENT_PRIORITY) + priority_announce("ТРЕВОГА. ТРЕВОГА. Активирована планетарная ядерная бомба. ТРЕВОГА. ТРЕВОГА. Идет самоуничтожение. ТРЕВОГА. ТРЕВОГА.", "Планетарная Боеголовка Успешно Запущена", type = ANNOUNCEMENT_PRIORITY) var/sound/S = sound(pick('sound/theme/nuclear_detonation1.ogg','sound/theme/nuclear_detonation2.ogg'), channel = CHANNEL_CINEMATIC) SEND_SOUND(world, S) diff --git a/code/datums/greyscale/greyscale_configs.dm b/code/datums/greyscale/greyscale_configs.dm index 4c00fbf565d..a340189aac0 100644 --- a/code/datums/greyscale/greyscale_configs.dm +++ b/code/datums/greyscale/greyscale_configs.dm @@ -255,7 +255,7 @@ ///AMMO - for both bullets and magazines /datum/greyscale_config/ammo json_config = 'code/datums/greyscale/json_configs/ammo.json' - icon_file = 'icons/obj/items/ammo.dmi' + icon_file = 'icons/obj/items/ammo/misc.dmi' ///PROJECTILES /datum/greyscale_config/projectile diff --git a/code/datums/jobs/job/clown.dm b/code/datums/jobs/job/clown.dm index 82e737790e5..742d3881c37 100644 --- a/code/datums/jobs/job/clown.dm +++ b/code/datums/jobs/job/clown.dm @@ -4,7 +4,6 @@ /datum/skills/civilian/clown name = CLOWN cqc = SKILL_CQC_MASTER - police = SKILL_CQC_DEFAULT medical = SKILL_MEDICAL_UNTRAINED firearms = SKILL_FIREARMS_UNTRAINED melee_weapons = SKILL_MELEE_TRAINED @@ -14,8 +13,43 @@ paygrade = "CLW" comm_title = "CLW" total_positions = 0 - access = list(ACCESS_MARINE_PREP, ACCESS_MARINE_MEDBAY, ACCESS_MARINE_CARGO, ACCESS_CIVILIAN_ENGINEERING, ACCESS_CIVILIAN_MEDICAL, ACCESS_CIVILIAN_RESEARCH) - minimal_access = ALL_MARINE_ACCESS + access = list( + ACCESS_MARINE_ALPHA, + ACCESS_MARINE_BRAVO, + ACCESS_MARINE_CHARLIE, + ACCESS_MARINE_DELTA, + ACCESS_MARINE_PREP, + ACCESS_MARINE_ROBOT, + ACCESS_MARINE_ENGPREP, + ACCESS_MARINE_SMARTPREP, + ACCESS_MARINE_MEDPREP, + ACCESS_MARINE_MEDBAY, + ACCESS_MARINE_CHEMISTRY, + ACCESS_CIVILIAN_MEDICAL, + ACCESS_CIVILIAN_RESEARCH, + ACCESS_CIVILIAN_ENGINEERING, + ACCESS_MARINE_ENGINEERING, + ACCESS_MARINE_LEADER, + ) + minimal_access = list( + ACCESS_MARINE_ALPHA, + ACCESS_MARINE_BRAVO, + ACCESS_MARINE_CHARLIE, + ACCESS_MARINE_DELTA, + ACCESS_MARINE_PREP, + ACCESS_MARINE_DROPSHIP, + ACCESS_MARINE_ROBOT, + ACCESS_MARINE_ENGPREP, + ACCESS_MARINE_SMARTPREP, + ACCESS_MARINE_MEDPREP, + ACCESS_MARINE_MEDBAY, + ACCESS_MARINE_CHEMISTRY, + ACCESS_CIVILIAN_MEDICAL, + ACCESS_CIVILIAN_RESEARCH, + ACCESS_CIVILIAN_ENGINEERING, + ACCESS_MARINE_ENGINEERING, + ACCESS_MARINE_LEADER, + ) skills_type = /datum/skills/civilian/clown display_order = JOB_DISPLAY_ORDER_CLOWN outfit = /datum/outfit/job/civilian/clown diff --git a/code/datums/jobs/job/job.dm b/code/datums/jobs/job/job.dm index 0d6d9437bb6..202deec3d26 100644 --- a/code/datums/jobs/job/job.dm +++ b/code/datums/jobs/job/job.dm @@ -181,18 +181,18 @@ GLOBAL_PROTECT(exp_specialmap) /datum/outfit/job/proc/handle_id(mob/living/carbon/human/H, client/override_client) var/datum/job/job = H.job ? H.job : SSjob.GetJobType(jobtype) var/obj/item/card/id/id = H.wear_id - if(istype(id)) - id.access = job.get_access() - id.iff_signal = GLOB.faction_to_iff[job.faction] - shuffle_inplace(id.access) // Shuffle access list to make NTNet passkeys less predictable - id.registered_name = H.real_name - id.assignment = job.title - id.rank = job.title - id.paygrade = job.paygrade - id.update_label() - if(H.mind?.initial_account) // In most cases they won't have a mind at this point. - id.associated_account_number = H.mind.initial_account.account_number - H.update_action_buttons() + if(!istype(id)) + return + id.access = job.get_access() + id.iff_signal = GLOB.faction_to_iff[job.faction] + shuffle_inplace(id.access) // Shuffle access list to make NTNet passkeys less predictable + id.registered_name = H.real_name + id.assignment = job.title + id.rank = job.title + id.paygrade = job.paygrade + id.update_label() + if(H.mind?.initial_account) // In most cases they won't have a mind at this point. + id.associated_account_number = H.mind.initial_account.account_number /datum/job/proc/get_special_name(client/preference_source) return @@ -222,8 +222,9 @@ GLOBAL_PROTECT(exp_specialmap) var/datum/job/scaled_job = SSjob.GetJobType(index) if(!(scaled_job in SSjob.active_joinable_occupations)) continue - scaled_job.add_job_points(-jobworth[index]) + scaled_job.remove_job_points(jobworth[index]) +///Adds to job points, adding a new slot if threshold reached /datum/job/proc/add_job_points(amount) job_points += amount if(total_positions >= max_positions) @@ -232,6 +233,17 @@ GLOBAL_PROTECT(exp_specialmap) job_points -= job_points_needed add_job_positions(1) +///Removes job points, and if needed, job positions +/datum/job/proc/remove_job_points(amount) + if(job_points_needed == INFINITY || total_positions == -1) + return + if(job_points >= amount) + job_points -= amount + return + var/job_slots_removed = ROUND_UP((amount - job_points) / job_points_needed) + remove_job_positions(job_slots_removed) + job_points += (job_slots_removed * job_points_needed) - amount + /datum/job/proc/add_job_positions(amount) if(!(job_flags & (JOB_FLAG_LATEJOINABLE|JOB_FLAG_ROUNDSTARTJOINABLE))) CRASH("add_job_positions called for a non-joinable job") diff --git a/code/datums/jobs/job/militarypolice.dm b/code/datums/jobs/job/militarypolice.dm index 2eb8aeabbce..5b3ca4f89a2 100644 --- a/code/datums/jobs/job/militarypolice.dm +++ b/code/datums/jobs/job/militarypolice.dm @@ -84,12 +84,6 @@ In addition, you are tasked with the security of high-ranking personnel, includi wear_suit = /obj/item/clothing/suit/armor/bulletproof/mp suit_store = /obj/item/weapon/gun/energy/taser -/obj/item/radio/headset/mainship/mp - icon = 'icons/obj/items/radio.dmi' - name = "security radio headset" - icon_state = "mp_headset" - keyslot = /obj/item/encryptionkey/mcom - /obj/item/storage/pouch/pistol/laserpistol/Initialize() . = ..() new /obj/item/weapon/gun/energy/lasgun/lasrifle/standard_marine_pistol/tactical(src) diff --git a/code/datums/jobs/job/other.dm b/code/datums/jobs/job/other.dm index f3cab152069..37d00fdcd2e 100644 --- a/code/datums/jobs/job/other.dm +++ b/code/datums/jobs/job/other.dm @@ -66,6 +66,7 @@ gloves = /obj/item/clothing/gloves/marine/officer/chief/sa glasses = /obj/item/clothing/glasses/sunglasses/sa/nodrop back = /obj/item/storage/backpack/marine/satchel + ears = /obj/item/radio/headset/mainship/spatial /datum/job/spatial_agent/galaxy_red outfit = /datum/outfit/job/other/spatial_agent/galaxy_red diff --git a/code/datums/jobs/squads.dm b/code/datums/jobs/squads.dm index 699fa9ffd34..b002e9f2910 100644 --- a/code/datums/jobs/squads.dm +++ b/code/datums/jobs/squads.dm @@ -108,7 +108,7 @@ CRASH("attempted to insert marine [new_squaddie] into squad while already having one") if(!(new_squaddie.job.title in current_positions)) - CRASH("Attempted to insert [new_squaddie.job.title] into squad [name]") + return FALSE current_positions[new_squaddie.job.title]++ @@ -144,7 +144,6 @@ marines_list += new_squaddie new_squaddie.assigned_squad = src new_squaddie.hud_set_job(faction) - new_squaddie.update_action_buttons() new_squaddie.update_inv_head() new_squaddie.update_inv_wear_suit() return TRUE @@ -192,7 +191,6 @@ leaving_squaddie.assigned_squad = null leaving_squaddie.hud_set_job(faction) - leaving_squaddie.update_action_buttons() leaving_squaddie.update_inv_head() leaving_squaddie.update_inv_wear_suit() return TRUE @@ -222,7 +220,6 @@ to_chat(squad_leader, "You're no longer the Squad Leader for [src]!") var/mob/living/carbon/human/H = squad_leader squad_leader = null - H.update_action_buttons() H.hud_set_job(faction) H.update_inv_head() H.update_inv_wear_suit() @@ -251,7 +248,6 @@ R.use_command = TRUE squad_leader.hud_set_job(faction) - squad_leader.update_action_buttons() squad_leader.update_inv_head() squad_leader.update_inv_wear_suit() to_chat(squad_leader, "You're now the Squad Leader for [src]!") diff --git a/code/datums/keybinding/living.dm b/code/datums/keybinding/living.dm index 71bbcfc89fa..19ff5eb2114 100644 --- a/code/datums/keybinding/living.dm +++ b/code/datums/keybinding/living.dm @@ -19,7 +19,7 @@ return TRUE /datum/keybinding/living/attempt_jump - hotkey_keys = list("Space") + hotkey_keys = list("V") name = "Jump" full_name = "Jump" description = "Jumps, if your mob is capable of doing so." diff --git a/code/datums/keybinding/xeno.dm b/code/datums/keybinding/xeno.dm index 3da0d1412c6..bbc16c25300 100644 --- a/code/datums/keybinding/xeno.dm +++ b/code/datums/keybinding/xeno.dm @@ -379,6 +379,20 @@ keybind_signal = COMSIG_XENOABILITY_FORTIFY hotkey_keys = list("Space") +/datum/keybinding/xeno/headbutt + name = "headbutt" + full_name = "Steel Crest: Headbutt" + description = "Headbutts into the designated target." + keybind_signal = COMSIG_XENOABILITY_STEELCREST_HEADBUTT + hotkey_keys = list("F") + +/datum/keybinding/xeno/soak + name = "soak" + full_name = "Steel Crest: Soak" + description = "Healing after taking damage" + keybind_signal = COMSIG_XENOABILITY_STEELCREST_SOAK + hotkey_keys = list("E") + /datum/keybinding/xeno/regenerate_skin name = "regenerate_skin" full_name = "Defender: Regenerate Skin" diff --git a/code/datums/marine_main_ship.dm b/code/datums/marine_main_ship.dm index 9207b0ad5e7..1f7885d9c32 100644 --- a/code/datums/marine_main_ship.dm +++ b/code/datums/marine_main_ship.dm @@ -14,11 +14,11 @@ GLOBAL_DATUM_INIT(marine_main_ship, /datum/marine_main_ship, new) /datum/marine_main_ship/proc/make_maint_all_access() maint_all_access = TRUE - priority_announce("The maintenance access requirement has been revoked on all airlocks.", "Attention!", "Shipside emergency declared.", sound = 'sound/misc/notice1.ogg', color_override = "grey") + priority_announce("Требование доступа для всех технических тоннелей отменено.", "Внимание!", "На корабле объявлена чрезвычайная ситуация.", sound = 'sound/misc/notice1.ogg', color_override = "grey") /datum/marine_main_ship/proc/revoke_maint_all_access() maint_all_access = FALSE - priority_announce("The maintenance access requirement has been readded on all maintenance airlocks.", "Attention!", "Shipside emergency revoked.", sound = 'sound/misc/notice2.ogg', color_override = "grey") + priority_announce("Требование доступа для всех технических тоннелей было возвращено.", "Внимание!", "Отбой Тревоги.", sound = 'sound/misc/notice2.ogg', color_override = "grey") /datum/marine_main_ship/proc/set_security_level(level, announce = TRUE) switch(level) @@ -79,7 +79,7 @@ GLOBAL_DATUM_INIT(marine_main_ship, /datum/marine_main_ship, new) switch(level) if(SEC_LEVEL_GREEN) if(announce) - priority_announce("Attention: Security level lowered to GREEN - all clear.", title = "Security Level Lowered", subtitle = "All Clear", sound = 'sound/AI/code_green.ogg', color_override = "green") + priority_announce("Всё стабильно.", title = "Код Зеленый", sound = 'sound/AI/code_green.ogg', color_override = "green") security_level = SEC_LEVEL_GREEN for(var/obj/machinery/status_display/SD in GLOB.machines) if(is_mainship_level(SD.z)) @@ -87,10 +87,10 @@ GLOBAL_DATUM_INIT(marine_main_ship, /datum/marine_main_ship, new) if(SEC_LEVEL_BLUE) if(security_level < SEC_LEVEL_BLUE) if(announce) - priority_announce("Attention: Security level elevated to BLUE - potentially hostile activity on board.", title = "Security Level Elevated", sound = 'sound/AI/code_blue_elevated.ogg') + priority_announce("На борту потенциально враждебная деятельность. Требуются тщательные проверки.", title = "Код Синий", sound = 'sound/AI/code_blue_elevated.ogg') else if(announce) - priority_announce("Attention: Security level lowered to BLUE - potentially hostile activity on board.", title = "Security Level Lowered", sound = 'sound/AI/code_blue_lowered.ogg') + priority_announce("Возможны остатки враждебной деятельности. Требуются тщательные проверки.", title = "Код Синий", sound = 'sound/AI/code_blue_lowered.ogg') security_level = SEC_LEVEL_BLUE for(var/obj/machinery/status_display/SD in GLOB.machines) if(is_mainship_level(SD.z)) @@ -98,10 +98,10 @@ GLOBAL_DATUM_INIT(marine_main_ship, /datum/marine_main_ship, new) if(SEC_LEVEL_RED) if(security_level < SEC_LEVEL_RED) if(announce) - priority_announce("Attention: Security level elevated to RED - there is an immediate threat to the ship.", title = "Security Level Elevated", sound = 'sound/AI/code_red_elevated.ogg', color_override = "red") + priority_announce("Существует непосредственная угроза судну. Боеспособному персоналу надлежит организовать защиту экипажа.", title = "Код Красный", sound = 'sound/AI/code_red_elevated.ogg', color_override = "red") else if(announce) - priority_announce("Attention: Security level lowered to RED - there is an immediate threat to the ship.", title = "Ship Destruction Averted", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/code_red_lowered.ogg', color_override = "red") + priority_announce("Существует непосредственная угроза судну. Боеспособному персоналу требуется разобраться с остальными проблемами.", title = "Код Красный", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/code_red_lowered.ogg', color_override = "red") /* var/area/A for(var/obj/machinery/power/apc/O in machines) @@ -119,8 +119,8 @@ GLOBAL_DATUM_INIT(marine_main_ship, /datum/marine_main_ship, new) if(announce) priority_announce( type = ANNOUNCEMENT_PRIORITY, - title = "Ship Destruction Imminent", - message = "Attention! Delta security level reached! " + CONFIG_GET(string/alert_delta), + title = "Код Дельта", + message = "Контроль над ситуацией полностью потерян. Всему персоналу требуется сделать всё ради предотвращения распространения опасности на другие объекты.", sound = 'sound/misc/airraid.ogg', channel_override = SSsounds.random_available_channel(), color_override = "purple" diff --git a/code/datums/outfit.dm b/code/datums/outfit.dm index bd9ced9abe7..65bae3aad70 100644 --- a/code/datums/outfit.dm +++ b/code/datums/outfit.dm @@ -105,7 +105,6 @@ H.update_body() return TRUE - /datum/outfit/proc/get_json_data() . = list() .["outfit_type"] = type diff --git a/code/datums/progressbar.dm b/code/datums/progressbar.dm index 152bafcf868..c7c6391722c 100644 --- a/code/datums/progressbar.dm +++ b/code/datums/progressbar.dm @@ -260,3 +260,6 @@ /image/progdisplay/energy icon_state = "busy_energy" + +/image/progdisplay/facehugger + icon_state = "busy_facehugger" diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index eec57534341..f2c4b73dc51 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1371,7 +1371,7 @@ /datum/status_effect/upgrade_trail/proc/do_acid_trail() SIGNAL_HANDLER - if(buff_owner.incapacitated(TRUE)) + if(buff_owner.incapacitated(TRUE) || buff_owner.status_flags & INCORPOREAL || buff_owner.is_ventcrawling) return if(prob(base_chance + chance_per_chamber * chamber_scaling)) var/turf/T = get_turf(buff_owner) diff --git a/code/game/objects/effects/landmarks/landmarks.dm b/code/game/objects/effects/landmarks/landmarks.dm index 129a4de7528..7ead8c0d094 100644 --- a/code/game/objects/effects/landmarks/landmarks.dm +++ b/code/game/objects/effects/landmarks/landmarks.dm @@ -172,7 +172,7 @@ /obj/effect/landmark/xeno_resin_wall/Initialize(mapload) GLOB.xeno_resin_wall_turfs += loc - ..() + . = ..() return INITIALIZE_HINT_QDEL /obj/effect/landmark/xeno_silo_spawn @@ -192,7 +192,7 @@ /obj/effect/landmark/xeno_tunnel_spawn/Initialize(mapload) GLOB.xeno_tunnel_spawn_turfs += loc - ..() + . = ..() return INITIALIZE_HINT_QDEL /obj/effect/landmark/resin_jelly_pod @@ -202,17 +202,17 @@ /obj/effect/landmark/resin_jelly_pod/Initialize(mapload) GLOB.xeno_jelly_pod_turfs += loc - ..() + . = ..() return INITIALIZE_HINT_QDEL /obj/effect/landmark/xeno_turret name = "xeno turret landmark" icon = 'icons/Xeno/acidturret.dmi' - icon_state = XENO_TURRET_ACID_ICONSTATE + icon_state = "acid_turret" /obj/effect/landmark/xeno_turret/Initialize(mapload) GLOB.xeno_turret_turfs += loc - ..() + . = ..() return INITIALIZE_HINT_QDEL /obj/effect/landmark/nuke_spawn @@ -229,7 +229,7 @@ /obj/effect/landmark/dropship_start_location/Initialize(mapload) GLOB.minidropship_start_loc = loc - ..() + . = ..() return INITIALIZE_HINT_QDEL /obj/effect/landmark/weapon_spawn @@ -464,10 +464,11 @@ /obj/effect/landmark/weapon_spawn/tier6_weapon_spawn name = "Tier meme Weapon Spawn" icon_state = "weapon6" - weapon_list = list( /obj/item/weapon/gun/pistol/chimp, - /obj/item/weapon/banhammer, - /obj/item/weapon/chainsword, - ) + weapon_list = list( + /obj/item/weapon/gun/pistol/chimp, + /obj/item/weapon/banhammer, + /obj/item/weapon/chainsword, + ) /obj/effect/landmark/sensor_tower name = "Sensor tower" @@ -475,7 +476,7 @@ icon_state = "sensor_loyalist" /obj/effect/landmark/sensor_tower/Initialize(mapload) - ..() + . = ..() GLOB.sensor_towers += loc return INITIALIZE_HINT_QDEL @@ -516,7 +517,7 @@ icon_state = "pinonfar" /obj/effect/landmark/xenoden_docking_port/Initialize(mapload) - ..() + . = ..() GLOB.xenoden_docking_ports_locs += loc return INITIALIZE_HINT_QDEL @@ -526,7 +527,7 @@ icon_state = "weed_silo" /obj/effect/landmark/xenoden_core/Initialize(mapload) - ..() + . = ..() GLOB.xenoden_cores_locs += loc return INITIALIZE_HINT_QDEL @@ -536,7 +537,7 @@ icon_state = "sensor" /obj/effect/landmark/sensor_tower_infestation_ground/Initialize(mapload) - ..() + . = ..() GLOB.sensor_towers_infestation_ground += loc return INITIALIZE_HINT_QDEL @@ -546,7 +547,7 @@ icon_state = "sensor" /obj/effect/landmark/sensor_tower_infestation_caves/Initialize(mapload) - ..() + . = ..() GLOB.sensor_towers_infestation_caves += loc return INITIALIZE_HINT_QDEL @@ -556,7 +557,7 @@ icon_state = "comm_tower" /obj/effect/landmark/tower_relay/Initialize(mapload) - ..() + . = ..() GLOB.tower_relay_locs += loc return INITIALIZE_HINT_QDEL diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 527fd5fce96..b2122619c6a 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -155,7 +155,7 @@ GLOBAL_LIST_EMPTY(blood_particles) icon = 'icons/Marine/marine-items.dmi' var/icon_state_on hud_possible = list(SQUAD_HUD_TERRAGOV, SQUAD_HUD_SOM) - duration = ORDER_DURATION + duration = CIC_ORDER_DURATION layer = TURF_LAYER /obj/effect/temp_visual/order/Initialize(mapload, faction) @@ -186,7 +186,7 @@ GLOBAL_LIST_EMPTY(blood_particles) /obj/effect/temp_visual/order/rally_order name = "rally order" icon_state_on = "rally" - duration = RALLY_ORDER_DURATION + duration = CIC_ORDER_DURATION ///Set visuals for the hud /obj/effect/temp_visual/order/proc/set_visuals(faction) diff --git a/code/game/objects/items/radio/headset.dm b/code/game/objects/items/radio/headset.dm index 3722a2a11ce..0df5bb7e19b 100644 --- a/code/game/objects/items/radio/headset.dm +++ b/code/game/objects/items/radio/headset.dm @@ -488,6 +488,16 @@ GLOBAL_LIST_INIT(channel_tokens, list( name = "silicon radio" keyslot = /obj/item/encryptionkey/mcom/ai +/obj/item/radio/headset/mainship/mp + name = "security radio headset" + icon_state = "mp_headset" + keyslot = /obj/item/encryptionkey/mcom + +/obj/item/radio/headset/mainship/spatial + name = "spatial agent headset" + icon_state = "headset_marine_generic" + keyslot = /obj/item/encryptionkey/mcom/ai + /obj/item/radio/headset/mainship/marine keyslot = /obj/item/encryptionkey/general diff --git a/code/game/objects/items/rcd.dm b/code/game/objects/items/rcd.dm index ef0ba36e357..693d0b1f310 100644 --- a/code/game/objects/items/rcd.dm +++ b/code/game/objects/items/rcd.dm @@ -17,7 +17,7 @@ /obj/item/ammo_rcd name = "compressed matter cartridge" desc = "Highly compressed matter for the RCD." - icon = 'icons/obj/items/ammo.dmi' + icon = 'icons/obj/items/ammo/misc.dmi' icon_state = "rcd" item_icons = list( slot_l_hand_str = 'icons/mob/inhands/equipment/tools_left.dmi', diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index b460360eed7..b2c7d6ba664 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -843,3 +843,56 @@ name = "\improper Modello/190" desc = "A small lightweight buttpack made for use in a wide variety of operations, made with a synthetic black fibre." icon_state = "icc_bag_guard" + +/obj/item/storage/backpack/marine/radiopack + name = "\improper TGMC radio operator backpack" + desc = "A backpack that resembles the ones old-age radio operator marines would use. It has a supply ordering console installed on it, and a retractable antenna to receive supply drops." + icon_state = "radiopack" + item_state = "radiopack" + ///Var for the window pop-up + var/datum/supply_ui/requests/supply_interface + /// Reference to the datum used by the supply drop console + var/datum/supply_beacon/beacon_datum + +/obj/item/storage/backpack/marine/radiopack/Destroy() + if(beacon_datum) + UnregisterSignal(beacon_datum, COMSIG_QDELETING) + QDEL_NULL(beacon_datum) + return ..() + +/obj/item/storage/backpack/marine/radiopack/examine(mob/user) + . = ..() + . += span_notice("Right-Click with empty hand to open requisitions interface.") + . += span_notice("Activate in hand to create a supply beacon signal.") + +/obj/item/storage/backpack/marine/radiopack/attack_hand_alternate(mob/living/user) + if(!allowed(user)) + return ..() + if(!supply_interface) + supply_interface = new(src) + return supply_interface.interact(user) + +/obj/item/storage/backpack/marine/radiopack/attack_self(mob/living/user) + if(beacon_datum) + UnregisterSignal(beacon_datum, COMSIG_QDELETING) + QDEL_NULL(beacon_datum) + user.show_message(span_warning("The [src] beeps and states, \"Your last position is no longer accessible by the supply console"), EMOTE_AUDIBLE, span_notice("The [src] vibrates but you can not hear it!")) + return + if(!is_ground_level(user.z)) + to_chat(user, span_warning("You have to be on the planet to use this or it won't transmit.")) + return FALSE + var/turf/location = get_turf(src) + beacon_datum = new /datum/supply_beacon(user.name, user.loc, user.faction, 4 MINUTES) + RegisterSignal(beacon_datum, COMSIG_QDELETING, PROC_REF(clean_beacon_datum)) + user.show_message(span_notice("The [src] beeps and states, \"Your current coordinates were registered by the supply console. LONGITUDE [location.x]. LATITUDE [location.y]. Area ID: [get_area(src)]\""), EMOTE_AUDIBLE, span_notice("The [src] vibrates but you can not hear it!")) + addtimer(CALLBACK(src, PROC_REF(update_beacon_location)), 5 SECONDS) + +/obj/item/storage/backpack/marine/radiopack/proc/update_beacon_location() + if(beacon_datum) + beacon_datum.drop_location = get_turf(src) + addtimer(CALLBACK(src, PROC_REF(update_beacon_location), beacon_datum), 5 SECONDS) + +/// Signal handler to nullify beacon datum +/obj/item/storage/backpack/marine/radiopack/proc/clean_beacon_datum() + SIGNAL_HANDLER + beacon_datum = null diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index dd12272821c..c978f0e3c86 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -592,7 +592,7 @@ else stun = knockback ? knockback_stun_amount : crush_stun_amount - if(!M.IsStun() && !M.IsParalyzed() && !isxenoqueen(M)) //Prevent chain stunning. Queen is protected. + if(!M.IsStun() && !M.IsParalyzed() && !isxenoqueen(M) && !isxenoking(M)) //Prevent chain stunning. Queen and King are protected. M.apply_effects(stun,weaken) return ..() diff --git a/code/game/objects/machinery/computer/communications.dm b/code/game/objects/machinery/computer/communications.dm index 29c62ad5836..a720f27ed7d 100644 --- a/code/game/objects/machinery/computer/communications.dm +++ b/code/game/objects/machinery/computer/communications.dm @@ -124,7 +124,7 @@ priority_announce(input, subtitle = "Sent by [usr]", type = ANNOUNCEMENT_COMMAND) message_admins("[ADMIN_TPMONTY(usr)] has just sent a command announcement") log_game("[key_name(usr)] has just sent a command announcement.") - TIMER_COOLDOWN_START(usr, COOLDOWN_HUD_ORDER, ORDER_COOLDOWN) + TIMER_COOLDOWN_START(usr, COOLDOWN_HUD_ORDER, CIC_ORDER_COOLDOWN) cooldown_message = world.time if("award") @@ -230,7 +230,7 @@ cooldown_request = world.time if(admin_response == "deny") SSticker.mode.distress_cancelled = TRUE - priority_announce("The distress signal has been blocked, the launch tubes are now recalibrating.", "Distress Beacon") + priority_announce("Сигнал бедствия заблокирован. Пусковые трубы перекалибруются.", "Сигнал Бедствия", sound = 'sound/AI/distress_deny.ogg') return FALSE if(admin_response =="deny without annoncing") SSticker.mode.distress_cancelled = TRUE diff --git a/code/game/objects/machinery/computer/intel_computer.dm b/code/game/objects/machinery/computer/intel_computer.dm index 6aa4795546d..bb1732defee 100644 --- a/code/game/objects/machinery/computer/intel_computer.dm +++ b/code/game/objects/machinery/computer/intel_computer.dm @@ -63,7 +63,7 @@ printing_complete = TRUE SSpoints.supply_points[faction] += supply_reward SSpoints.dropship_points += dropship_reward - priority_announce("Classified transmission recieved from [get_area(src)]. Bonus delivered as [supply_reward] supply points and [dropship_reward] dropship points.", title = "TGMC Intel Division") + priority_announce("Получена секретная передача из [get_area(src)]. Бонус доставлен в виде [supply_reward] очков Карго и [dropship_reward] очков шаттла.", title = "Отдел Разведки UPP", sound = 'sound/AI/bonus_climed.ogg') SSminimaps.remove_marker(src) /obj/machinery/computer/intel_computer/Destroy() diff --git a/code/game/objects/machinery/overwatch.dm b/code/game/objects/machinery/overwatch.dm index adb8d859298..9411f2a0039 100644 --- a/code/game/objects/machinery/overwatch.dm +++ b/code/game/objects/machinery/overwatch.dm @@ -371,7 +371,7 @@ GLOBAL_LIST_EMPTY(active_cas_targets) return var/input = tgui_input_text(operator, "Please write a message to announce to the squad leader:", "SL Message", max_length = MAX_COMMAND_MESSAGE_LENGTH) if(input) - TIMER_COOLDOWN_START(operator, COOLDOWN_HUD_ORDER, ORDER_COOLDOWN) + TIMER_COOLDOWN_START(operator, COOLDOWN_HUD_ORDER, CIC_ORDER_COOLDOWN) message_member(current_squad.squad_leader, input, operator) if(issilicon(operator)) to_chat(operator, span_boldnotice("Message sent to Squad Leader [current_squad.squad_leader] of squad '[current_squad]'.")) @@ -781,7 +781,7 @@ GLOBAL_LIST_EMPTY(active_cas_targets) return var/input = tgui_input_text(source, "Please write a message to announce to this marine:", "CIC Message", max_length = MAX_COMMAND_MESSAGE_LENGTH) message_member(human_target, input, source) - TIMER_COOLDOWN_START(operator, COOLDOWN_HUD_ORDER, ORDER_COOLDOWN) + TIMER_COOLDOWN_START(operator, COOLDOWN_HUD_ORDER, CIC_ORDER_COOLDOWN) if(ASL) if(human_target == human_target.assigned_squad.squad_leader) human_target.assigned_squad.demote_leader() @@ -813,7 +813,7 @@ GLOBAL_LIST_EMPTY(active_cas_targets) continue message_member(target, input, source) message_member(source, input, source) - TIMER_COOLDOWN_START(operator, COOLDOWN_HUD_ORDER, ORDER_COOLDOWN) + TIMER_COOLDOWN_START(operator, COOLDOWN_HUD_ORDER, CIC_ORDER_COOLDOWN) if(SQUAD_ACTIONS) choice = show_radial_menu(source, turf_target, squad_radial_options, null, 48, null, FALSE, TRUE) var/datum/squad/chosen_squad = squad_select(source, turf_target) @@ -825,7 +825,7 @@ GLOBAL_LIST_EMPTY(active_cas_targets) var/input = tgui_input_text(source, "Please write a message to announce to the squad:", "Squad Message", max_length = MAX_COMMAND_MESSAGE_LENGTH) if(input) chosen_squad.message_squad(input, source) - TIMER_COOLDOWN_START(operator, COOLDOWN_HUD_ORDER, ORDER_COOLDOWN) + TIMER_COOLDOWN_START(operator, COOLDOWN_HUD_ORDER, CIC_ORDER_COOLDOWN) if(SWITCH_SQUAD_NEAR) for(var/mob/living/carbon/human/target in GLOB.human_mob_list) if(!target.faction == faction || get_dist(target, turf_target) > 9) @@ -913,7 +913,7 @@ GLOBAL_LIST_EMPTY(active_cas_targets) to_chat(src, span_warning("You cannot give an order while muted.")) return - if(command_aura_cooldown) + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_SKILL_ORDERS)) to_chat(src, span_warning("You have recently given an order. Calm down.")) return @@ -925,7 +925,7 @@ GLOBAL_LIST_EMPTY(active_cas_targets) if(!command_aura) return - if(command_aura_cooldown) + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_SKILL_ORDERS)) to_chat(src, span_warning("You have recently given an order. Calm down.")) return @@ -933,7 +933,7 @@ GLOBAL_LIST_EMPTY(active_cas_targets) return var/aura_strength = skills.getRating(SKILL_LEADERSHIP) - 1 var/aura_target = pick_order_target() - SSaura.add_emitter(aura_target, command_aura, aura_strength + 4, aura_strength, 30 SECONDS, faction) + SSaura.add_emitter(aura_target, command_aura, aura_strength + 4, aura_strength, SKILL_ORDER_DURATION, faction) var/message = "" switch(command_aura) @@ -953,10 +953,6 @@ GLOBAL_LIST_EMPTY(active_cas_targets) say(message) add_emote_overlay(focus) - command_aura_cooldown = addtimer(CALLBACK(src, PROC_REF(end_command_aura_cooldown)), 45 SECONDS) - - update_action_buttons() - ///Choose what we're sending a buff order through /mob/living/carbon/human/proc/pick_order_target() //If we're in overwatch, use the camera eye @@ -964,10 +960,6 @@ GLOBAL_LIST_EMPTY(active_cas_targets) return remote_control return src -/mob/living/carbon/human/proc/end_command_aura_cooldown() - command_aura_cooldown = null - update_action_buttons() - /datum/action/skill/issue_order name = "Issue Order" action_icon = 'icons/mob/order_icons.dmi' @@ -975,10 +967,28 @@ GLOBAL_LIST_EMPTY(active_cas_targets) skill_min = SKILL_LEAD_TRAINED var/order_type = null +/datum/action/skill/issue_order/give_action(mob/M) + . = ..() + RegisterSignals(M, list(COMSIG_SKILL_ORDER_SENT, COMSIG_SKILL_ORDER_OFF_CD), PROC_REF(update_button_icon)) + +/datum/action/skill/issue_order/remove_action(mob/M) + . = ..() + UnregisterSignal(M, list(COMSIG_CIC_ORDER_SENT, COMSIG_CIC_ORDER_OFF_CD)) + +/datum/action/skill/issue_order/can_use_action() + . = ..() + if(!.) + return + if(owner.stat || TIMER_COOLDOWN_CHECK(owner, COOLDOWN_SKILL_ORDERS)) + return FALSE + /datum/action/skill/issue_order/action_activate() var/mob/living/carbon/human/human = owner if(istype(human)) human.issue_order(order_type) + TIMER_COOLDOWN_START(owner, COOLDOWN_SKILL_ORDERS, SKILL_ORDER_COOLDOWN) + addtimer(CALLBACK(src, PROC_REF(on_cooldown_finish)), SKILL_ORDER_COOLDOWN + 1) + SEND_SIGNAL(owner, COMSIG_SKILL_ORDER_SENT) /datum/action/skill/issue_order/update_button_icon() var/mob/living/carbon/human/human = owner @@ -991,11 +1001,15 @@ GLOBAL_LIST_EMPTY(active_cas_targets) var/mob/living/carbon/human/human = owner if(!istype(human)) return - if(human.command_aura_cooldown) + if(TIMER_COOLDOWN_CHECK(human, COOLDOWN_SKILL_ORDERS)) button.color = rgb(255,0,0,255) else button.color = rgb(255,255,255,255) +///Lets any other orders know when we're off CD +/datum/action/skill/issue_order/proc/on_cooldown_finish() + SEND_SIGNAL(owner, COMSIG_SKILL_ORDER_OFF_CD, src) + /datum/action/skill/issue_order/move name = "Issue Move Order" order_type = AURA_HUMAN_MOVE @@ -1031,16 +1045,14 @@ GLOBAL_LIST_EMPTY(active_cas_targets) if(orders_visible) orders_visible = FALSE action_icon_state = "show_order" - for(var/datum/action/skill/path in owner.actions) - if(istype(path, /datum/action/skill/issue_order)) - path.remove_action(H) + for(var/datum/action/skill/issue_order/action in owner.actions) + action.hidden = TRUE else orders_visible = TRUE action_icon_state = "hide_order" - var/list/subtypeactions = subtypesof(/datum/action/skill/issue_order) - for(var/path in subtypeactions) - var/datum/action/skill/issue_order/A = new path() - A.give_action(H) + for(var/datum/action/skill/issue_order/action in owner.actions) + action.hidden = FALSE + owner.update_action_buttons() /obj/machinery/computer/camera_advanced/overwatch/proc/get_squad_by_id(id) for(var/datum/squad/squad AS in watchable_squads) diff --git a/code/game/objects/machinery/self_destruct.dm b/code/game/objects/machinery/self_destruct.dm index 95f89676ce6..aa8450727fd 100644 --- a/code/game/objects/machinery/self_destruct.dm +++ b/code/game/objects/machinery/self_destruct.dm @@ -81,7 +81,7 @@ if("dest_start") to_chat(usr, span_notice("You press a few keys on the panel.")) to_chat(usr, span_notice("The system must be booting up the self-destruct sequence now.")) - priority_announce("Danger. The emergency destruct system is now activated. The ship will detonate in T-minus 20 minutes. Automatic detonation is unavailable. Manual detonation is required.", title = "Self Destruct System", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/selfdestruct.ogg', color_override = "purple") + priority_announce("Тревога! Протокол самоуничтожения активирован. Корабль взорвется через 20 минут. Автоматическая детонация недоступна. Требуется ручное вмешательство.", title = "Протокол Самоуничтожения", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/selfdestruct.ogg', color_override = "purple") active_state = SELF_DESTRUCT_MACHINE_ARMED var/obj/machinery/self_destruct/rod/I = SSevacuation.dest_rods[SSevacuation.dest_index] I.activate_time = world.time diff --git a/code/game/objects/machinery/vending/marine_vending.dm b/code/game/objects/machinery/vending/marine_vending.dm index abff9bd66a3..bfeb18587ac 100644 --- a/code/game/objects/machinery/vending/marine_vending.dm +++ b/code/game/objects/machinery/vending/marine_vending.dm @@ -789,11 +789,6 @@ "Surplus Special Equipment" = list( /obj/item/pinpointer = 1, /obj/item/beacon/supply_beacon = 1, - /obj/item/ammo_magazine/rifle/sr81 = 3, - /obj/item/ammo_magazine/rifle/tx8 = 3, - /obj/item/ammo_magazine/rocket/sadar = 3, - /obj/item/ammo_magazine/minigun_powerpack = 2, - /obj/item/ammo_magazine/shotgun/mbx900 = 2, /obj/item/explosive/plastique = 5, /obj/item/fulton_extraction_pack = 2, /obj/item/clothing/suit/storage/marine/boomvest = 20, diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index b1a0d426fbe..8511866d12a 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -14,7 +14,7 @@ . = ..() switch(dir) if(NORTH) - pixel_y = -14 + pixel_y = -17 if(SOUTH) pixel_y = 27 if(EAST) diff --git a/code/game/objects/structures/orbital_cannon.dm b/code/game/objects/structures/orbital_cannon.dm index e1197c3b654..c496eecdc0f 100644 --- a/code/game/objects/structures/orbital_cannon.dm +++ b/code/game/objects/structures/orbital_cannon.dm @@ -214,13 +214,13 @@ var/turf/target = locate(T.x + inaccurate_fuel * pick(-2, 2),T.y + inaccurate_fuel * pick(-2, 2),T.z) // Give marines a warning if misfuelled. - var/fuel_warning = "Warhead fuel level: safe." + var/fuel_warning = "Уровень топлива боеголовки: корректный." if(inaccurate_fuel > 0) - fuel_warning = "Warhead fuel level: incorrect.
Warhead may be inaccurate." + fuel_warning = "Уровень топлива боеголовки: некорректный.
Возможно смещение области поражения." priority_announce( - message = "Evacuate the impact zone immediately!

Warhead type: [tray.warhead.warhead_kind].
[fuel_warning]
Estimated location of impact: [get_area(T)].", - title = "Orbital bombardment launch command detected!", + message = "Немедленно покиньте зону поражения!

Тип боеголовки: [tray.warhead.warhead_kind_rus].
[fuel_warning]
Цель: [get_area(T)].", + title = "Обнаружена команда на запуск орбитальной бомбардировки!", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/effects/OB_warning_announce.ogg', channel_override = SSsounds.random_available_channel(), // This way, we can't have it be cut off by other sounds. @@ -228,7 +228,7 @@ ) var/list/receivers = (GLOB.alive_human_list + GLOB.ai_list + GLOB.observer_list) for(var/mob/living/screentext_receiver AS in receivers) - screentext_receiver.play_screen_text("ORBITAL STRIKE IMMINENT
TYPE: [uppertext(tray.warhead.warhead_kind)]", /atom/movable/screen/text/screen_text/command_order) + screentext_receiver.play_screen_text("ОРБИТАЛЬНЫЙ УДАР
ТИП СНАРЯДА: [uppertext(tray.warhead.warhead_kind_rus)]", /atom/movable/screen/text/screen_text/command_order) playsound(target, 'sound/effects/OB_warning_announce_novoiceover.ogg', 125, FALSE, 30, 10) //VOX-less version for xenomorphs var/impact_time = 10 SECONDS + (WARHEAD_FLY_TIME * (GLOB.current_orbit/3)) @@ -361,6 +361,7 @@ /obj/structure/ob_ammo/warhead name = "theoretical orbital ammo" var/warhead_kind + var/warhead_kind_rus ///Explode the warhead /obj/structure/ob_ammo/warhead/proc/warhead_impact() @@ -373,8 +374,8 @@ relative_dir = 0 else relative_dir = get_dir(our_mob, target) - our_mob.show_message(span_highdanger("The sky erupts into flames [relative_dir ? ("to the " + dir2text(relative_dir)) : "right above you"]!"), EMOTE_VISIBLE, - span_highdanger("You hear a very loud sound coming from above to the [relative_dir ? ("to the " + dir2text(relative_dir)) : "right above you"]!"), EMOTE_AUDIBLE) + our_mob.show_message(span_highdanger("Небо вспыхнуло [relative_dir ? ("с " + dir2rutext(relative_dir) + "а от тебя") : "прямо над тобой"]!"), EMOTE_VISIBLE, + span_highdanger("Громкий шум слышно из неба [relative_dir ? ("примерно с " + dir2rutext(relative_dir) + "а от тебя") : "прямо над тобой"]!"), EMOTE_AUDIBLE) sleep(impact_time / 3) for(var/mob/living/our_mob in range(25, target)) @@ -382,17 +383,18 @@ relative_dir = 0 else relative_dir = get_dir(our_mob, target) - our_mob.show_message(span_highdanger("The sky roars louder [relative_dir ? ("to the " + dir2text(relative_dir)) : "right above you"]!"), EMOTE_VISIBLE, - span_highdanger("The sound becomes louder [relative_dir ? ("to the " + dir2text(relative_dir)) : "right above you"]!"), EMOTE_AUDIBLE) + our_mob.show_message(span_highdanger("Небо ревет все громче [relative_dir ? ("с " + dir2rutext(relative_dir) + "а от тебя") : "прямо над тобой"]!"), EMOTE_VISIBLE, + span_highdanger("Шум становится громче [relative_dir ? ("где-то с " + dir2rutext(relative_dir) + "а от тебя") : "прямо над тобой"]!"), EMOTE_AUDIBLE) sleep(impact_time / 3) for(var/mob/living/our_mob in range(15, target)) - our_mob.show_message(span_highdanger("OH GOD THE SKY WILL EXPLODE!!!"), EMOTE_VISIBLE, - span_highdanger("YOU SHOULDN'T BE HERE!"), EMOTE_AUDIBLE) + our_mob.show_message(span_highdanger("О БОЖЕ, НЕБО СЕЙЧАС ВЗОРВЕТСЯ!!!"), EMOTE_VISIBLE, + span_highdanger("СМАТЫВАЙСЯ ОТСЮДА!"), EMOTE_AUDIBLE) /obj/structure/ob_ammo/warhead/explosive name = "\improper HE orbital warhead" warhead_kind = "explosive" + warhead_kind_rus = "взрывной" icon_state = "ob_warhead_1" var/explosion_power = 1425 var/explosion_falloff = 90 @@ -403,6 +405,7 @@ /obj/structure/ob_ammo/warhead/incendiary name = "\improper Incendiary orbital warhead" warhead_kind = "incendiary" + warhead_kind_rus = "зажигательный" icon_state = "ob_warhead_2" var/flame_range_num var/flame_intensity = 36 @@ -420,6 +423,7 @@ /obj/structure/ob_ammo/warhead/cluster name = "\improper Cluster orbital warhead" warhead_kind = "cluster" + warhead_kind_rus = "кластер" icon_state = "ob_warhead_3" var/cluster_amount = 25 var/cluster_power = 240 @@ -441,6 +445,7 @@ /obj/structure/ob_ammo/warhead/plasmaloss name = "\improper Plasma draining orbital warhead" warhead_kind = "plasma" + warhead_kind_rus = "Т-ГАЗ" icon_state = "ob_warhead_4" var/smoke_radius = 25 var/smoke_duration = 3 SECONDS diff --git a/code/game/sound.dm b/code/game/sound.dm index 5f89017d467..f9b1853850e 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -402,6 +402,8 @@ A good representation is: 'byond applies a volume reduction to the sound every X S = pick('sound/voice/predator/pain_rare1.ogg') if("pred_warcry") S = pick('sound/voice/predator/warcry.ogg') + if("pred_laugh") + S = pick('sound/voice/predator/laugh1.ogg', 'sound/voice/predator/laugh2.ogg', 'sound/voice/predator/laugh3.ogg', 'sound/voice/predator/laugh4.ogg') //pred items if("clan_sword_hit") diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e97b048c92f..5053811fdb7 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -682,7 +682,6 @@ var/mob/M = usr var/chosen = tgui_input_list(usr, "Please, select an area.", "Select an area.", GLOB.sorted_areas, timeout = 0) - chosen = pick(get_area_turfs(chosen)) var/turf/T = pick(get_area_turfs(chosen)) M.forceMove(T) diff --git a/code/modules/admin/fun_verbs.dm b/code/modules/admin/fun_verbs.dm index e901d7167f9..2b5b8a6f09e 100644 --- a/code/modules/admin/fun_verbs.dm +++ b/code/modules/admin/fun_verbs.dm @@ -155,7 +155,7 @@ if("Yes") priority_announce(input, customname, customsubtitle, sound = 'sound/AI/commandreport.ogg', color_override = override); if("No") - priority_announce("New update available at all communication consoles.", "Classified Transmission Received", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/commandreport.ogg') + priority_announce("Новое объявление доступно на всех консолях связи.", "Получена конфиденциальная передача", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/commandreport.ogg') else return diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index f4ad78eea8e..ab5ec796610 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -657,7 +657,7 @@ Status: [status ? status : "Unknown"] | Damage: [health ? health : "None"] return SSticker.mode.distress_cancelled = TRUE - priority_announce("The distress signal has been blocked, the launch tubes are now recalibrating.", "Distress Beacon") + priority_announce("Сигнал бедствия заблокирован. Пусковые трубы перекалибруются.", "Сигнал Бедствия", sound = 'sound/AI/distressbeaconlocked.ogg') log_admin("[key_name(usr)] has denied a distress beacon, requested by [key_name(M)]") message_admins("[ADMIN_TPMONTY(usr)] has denied a distress beacon, requested by [ADMIN_TPMONTY(M)]") diff --git a/code/modules/clothing/modular_armor/attachments/modules.dm b/code/modules/clothing/modular_armor/attachments/modules.dm index 5904906526a..45b6781c7f1 100644 --- a/code/modules/clothing/modular_armor/attachments/modules.dm +++ b/code/modules/clothing/modular_armor/attachments/modules.dm @@ -177,14 +177,14 @@ */ /obj/item/armor_module/module/mimir_environment_protection name = "\improper Mark 2 Mimir Environmental Resistance System" - desc = "Designed for mounting on modular armor. This newer model provides great resistance to acid, biological, and radiological attacks. Pairing this with a Mimir helmet module and mask will make the user impervious to xeno gas clouds. Will impact mobility." + desc = "Designed for mounting on modular armor. This newer model provides great resistance to acid, biological, and radiological attacks. Pairing this with a Mimir helmet module and mask will make the user impervious to any gas clouds. Will impact mobility." icon = 'icons/mob/modular/modular_armor_modules.dmi' icon_state = "mod_biohazard" item_state = "mod_biohazard_a" - soft_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 10, FIRE = 0, ACID = 10) + soft_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 10, FIRE = 0, ACID = 25) slowdown = 0.2 slot = ATTACHMENT_SLOT_MODULE - ///siemens coefficient mod for gas protection. + ///siemens (electro resist) coefficient mod for gas protection. var/siemens_coefficient_mod = -0.9 ///permeability coefficient mod for gas protection. var/permeability_coefficient_mod = -1 @@ -205,11 +205,13 @@ /obj/item/armor_module/module/mimir_environment_protection/mark1 name = "\improper Mark 1 Mimir Environmental Resistance System" - desc = "Designed for mounting on modular armor. This older model provides minor resistance to acid, biological, and radiological attacks. Pairing this with a Mimir helmet module and mask will make the user impervious to xeno gas clouds. Will impact mobility." + desc = "Designed for mounting on modular armor. This older model provides minor resistance to acid, biological, and radiological attacks. Pairing this with a Mimir helmet module and mask will make the user almost impervious to any gas clouds. Will impact mobility." icon_state = "mod_biohazard" item_state = "mod_biohazard_a" - soft_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 5, FIRE = 0, ACID = 5) + soft_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 5, FIRE = 0, ACID = 10) slowdown = 0.3 + permeability_coefficient_mod = -0.5 + gas_transfer_coefficient_mod = -0.5 //SOM version /obj/item/armor_module/module/mimir_environment_protection/som @@ -220,20 +222,20 @@ //soft_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 25, FIRE = 0, ACID = 20) /obj/item/armor_module/module/mimir_environment_protection/mimir_helmet - name = "Mimir Environmental Helmet System" - desc = "Designed for mounting on a modular helmet. Provides good resistance to xeno gas clouds" + name = "Mark 2 Mimir Environmental Helmet System" + desc = "Designed for mounting on a modular helmet. Provides good resistance to xeno gas clouds." icon = 'icons/mob/modular/modular_armor_modules.dmi' icon_state = "mimir_head" item_state = "mimir_head_a" variants_by_parent_type = list(/obj/item/clothing/head/modular/m10x = "mimir_head_xn") - soft_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 10, FIRE = 0, ACID = 10) + soft_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 10, FIRE = 0, ACID = 25) slowdown = 0 slot = ATTACHMENT_SLOT_HEAD_MODULE -/obj/item/armor_module/module/mimir_environment_protection/mimir_helmet/mark1 //gas protection +/obj/item/armor_module/module/mimir_environment_protection/mimir_helmet/mark1 name = "Mark 1 Mimir Environmental Helmet System" - desc = "Designed for mounting on a modular helmet. This older model provides minor resistance to acid and biological attacks. Pairing this with a Mimir suit module and mask will make the user impervious to xeno gas clouds." - soft_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 5, FIRE = 0, ACID = 5) + desc = "Designed for mounting on a modular helmet. This older model provides minor resistance to acid and biological attacks." + soft_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 5, FIRE = 0, ACID = 10) //Explosive defense armor /obj/item/armor_module/module/hlin_explosive_armor diff --git a/code/modules/events/intel_computer.dm b/code/modules/events/intel_computer.dm index 626b5d96b59..5b91384aa14 100644 --- a/code/modules/events/intel_computer.dm +++ b/code/modules/events/intel_computer.dm @@ -22,5 +22,5 @@ /datum/round_event/intel_computer/proc/activate(obj/machinery/computer/intel_computer/I) I.active = TRUE I.update_minimap_icon() - priority_announce("Our data sifting algorithm has detected valuable classified information on a access point in [get_area(I)]. Should this data be recovered by ground forces, a reward will be given in the form of increased assets.", title = "TGMC Intel Division") - xeno_message("We sense a looming threat from [get_area(I)]. We must keep the hosts away from there.") + priority_announce("Обнаружена ценная информация в [get_area(I)]. Если эти данные будут восстановлены наземными силами, будет выдано вознаграждение.", title = "Отдел Разведки UPP", sound = 'sound/AI/bonus_found.ogg') + xeno_message("Кажется в [get_area(I)] есть что-то полезное для морпехов. Следует держать их подальше от этого места.") diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm index a86ea68c7e6..c9924fd4516 100644 --- a/code/modules/events/ion_storm.dm +++ b/code/modules/events/ion_storm.dm @@ -23,12 +23,12 @@ addtimer(CALLBACK(src, PROC_REF(fix_comms)), comms_knockout_timer MINUTES) /datum/round_event/ion_storm/announce() - var/alert = pick( "Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you*%fj00)`5vc-BZZT", - "Ionospheric anomalies detected. Temporary telecommunication failu*3mga;b4;'1v¬-BZZZT", - "Ionospheric anomalies detected. Temporary telec#MCi46:5.;@63-BZZZZT", - "Ionospheric anomalies dete'fZ\\kg5_0-BZZZZZT", - "Ionospheri:%£ MCayj^j<.3-BZZZZZZT", - "#4nd%;f4y6,>£%-BZZZZZZZT", + var/alert = pick( "Обнаружена ионосферная аномалия. Сбой связи неизбежен. Пожалуйста, свяжитесь с ваши*%fj00)`5vc", + "Обнаружена ионосферная аномалия. Сбой связи неизб*3mga;b4;'1v¬", + "Обнаружена ионосферная аномалия. Сбой свя#MCi46:5.;@63", + "Обнаружена ионосферная аномал'fZ\\kg5_0", + "Обнаружена ионосфер:%£ MCayj^j<.3", + "#4nd%;f4y6,>£%", ) priority_announce(alert) diff --git a/code/modules/events/stock_uptick.dm b/code/modules/events/stock_uptick.dm index 34dfc1855a1..0a9a2954989 100644 --- a/code/modules/events/stock_uptick.dm +++ b/code/modules/events/stock_uptick.dm @@ -19,4 +19,4 @@ if(points_to_be_added > 1250) //cap the max amount of points at 1250 points_to_be_added = 1250 SSpoints.supply_points[FACTION_TERRAGOV] += points_to_be_added - priority_announce("Due to an increase in Nanotrasen quarterly revenues, our supply allotment has increased by [points_to_be_added] points.") + priority_announce("В связи с ростом квартальной выручки Nanotrasen наш объем поставок увеличился на [points_to_be_added] очков.", sound = 'sound/AI/supply_increase.ogg') diff --git a/code/modules/events/supply_drop.dm b/code/modules/events/supply_drop.dm index 969abe3025c..a5679b24cdf 100644 --- a/code/modules/events/supply_drop.dm +++ b/code/modules/events/supply_drop.dm @@ -29,7 +29,7 @@ ///sets the target for this event, and notifies the hive /datum/round_event/supply_drop/proc/set_target(turf/target_turf) var/supplying_faction = pick(SSticker.mode.factions) - priority_announce("Friendly supply drop arriving in AO in [drop_delay / 600] minutes. Drop zone at [target_turf.loc].", "Bluespace Tactical Scanner Status", sound = 'sound/AI/distressreceived.ogg', receivers = (GLOB.alive_human_list_faction[supplying_faction] + GLOB.observer_list)) + priority_announce("Союзный груз прибудет через [drop_delay / 600] минут. Место посадки - [target_turf.loc].", "Статус Тактического Блюспейс Сканера", sound = 'sound/AI/sup_drop.ogg', receivers = (GLOB.alive_human_list_faction[supplying_faction] + GLOB.observer_list)) addtimer(CALLBACK(src, PROC_REF(alert_hostiles), target_turf, supplying_faction), alert_delay) addtimer(CALLBACK(src, PROC_REF(drop_supplies), target_turf, supplying_faction), drop_delay) @@ -40,12 +40,12 @@ if(alerted_human.faction == supplying_faction) humans_to_alert -= alerted_human - priority_announce("Incoming [supplying_faction] supply drop detected, ETA [(drop_delay - alert_delay) / 600] minutes. Drop zone estimated as [target_turf.loc].", "Bluespace Tactical Scanner Status", sound = 'sound/AI/distressreceived.ogg', receivers = (humans_to_alert + GLOB.observer_list)) + priority_announce("На подходе груз [supplying_faction]. Прибудет через [(drop_delay - alert_delay) / 600] минут. Место - [target_turf.loc].", "Статус Тактического Блюспейс Сканера", sound = 'sound/AI/sup_drop_enemy.ogg', receivers = (humans_to_alert + GLOB.observer_list)) ///deploys the actual supply drop /datum/round_event/supply_drop/proc/drop_supplies(turf/target_turf, faction) - priority_announce("[faction] supply drop Materialisation detected at [target_turf.loc].", "Bluespace Tactical Scanner Status", sound = 'sound/AI/distressreceived.ogg', receivers = (GLOB.alive_human_list + GLOB.observer_list)) + priority_announce("Обнаружена поставка от [faction] в [target_turf.loc].", "Статус Тактического Блюспейс Сканера", sound = 'sound/AI/sup_drop_act.ogg', receivers = (GLOB.alive_human_list + GLOB.observer_list)) new /obj/item/explosive/grenade/flare/on(target_turf) switch(faction) if(FACTION_SOM) diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm index 133f833c7a2..6650e50e4c1 100644 --- a/code/modules/language/language_holder.dm +++ b/code/modules/language/language_holder.dm @@ -111,6 +111,10 @@ /datum/language_holder/xeno languages = list(/datum/language/xenocommon) +/datum/language_holder/hivemind + languages = list(/datum/language/xenocommon) + shadow_languages = list(/datum/language/common) + /datum/language_holder/universal/New() . = ..() diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index f17ca637602..ec4b8235c5f 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -299,7 +299,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) if(tier != XENO_TIER_MINION && hivenumber == XENO_HIVE_NORMAL) GLOB.key_to_time_of_xeno_death[ghost.key] = world.time //If you ghost as a xeno that is not a minion, sets respawn timer - /mob/dead/observer/Move(atom/newloc, direct, glide_size_override = 32) if(updatedir) setDir(direct)//only update dir if we actually need it, so overlays won't spin on base sprites that don't have directions of their own @@ -654,9 +653,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) if(!istype(target)) return - var/icon/I = icon(target.icon, target.icon_state, target.dir) - - var/orbitsize = (I.Width() + I.Height()) * 0.5 + var/list/icon_dimensions = get_icon_dimensions(target.icon) + var/orbitsize = (icon_dimensions["width"] + icon_dimensions["height"]) * 0.5 orbitsize -= (orbitsize / world.icon_size) * (world.icon_size * 0.25) var/rot_seg diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote/human.dm similarity index 77% rename from code/modules/mob/living/carbon/human/emote.dm rename to code/modules/mob/living/carbon/human/emote/human.dm index 4c9d351fbc2..49ba1eb59a4 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote/human.dm @@ -1,31 +1,26 @@ /datum/emote/living/carbon/human mob_type_allowed_typecache = /mob/living/carbon/human - /datum/emote/living/carbon/human/run_emote(mob/living/carbon/human/user, params, type_override, intentional = FALSE, prefix) var/paygrade = user.get_paygrade() if(paygrade) prefix = "[paygrade] " return ..() - /datum/emote/living/carbon/human/blush key = "blush" key_third_person = "blushes" message = "blushes." - /datum/emote/living/carbon/human/blink key = "blink" key_third_person = "blinks" message = "blinks." - /datum/emote/living/carbon/human/blink_r key = "blinkr" message = "blinks rapidly." - /datum/emote/living/carbon/human/bow key = "bow" key_third_person = "bows" @@ -33,21 +28,18 @@ message_param = "bows to %t." flags_emote = EMOTE_RESTRAINT_CHECK - /datum/emote/living/carbon/human/chuckle key = "chuckle" key_third_person = "chuckles" message = "chuckles." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/cross key = "cross" key_third_person = "crosses" message = "crosses their arms." flags_emote = EMOTE_RESTRAINT_CHECK - /datum/emote/living/carbon/human/clap key = "clap" key_third_person = "claps" @@ -56,28 +48,24 @@ emote_type = EMOTE_AUDIBLE sound = 'sound/misc/clap.ogg' - /datum/emote/living/carbon/human/collapse key = "collapse" key_third_person = "collapses" message = "collapses!" emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/collapse/run_emote(mob/living/carbon/human/user, params, type_override, intentional = FALSE, prefix) . = ..() if(!.) return user.Unconscious(4 SECONDS) - /datum/emote/living/carbon/human/cough key = "cough" key_third_person = "coughs" message = "coughs!" emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/cough/get_sound(mob/living/carbon/human/user) if(!user.species) return @@ -86,44 +74,37 @@ if(user.species.coughs[NEUTER]) return user.species.coughs[NEUTER] - /datum/emote/living/carbon/human/cry key = "cry" key_third_person = "cries" message = "cries." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/drool key = "drool" key_third_person = "drools" message = "drools." - /datum/emote/living/carbon/human/eyebrow key = "eyebrow" message = "raises an eyebrow." - /datum/emote/living/carbon/human/faint key = "faint" key_third_person = "faints" message = "faints." - /datum/emote/living/carbon/human/faint/run_emote(mob/living/carbon/human/user, params, type_override, intentional = FALSE, prefix) . = ..() if(!.) return user.AdjustSleeping(1 SECONDS) - /datum/emote/living/carbon/human/frown key = "frown" key_third_person = "frowns" message = "frowns." - /datum/emote/living/carbon/human/gasp key = "gasp" key_third_person = "gasps" @@ -131,7 +112,6 @@ emote_type = EMOTE_AUDIBLE stat_allowed = UNCONSCIOUS - /datum/emote/living/carbon/human/gasp/get_sound(mob/living/carbon/human/user) if(!user.species) return @@ -146,7 +126,6 @@ message = "giggles." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/glare key = "glare" key_third_person = "glares" @@ -154,26 +133,22 @@ message_param = "glares at %t." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/yawn key = "yawn" key_third_person = "yawns" message = "yawns." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/wave key = "wave" key_third_person = "waves" message = "waves." - /datum/emote/living/carbon/human/twitch key = "twitch" key_third_person = "twitches" message = "twitches." - /datum/emote/living/carbon/human/snore key = "snore" key_third_person = "snores" @@ -181,38 +156,32 @@ emote_type = EMOTE_AUDIBLE stat_allowed = UNCONSCIOUS - /datum/emote/living/carbon/human/smile key = "smile" key_third_person = "smiles" message = "smiles." - /datum/emote/living/carbon/human/smug key = "smug" key_third_person = "smugs" message = "grins smugly." - /datum/emote/living/carbon/human/stare key = "stare" key_third_person = "stares" message = "stares." message_param = "stares at %t." - /datum/emote/living/carbon/human/strech key = "stretch" key_third_person = "stretches" message = "stretches their arms." - /datum/emote/living/carbon/human/sulk key = "sulk" key_third_person = "sulks" message = "sulks down sadly." - /datum/emote/living/carbon/human/surrender key = "surrender" key_third_person = "surrenders" @@ -221,10 +190,12 @@ /datum/emote/living/carbon/human/surrender/run_emote(mob/user, params, type_override, intentional) . = ..() - if(. && isliving(user)) - var/mob/living/L = user - L.Paralyze(20 SECONDS) - + if(!.) + return + if(!isliving(user)) + return + var/mob/living/L = user + L.Paralyze(20 SECONDS) /datum/emote/living/carbon/human/sneeze key = "sneeze" @@ -232,35 +203,30 @@ message = "sneezes." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/sniff key = "sniff" key_third_person = "sniffs" message = "sniffs." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/shiver key = "shiver" key_third_person = "shiver" message = "shivers." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/scowl key = "scowl" key_third_person = "scowls" message = "scowls." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/sigh key = "sigh" key_third_person = "sighs" message = "sighs." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/sit key = "sit" key_third_person = "sits" @@ -271,28 +237,24 @@ key_third_person = "shrugs" message = "shrugs." - /datum/emote/living/carbon/human/shakehead key = "shakehead" key_third_person = "shakeheads" message = "shakes their head." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/nod key = "nod" key_third_person = "nods" message = "nods." message_param = "nods at %t." - /datum/emote/living/carbon/human/gag key = "gag" key_third_person = "gags" message = "gags." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/glare key = "glare" key_third_person = "glares" @@ -300,26 +262,22 @@ message_param = "glares at %t." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/grin key = "grin" key_third_person = "grins" message = "grins." - /datum/emote/living/carbon/human/grimace key = "grimace" key_third_person = "grimaces" message = "grimaces." - /datum/emote/living/carbon/human/jump key = "jump" key_third_person = "jumps" message = "jumps!" flags_emote = EMOTE_RESTRAINT_CHECK - /datum/emote/living/carbon/human/grumble key = "grumble" key_third_person = "grumbles" @@ -333,14 +291,12 @@ message_param = "blows a kiss to %t." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/signal key = "signal" key_third_person = "signals" message_param = "raises %t fingers." flags_emote = EMOTE_RESTRAINT_CHECK - /datum/emote/living/carbon/human/signal/select_param(mob/user, params) params = text2num(params) if(params == 1 || !isnum(params)) @@ -348,33 +304,25 @@ params = num2text(clamp(params, 2, 10)) return ..() - /datum/emote/living/carbon/human/mumble key = "mumble" key_third_person = "mumbles" message = "mumbles!" emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/moan key = "moan" key_third_person = "moans" message = "moans!" emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/laugh key = "laugh" key_third_person = "laughs" message = "laughs." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/laugh/get_sound(mob/living/carbon/human/user) - - if(isyautja(user)) - return pick('sound/voice/predator/laugh1.ogg', 'sound/voice/predator/laugh2.ogg', 'sound/voice/predator/laugh3.ogg', 'sound/voice/predator/laugh4.ogg') - if(!user?.species?.laughs) return if(user.species.laughs[user.gender]) @@ -396,7 +344,6 @@ if(user.species.warcries[NEUTER]) return user.species.warcries[NEUTER] - /datum/emote/living/carbon/human/warcry/run_emote(mob/user, params, type_override, intentional = FALSE, prefix) . = ..() if(!.) @@ -420,14 +367,12 @@ flags_emote = EMOTE_RESTRAINT_CHECK emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/look key = "look" key_third_person = "looks" message = "looks." message_param = "looks at %t." - /datum/emote/living/carbon/human/handshake key = "handshake" message = "shakes their own hands." @@ -435,7 +380,6 @@ flags_emote = EMOTE_RESTRAINT_CHECK emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/salute key = "salute" key_third_person = "salutes" @@ -444,7 +388,6 @@ flags_emote = EMOTE_RESTRAINT_CHECK sound = 'sound/misc/salute.ogg' - /datum/emote/living/carbon/human/golfclap key = "golfclap" key_third_person = "golfclaps" @@ -452,21 +395,18 @@ flags_emote = EMOTE_RESTRAINT_CHECK sound = 'sound/misc/golfclap.ogg' - /datum/emote/living/carbon/human/pout key = "pout" key_third_person = "pouts" message = "pouts." emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/scream key = "scream" key_third_person = "screams" message = "screams!" emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/scream/get_sound(mob/living/carbon/human/user) if(!user.species) return @@ -475,7 +415,6 @@ if(user.species.screams[NEUTER]) return user.species.screams[NEUTER] - /datum/emote/living/carbon/human/scream/run_emote(mob/user, params, type_override, intentional = FALSE, prefix) . = ..() if(!.) @@ -483,14 +422,20 @@ var/image/scream = image('icons/mob/talk.dmi', user, icon_state = "scream") user.add_emote_overlay(scream) - /datum/emote/living/carbon/human/medic key = "medic" message = "calls for a medic!" emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/medic/get_sound(mob/living/carbon/human/user) + if(isrobot(user)) + if(user.gender == MALE) + if(prob(95)) + return 'sound/voice/robotic/male_medic.ogg' + else + return 'sound/voice/robotic/male_medic2.ogg' + else + return 'sound/voice/robotic/female_medic.ogg' if(user.gender == MALE) if(prob(95)) return 'sound/voice/human/male/medic.ogg' @@ -499,7 +444,6 @@ else return 'sound/voice/human/female/medic.ogg' - /datum/emote/living/carbon/human/medic/run_emote(mob/user, params, type_override, intentional = FALSE, prefix) . = ..() if(!.) @@ -507,13 +451,11 @@ var/image/medic = image('icons/mob/talk.dmi', user, icon_state = "medic") user.add_emote_overlay(medic) - /datum/emote/living/carbon/human/pain key = "pain" message = "cries out in pain!" emote_type = EMOTE_AUDIBLE - /datum/emote/living/carbon/human/pain/get_sound(mob/living/carbon/human/user) if(!user.species) return @@ -522,7 +464,6 @@ if(user.species.paincries[NEUTER]) return user.species.paincries[NEUTER] - /datum/emote/living/carbon/human/pain/run_emote(mob/user, params, type_override, intentional = FALSE, prefix) . = ..() if(!.) @@ -530,14 +471,12 @@ var/image/pain = image('icons/mob/talk.dmi', user, icon_state = "pain") user.add_emote_overlay(pain) - /datum/emote/living/carbon/human/gored key = "gored" message = "gags out in pain!" emote_type = EMOTE_AUDIBLE flags_emote = EMOTE_FORCED_AUDIO - /datum/emote/living/carbon/human/gored/get_sound(mob/living/carbon/human/user) if(!user.species) return @@ -546,7 +485,6 @@ if(user.species.goredcries[NEUTER]) return user.species.goredcries[NEUTER] - /datum/emote/living/carbon/human/gored/run_emote(mob/user, params, type_override, intentional = FALSE, prefix) . = ..() if(!.) @@ -554,7 +492,6 @@ var/image/pain = image('icons/mob/talk.dmi', user, icon_state = "pain") user.add_emote_overlay(pain) - /datum/emote/living/carbon/human/burstscream key = "burstscream" message = "screams in agony!" @@ -562,7 +499,6 @@ flags_emote = EMOTE_FORCED_AUDIO stat_allowed = UNCONSCIOUS - /datum/emote/living/carbon/human/burstscream/get_sound(mob/living/carbon/human/user) if(!user.species) return @@ -571,7 +507,6 @@ if(user.species.burstscreams[NEUTER]) return user.species.burstscreams[NEUTER] - /datum/emote/living/carbon/human/burstscream/run_emote(mob/user, params, type_override, intentional = FALSE, prefix) . = ..() if(!.) @@ -587,7 +522,6 @@ else return 'sound/misc/human_male_sneeze_1.ogg' - /datum/emote/living/carbon/human/sigh/get_sound(mob/living/user) if(isrobot(user)) return @@ -596,7 +530,6 @@ else return 'sound/voice/human/male/sigh_1.ogg' - /datum/emote/living/carbon/human/giggle/get_sound(mob/living/user) if(isrobot(user)) if(user.gender == FEMALE) @@ -608,7 +541,6 @@ else return 'sound/voice/human/male/giggle_1.ogg' - /datum/emote/living/carbon/human/yawn/get_sound(mob/living/user) if(isrobot(user)) return @@ -617,7 +549,6 @@ else return 'sound/voice/human/male/yawn_1.ogg' - /datum/emote/living/carbon/human/moan/get_sound(mob/living/user) if(isrobot(user)) return @@ -626,7 +557,6 @@ else return 'sound/voice/human/male/moan_1.ogg' - /datum/emote/living/carbon/human/cry/get_sound(mob/living/user) if(isrobot(user)) return @@ -635,17 +565,6 @@ else return 'sound/voice/human/male/cry_1.ogg' -/datum/emote/living/carbon/human/medic/get_sound(mob/living/carbon/human/user) - if(isrobot(user)) - if(user.gender == MALE) - if(prob(95)) - return 'sound/voice/robotic/male_medic.ogg' - else - return 'sound/voice/robotic/male_medic2.ogg' - else - return 'sound/voice/robotic/female_medic.ogg' - return ..() - /datum/emote/living/carbon/human/whistle key = "whistle" key_third_person = "whistles" @@ -664,163 +583,3 @@ emote_type = EMOTE_AUDIBLE flags_emote = EMOTE_RESTRAINT_CHECK|EMOTE_MUZZLE_IGNORE|EMOTE_ARMS_CHECK sound = 'sound/misc/sound_misc_knuckles.ogg' - -//Robotic - -/datum/emote/living/carbon/robot - mob_type_allowed_typecache = list(/mob/living/carbon/human/species/robot, /mob/living/carbon/human/species/synthetic, /mob/living/carbon/human/species/early_synthetic) - -/datum/emote/living/carbon/robot/dwoop - key = "dwoop" - key_third_person = "dwoops" - message = "pips happily!" - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/robotic/dwoop.ogg' - -/datum/emote/living/carbon/robot/yes - key = "yes" - message = "emits an affirmative blip." - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/robotic/synth_yes.ogg' - -/datum/emote/living/carbon/robot/no - key = "no" - message = "emits a negative blip." - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/robotic/synth_no.ogg' - -/datum/emote/living/carbon/robot/buzz - key = "buzz" - key_third_person = "buzzes" - message = "buzzes." - message_param = "buzzes at %t." - emote_type = EMOTE_AUDIBLE - sound = 'sound/machines/buzz-sigh.ogg' - -/datum/emote/living/carbon/robot/buzz2 - key = "buzz2" - message = "buzzes twice." - message_param = "buzzes twice at %t." - emote_type = EMOTE_AUDIBLE - sound = 'sound/machines/buzz-two.ogg' - -/datum/emote/living/carbon/robot/beep - key = "beep" - message = "beeps sharply." - message_param = "beeps sharply at %t." - emote_type = EMOTE_AUDIBLE - sound = 'sound/machines/twobeep.ogg' - -/datum/emote/living/carbon/robot/chime - key = "chime" - key_third_person = "chimes" - message = "chimes." - emote_type = EMOTE_AUDIBLE - sound = 'sound/machines/chime.ogg' - -/datum/emote/living/carbon/robot/honk - key = "honk" - key_third_person = "honks" - message = "honks." - emote_type = EMOTE_AUDIBLE - sound = 'sound/items/bikehorn.ogg' - -/datum/emote/living/carbon/robot/ping - key = "ping" - key_third_person = "pings" - message = "pings." - emote_type = EMOTE_AUDIBLE - sound = 'sound/machines/ping.ogg' - -/datum/emote/living/carbon/robot/sad - key = "sad" - message = "plays a sad trombone..." - emote_type = EMOTE_AUDIBLE - sound = 'sound/misc/sadtrombone.ogg' - -/datum/emote/living/carbon/robot/warn - key = "warn" - key_third_person = "warns" - message = "blares an alarm!" - emote_type = EMOTE_AUDIBLE - sound = 'sound/machines/warning-buzzer.ogg' - -/datum/emote/living/carbon/robot/laughtrack - key = "laughtrack" - message = "plays a laughtrack." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/carbon/robot/laughtrack/get_sound(mob/living/user) - return pick('sound/voice/robotic/sitcomLaugh1.ogg', 'sound/voice/robotic/sitcomLaugh2.ogg') - -//Neco Ark - -/datum/emote/living/carbon/necoarc - mob_type_allowed_typecache = /mob/living/carbon/human/species/necoarc - -/datum/emote/living/carbon/necoarc/mudamuda - key = "muda" - key_third_person = "muda muda" - message = "Muda Muda" - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/necoarc/Neco Muda muDa.ogg' - - -/datum/emote/living/carbon/necoarc/bubu //then add to the grenade throw - key = "bubu" - key_third_person = "bu bu" - message = "bu buuu" - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/necoarc/Neco bu buuu.ogg' - - -/datum/emote/living/carbon/necoarc/dori - key = "dori" - key_third_person = "dori dori dori" - message = "dori dori dori" - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/necoarc/Neco dori dori dori.ogg' - - -/datum/emote/living/carbon/necoarc/sayesa - key = "sa" - key_third_person = "sa yesa" - message = "Sa Yesa!" - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/necoarc/Neco Sa Yesa 1.ogg' - - -/datum/emote/living/carbon/necoarc/sayesa/two - key = "sa2" - key_third_person = "sa yesa2" - sound = 'sound/voice/necoarc/Neco Sa Yesa 2.ogg' - - -/datum/emote/living/carbon/necoarc/yanyan - key = "yanyan" - key_third_person = "yanyan yaan" - message = "yanyan yaan" - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/necoarc/Neco yanyan yaan.ogg' - - -/datum/emote/living/carbon/necoarc/nya - key = "nya" - message = "nya" - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/necoarc/Neco-Arc sound effect.ogg' - - -/datum/emote/living/carbon/necoarc/isa - key = "isa" - message = "iiiiisAAAAA!" - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/necoarc/Neco iiiiisAAAAA.ogg' - - -/datum/emote/living/carbon/necoarc/qahu - key = "qahu" - key_third_person = "quiajuuu" - message = "qahuuuuu!" - emote_type = EMOTE_AUDIBLE - sound = 'sound/voice/necoarc/Neco quiajuuubn.ogg' diff --git a/code/modules/mob/living/carbon/human/emote/necoarc.dm b/code/modules/mob/living/carbon/human/emote/necoarc.dm new file mode 100644 index 00000000000..c8bf886e077 --- /dev/null +++ b/code/modules/mob/living/carbon/human/emote/necoarc.dm @@ -0,0 +1,61 @@ +/datum/emote/living/carbon/necoarc + mob_type_allowed_typecache = /mob/living/carbon/human/species/necoarc + +/datum/emote/living/carbon/necoarc/mudamuda + key = "muda" + key_third_person = "muda muda" + message = "Muda Muda" + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/necoarc/Neco Muda muDa.ogg' + +/datum/emote/living/carbon/necoarc/bubu //then add to the grenade throw + key = "bubu" + key_third_person = "bu bu" + message = "bu buuu" + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/necoarc/Neco bu buuu.ogg' + +/datum/emote/living/carbon/necoarc/dori + key = "dori" + key_third_person = "dori dori dori" + message = "dori dori dori" + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/necoarc/Neco dori dori dori.ogg' + +/datum/emote/living/carbon/necoarc/sayesa + key = "sa" + key_third_person = "sa yesa" + message = "Sa Yesa!" + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/necoarc/Neco Sa Yesa 1.ogg' + +/datum/emote/living/carbon/necoarc/sayesa/two + key = "sa2" + key_third_person = "sa yesa2" + sound = 'sound/voice/necoarc/Neco Sa Yesa 2.ogg' + +/datum/emote/living/carbon/necoarc/yanyan + key = "yanyan" + key_third_person = "yanyan yaan" + message = "yanyan yaan" + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/necoarc/Neco yanyan yaan.ogg' + +/datum/emote/living/carbon/necoarc/nya + key = "nya" + message = "nya" + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/necoarc/Neco-Arc sound effect.ogg' + +/datum/emote/living/carbon/necoarc/isa + key = "isa" + message = "iiiiisAAAAA!" + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/necoarc/Neco iiiiisAAAAA.ogg' + +/datum/emote/living/carbon/necoarc/qahu + key = "qahu" + key_third_person = "quiajuuu" + message = "qahuuuuu!" + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/necoarc/Neco quiajuuubn.ogg' diff --git a/code/modules/mob/living/carbon/human/emote/robot.dm b/code/modules/mob/living/carbon/human/emote/robot.dm new file mode 100644 index 00000000000..f89743dbe04 --- /dev/null +++ b/code/modules/mob/living/carbon/human/emote/robot.dm @@ -0,0 +1,88 @@ +/datum/emote/living/carbon/robot // isn't actually robot only + mob_type_allowed_typecache = list(/mob/living/carbon/human/species/robot, /mob/living/carbon/human/species/synthetic, /mob/living/carbon/human/species/early_synthetic) + +/datum/emote/living/carbon/robot/dwoop + key = "dwoop" + key_third_person = "dwoops" + message = "pips happily!" + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/robotic/dwoop.ogg' + +/datum/emote/living/carbon/robot/yes + key = "yes" + message = "emits an affirmative blip." + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/robotic/synth_yes.ogg' + +/datum/emote/living/carbon/robot/no + key = "no" + message = "emits a negative blip." + emote_type = EMOTE_AUDIBLE + sound = 'sound/voice/robotic/synth_no.ogg' + +/datum/emote/living/carbon/robot/buzz + key = "buzz" + key_third_person = "buzzes" + message = "buzzes." + message_param = "buzzes at %t." + emote_type = EMOTE_AUDIBLE + sound = 'sound/machines/buzz-sigh.ogg' + +/datum/emote/living/carbon/robot/buzz2 + key = "buzz2" + message = "buzzes twice." + message_param = "buzzes twice at %t." + emote_type = EMOTE_AUDIBLE + sound = 'sound/machines/buzz-two.ogg' + +/datum/emote/living/carbon/robot/beep + key = "beep" + message = "beeps sharply." + message_param = "beeps sharply at %t." + emote_type = EMOTE_AUDIBLE + sound = 'sound/machines/twobeep.ogg' + +/datum/emote/living/carbon/robot/chime + key = "chime" + key_third_person = "chimes" + message = "chimes." + emote_type = EMOTE_AUDIBLE + sound = 'sound/machines/chime.ogg' + +/datum/emote/living/carbon/robot/honk + key = "honk" + key_third_person = "honks" + message = "honks." + emote_type = EMOTE_AUDIBLE + sound = 'sound/items/bikehorn.ogg' + +/datum/emote/living/carbon/robot/ping + key = "ping" + key_third_person = "pings" + message = "pings." + emote_type = EMOTE_AUDIBLE + sound = 'sound/machines/ping.ogg' + +/datum/emote/living/carbon/robot/sad + key = "sad" + message = "plays a sad trombone..." + emote_type = EMOTE_AUDIBLE + sound = 'sound/misc/sadtrombone.ogg' + +/datum/emote/living/carbon/robot/warn + key = "warn" + key_third_person = "warns" + message = "blares an alarm!" + emote_type = EMOTE_AUDIBLE + sound = 'sound/machines/warning-buzzer.ogg' + +/datum/emote/living/carbon/robot/laughtrack + key = "laughtrack" + message = "plays a laughtrack." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/carbon/robot/laughtrack/get_sound(mob/living/user) + return pick('sound/voice/robotic/sitcomLaugh1.ogg', 'sound/voice/robotic/sitcomLaugh2.ogg') + +/datum/emote/living/carbon/robot/sneeze/get_sound(mob/living/user) + return diff --git a/code/modules/mob/living/carbon/human/emote-yautja.dm b/code/modules/mob/living/carbon/human/emote/yautja.dm similarity index 66% rename from code/modules/mob/living/carbon/human/emote-yautja.dm rename to code/modules/mob/living/carbon/human/emote/yautja.dm index fe38dbbfa23..eea2d4f2bb6 100644 --- a/code/modules/mob/living/carbon/human/emote-yautja.dm +++ b/code/modules/mob/living/carbon/human/emote/yautja.dm @@ -1,108 +1,108 @@ -/datum/emote/living/carbon/human/species/yautja +/datum/emote/living/carbon/human/yautja mob_type_allowed_typecache = /mob/living/carbon/human/species/yautja -/datum/emote/living/carbon/human/species/yautja/anytime +/datum/emote/living/carbon/human/yautja/anytime key = "anytime" sound = 'sound/voice/predator/anytime.ogg' key_third_person = "anytime" message = "any time" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/click +/datum/emote/living/carbon/human/yautja/click key = "click" key_third_person = "click" message = "clicks" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/click/get_sound(mob/living/user) - if(rand(0,100) < 50) +/datum/emote/living/carbon/human/yautja/click/get_sound(mob/living/user) + if(prob(50)) return 'sound/voice/predator/click1.ogg' else return 'sound/voice/predator/click2.ogg' -/datum/emote/living/carbon/human/species/yautja/helpme +/datum/emote/living/carbon/human/yautja/helpme key = "helpme" sound = 'sound/voice/predator/helpme.ogg' key_third_person = "helpme" message = "help me!" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/iseeyou +/datum/emote/living/carbon/human/yautja/iseeyou key = "iseeyou" sound = 'sound/hallucinations/i_see_you2.ogg' key_third_person = "iseeyou" message = "i see you!" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/itsatrap +/datum/emote/living/carbon/human/yautja/itsatrap key = "itsatrap" sound = 'sound/voice/predator/itsatrap.ogg' key_third_person = "itsatrap" message = "it's a trap!" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/laugh1 +/datum/emote/living/carbon/human/yautja/laugh1 key = "laugh1" sound = 'sound/voice/predator/laugh1.ogg' key_third_person = "laugh1" message = "laughs" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/laugh2 +/datum/emote/living/carbon/human/yautja/laugh2 key = "laugh2" sound = 'sound/voice/predator/laugh2.ogg' key_third_person = "laugh2" message = "laughs" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/laugh3 +/datum/emote/living/carbon/human/yautja/laugh3 key = "laugh3" sound = 'sound/voice/predator/laugh3.ogg' key_third_person = "laugh3" message = "laughs" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/laugh4 +/datum/emote/living/carbon/human/yautja/laugh4 key = "laugh4" sound = 'sound/voice/predator/laugh4.ogg' key_third_person = "laugh4" message = "laughs" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/overhere +/datum/emote/living/carbon/human/yautja/overhere key = "overhere" sound = 'sound/voice/predator/overhere.ogg' key_third_person = "overhere" message = "over here!" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/predroar +/datum/emote/living/carbon/human/yautja/predroar key = "predroar" key_third_person = "predroars" message = "roars!" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/predroar/get_sound(mob/living/user) +/datum/emote/living/carbon/human/yautja/predroar/get_sound(mob/living/user) return pick('sound/voice/predator/roar1.ogg', 'sound/voice/predator/roar2.ogg') -/datum/emote/living/carbon/human/species/yautja/predroar2 +/datum/emote/living/carbon/human/yautja/predroar2 key = "predroar2" key_third_person = "predroars2" sound = 'sound/voice/predator/roar3.ogg' message = "roars!" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/loudroar +/datum/emote/living/carbon/human/yautja/loudroar key = "loudroar" key_third_person = "loudroar" message = "roars loudly!" cooldown = 120 SECONDS emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/loudroar/get_sound(mob/living/user) +/datum/emote/living/carbon/human/yautja/loudroar/get_sound(mob/living/user) return pick('sound/voice/predator/roar4.ogg', 'sound/voice/predator/roar5.ogg') -/datum/emote/living/carbon/human/species/yautja/loudroar/run_emote(mob/user, params, type_override, intentional) +/datum/emote/living/carbon/human/yautja/loudroar/run_emote(mob/user, params, type_override, intentional) . = ..() if(!.) return @@ -114,55 +114,55 @@ var/final_dir = dir2text(relative_dir) to_chat(current_mob, span_highdanger("You hear a loud roar coming from [final_dir ? "the [final_dir]" : "nearby"]!")) -/datum/emote/living/carbon/human/species/yautja/turnaround +/datum/emote/living/carbon/human/yautja/turnaround key = "turnaround" key_third_person = "turnaround" message = "turn around!" sound = 'sound/voice/predator/turnaround.ogg' emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/click2 +/datum/emote/living/carbon/human/yautja/click2 key = "click2" key_third_person = "click2" message = "clicks" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/click2/get_sound(mob/living/user) +/datum/emote/living/carbon/human/yautja/click2/get_sound(mob/living/user) return pick('sound/voice/predator/click3.ogg', 'sound/voice/predator/click4.ogg') -/datum/emote/living/carbon/human/species/yautja/aliengrowl +/datum/emote/living/carbon/human/yautja/aliengrowl key = "aliengrowl" key_third_person = "aliengrowl" message = "growls!" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/aliengrowl/get_sound(mob/living/user) +/datum/emote/living/carbon/human/yautja/aliengrowl/get_sound(mob/living/user) return pick('sound/voice/alien/growl1.ogg', 'sound/voice/alien/growl2.ogg') -/datum/emote/living/carbon/human/species/yautja/alienhelp +/datum/emote/living/carbon/human/yautja/alienhelp key = "alienhelp" key_third_person = "alienhelp" message = "needs help!" emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/alienhelp/get_sound(mob/living/user) +/datum/emote/living/carbon/human/yautja/alienhelp/get_sound(mob/living/user) return pick('sound/voice/alien/help1.ogg', 'sound/voice/alien/help2.ogg') -/datum/emote/living/carbon/human/species/yautja/comeonout +/datum/emote/living/carbon/human/yautja/comeonout key = "comeonout" key_third_person = "comeonout" message = "come on out!" sound = 'sound/voice/predator/come_on_out.ogg' emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/overthere +/datum/emote/living/carbon/human/yautja/overthere key = "overthere" key_third_person = "overthere" message = "over there!" sound = 'sound/voice/predator/over_there.ogg' emote_type = EMOTE_AUDIBLE -/datum/emote/living/carbon/human/species/yautja/uglyfreak +/datum/emote/living/carbon/human/yautja/uglyfreak key = "uglyfreak" key_third_person = "uglyfreak" message = "ugly freak!" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 8b96aeb7f44..1af8d9e277a 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -647,8 +647,6 @@ species.create_organs(src) - dextrous = species.has_fine_manipulation - if(species.default_language_holder) language_holder = new species.default_language_holder(src) diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 6d39327ffe2..53434f60987 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -27,7 +27,7 @@ return TRUE if(istype(wear_mask, /obj/item/clothing/mask/facehugger) && H != src) - H.stripPanelUnequip(wear_mask, src, SLOT_WEAR_MASK) + H.stripPanelUnequip(wear_mask, src, SLOT_WEAR_MASK, BUSY_ICON_FACEHUGGER) return TRUE if(health >= get_crit_threshold()) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 2d8022f688b..01ec5561f83 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -11,7 +11,7 @@ buckle_flags = CAN_BE_BUCKLED|CAN_BUCKLE resistance_flags = XENO_DAMAGEABLE appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE|LONG_GLIDE - + dextrous = TRUE hud_type = /datum/hud/human /// Used for preventing possible lags in the med_hud_set_status(), yes it's ugly @@ -107,9 +107,7 @@ ///Auras we can create, used for the order choice UI. var/static/list/command_aura_allowed = list(AURA_HUMAN_MOVE, AURA_HUMAN_HOLD, AURA_HUMAN_FOCUS) - ///Whether we can use another command order yet. Either null or a timer ID. - var/command_aura_cooldown - + ///Strength of the move order aura affecting us var/mobility_aura = 0 var/protection_aura = 0 var/marksman_aura = 0 diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index da0bd8d546d..d060114e32a 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -253,3 +253,27 @@ var/datum/internal_organ/organ = get_organ_slot(string) internal_organs_by_name -= string internal_organs -= organ + +/// Does something. Unshitcode me. +/mob/living/carbon/human/proc/disable_special_items() + set waitfor = FALSE // Scout decloak animation uses sleep(), which is problematic for taser gun + + if(istype(back, /obj/item/storage/backpack/marine/satchel/scout_cloak)) + var/obj/item/storage/backpack/marine/satchel/scout_cloak/SC = back + if(SC.camo_active) + SC.camo_off(src) + return + var/list/cont = list() + for(var/atom/A in contents) + cont += A + if(A.contents.len) + cont += A.contents + + for(var/i in cont) + if(istype(i, /obj/item/assembly/prox_sensor)) + var/obj/item/assembly/prox_sensor/prox = i + if(prox.scanning) + prox.toggle_scan() + if(istype(i, /obj/item/attachable/motiondetector)) + var/obj/item/attachable/motiondetector/md = i + md.clean_operator() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 0c86358fa4f..cef924ff4b3 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -535,20 +535,21 @@ else if(equipped_item == s_store) . = SLOT_S_STORE -/mob/living/carbon/human/stripPanelUnequip(obj/item/I, mob/M, slot_to_process) +/mob/living/carbon/human/stripPanelUnequip(obj/item/I, mob/M, slot_to_process, display_icon = BUSY_ICON_HOSTILE) if(!I.canStrip(M)) return log_combat(src, M, "attempted to remove [key_name(I)] ([slot_to_process])") M.visible_message(span_danger("[src] tries to remove [M]'s [I.name]."), \ - span_userdanger("[src] tries to remove [M]'s [I.name]."), null, 5) - if(do_after(src, HUMAN_STRIP_DELAY, NONE, M, BUSY_ICON_HOSTILE)) - if(Adjacent(M) && I && I == M.get_item_by_slot(slot_to_process)) - M.dropItemToGround(I) - log_combat(src, M, "removed [key_name(I)] ([slot_to_process])") - if(isidcard(I)) - message_admins("[ADMIN_TPMONTY(src)] took the [I] of [ADMIN_TPMONTY(M)].") - + span_userdanger("[src] tries to remove [M]'s [I.name]."), null, 5) + if(!do_after(src, HUMAN_STRIP_DELAY, NONE, M, display_icon)) + return + if(!Adjacent(M)|| !I || I != M.get_item_by_slot(slot_to_process)) + return + M.dropItemToGround(I) + log_combat(src, M, "removed [key_name(I)] ([slot_to_process])") + if(isidcard(I)) + message_admins("[ADMIN_TPMONTY(src)] took the [I] of [ADMIN_TPMONTY(M)].") /mob/living/carbon/human/proc/equipOutfit(outfit, visualsOnly = FALSE, client/override_client) var/datum/outfit/O = null @@ -564,7 +565,6 @@ return O.equip(src, visualsOnly, override_client) - /mob/living/carbon/human/proc/delete_equipment(save_id = FALSE) for(var/i in contents) if(save_id && istype(i, /obj/item/card/id)) diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm index 315802ffd1e..7cd08a9ca78 100644 --- a/code/modules/mob/living/carbon/human/login.dm +++ b/code/modules/mob/living/carbon/human/login.dm @@ -1,6 +1,4 @@ /mob/living/carbon/human/Login() . = ..() - species?.handle_login_special(src) - if(HAS_TRAIT(src, TRAIT_IS_RESURRECTING)) to_chat(src, span_notice("You are resurrecting, hold still...")) diff --git a/code/modules/mob/living/carbon/human/logout.dm b/code/modules/mob/living/carbon/human/logout.dm index fc7f485cd30..9be08269203 100644 --- a/code/modules/mob/living/carbon/human/logout.dm +++ b/code/modules/mob/living/carbon/human/logout.dm @@ -1,6 +1,5 @@ /mob/living/carbon/human/Logout() . = ..() - species?.handle_logout_special(src) if(!key) set_afk_status(MOB_DISCONNECTED) else if(!isclientedaghost(src)) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm deleted file mode 100644 index c2701dbe6d4..00000000000 --- a/code/modules/mob/living/carbon/human/species.dm +++ /dev/null @@ -1,1055 +0,0 @@ -/* - Datum-based species. Should make for much cleaner and easier to maintain species code. -*/ -///TODO SPLIT THIS INTO MULTIPLE FILES - -/datum/species - ///Species name - var/name - var/name_plural - ///what kind of species it is considered - var/species_type = SPECIES_HUMAN - - ///Normal icon file - var/icobase = 'icons/mob/human_races/r_human.dmi' - ///icon state for calculating brute damage icons - var/brute_damage_icon_state = "human_brute" - ///icon state for calculating brute damage icons - var/burn_damage_icon_state = "human_burn" - ///damage mask icon we want to use when drawing wounds - var/damage_mask_icon = 'icons/mob/dam_mask.dmi' - ///If set, draws this from icobase when mob is prone. - var/prone_icon - ///icon for eyes - var/eyes = "eyes_s" - - var/datum/unarmed_attack/unarmed // For empty hand harm-intent attack - var/datum/unarmed_attack/secondary_unarmed // For empty hand harm-intent attack if the first fails. - var/datum/hud_data/hud - var/hud_type - var/slowdown = 0 - var/taste_sensitivity = TASTE_NORMAL - var/gluttonous // Can eat some mobs. 1 for monkeys, 2 for people. - var/rarity_value = 1 // Relative rarity/collector value for this species. Only used by ninja and cultists atm. - var/datum/unarmed_attack/unarmed_type = /datum/unarmed_attack - var/secondary_unarmed_type = /datum/unarmed_attack/bite - var/default_language_holder = /datum/language_holder - var/speech_verb_override - var/secondary_langs = list() // The names of secondary languages that are available to this species. - var/list/speech_sounds // A list of sounds to potentially play when speaking. - var/list/speech_chance - var/has_fine_manipulation = TRUE // Can use small items. - var/count_human = FALSE // Does this count as a human? - - ///Inventory slots the race can't equip stuff to. Golems cannot wear jumpsuits, for example. - var/list/no_equip = list() - - // Some species-specific gibbing data. - var/gibbed_anim = "gibbed-h" - var/dusted_anim = "dust-h" - var/remains_type = /obj/effect/decal/cleanable/ash - var/death_sound - var/death_message = "seizes up and falls limp, their eyes dead and lifeless..." - - /// new maxHealth [/mob/living/carbon/human/var/maxHealth] of the human mob once species is applied - var/total_health = 100 - var/max_stamina = 50 - - var/cold_level_1 = BODYTEMP_COLD_DAMAGE_LIMIT_ONE // Cold damage level 1 below this point. - var/cold_level_2 = BODYTEMP_COLD_DAMAGE_LIMIT_TWO // Cold damage level 2 below this point. - var/cold_level_3 = BODYTEMP_COLD_DAMAGE_LIMIT_THREE // Cold damage level 3 below this point. - - var/heat_level_1 = BODYTEMP_HEAT_DAMAGE_LIMIT_ONE // Heat damage level 1 above this point. - var/heat_level_2 = BODYTEMP_HEAT_DAMAGE_LIMIT_TWO // Heat damage level 2 above this point. - var/heat_level_3 = BODYTEMP_HEAT_DAMAGE_LIMIT_THREE // Heat damage level 2 above this point. - - var/body_temperature = BODYTEMP_NORMAL //non-IS_SYNTHETIC species will try to stabilize at this temperature. (also affects temperature processing) - var/reagent_tag //Used for metabolizing reagents. - - var/darksight = 2 - - var/brute_mod = null // Physical damage reduction/malus. - var/burn_mod = null // Burn damage reduction/malus. - - ///Whether this mob will tell when the user has logged out - var/is_sentient = TRUE - - ///Generic traits tied to having the species. - var/list/inherent_traits = list() - var/species_flags = NONE // Various specific features. - - var/list/preferences = list() - var/list/screams = list() - var/list/paincries = list() - var/list/goredcries = list() - var/list/gasps = list() - var/list/coughs = list() - var/list/burstscreams = list() - var/list/warcries = list() - var/list/laughs = list() - - var/blood_color = "#A10808" //Red. - var/flesh_color = "#FFC896" //Pink. - var/base_color //Used when setting species. - var/hair_color //If the species only has one hair color - - //Used in icon caching. - var/race_key = 0 - var/icon/icon_template - - /// inherent Species-specific verbs. - var/list/inherent_verbs - /// inherent species-specific actions - var/list/inherent_actions - var/list/has_organ = list( - ORGAN_SLOT_HEART = /datum/internal_organ/heart, - ORGAN_SLOT_LUNGS = /datum/internal_organ/lungs, - ORGAN_SLOT_LIVER = /datum/internal_organ/liver, - ORGAN_SLOT_STOMACH = /datum/internal_organ/stomach, - ORGAN_SLOT_KIDNEYS = /datum/internal_organ/kidneys, - ORGAN_SLOT_BRAIN = /datum/internal_organ/brain, - ORGAN_SLOT_APPENDIX = /datum/internal_organ/appendix, - ORGAN_SLOT_EYES = /datum/internal_organ/eyes - ) - - var/knock_down_reduction = 1 //how much the knocked_down effect is reduced per Life call. - var/stun_reduction = 1 //how much the stunned effect is reduced per Life call. - var/knock_out_reduction = 1 //same thing - var/lighting_alpha - var/see_in_dark - - var/datum/namepool/namepool = /datum/namepool - var/special_death_message = "You have perished." // Special death message that gets overwritten if possible. - ///Whether it is possible with this race roundstart - var/joinable_roundstart = FALSE - -/datum/species/New() - if(hud_type) - hud = new hud_type() - else - hud = new() - - if(unarmed_type) - unarmed = new unarmed_type() - if(secondary_unarmed_type) - secondary_unarmed = new secondary_unarmed_type() - if(species_flags & GREYSCALE_BLOOD) - brute_damage_icon_state = "grayscale" - -/datum/species/proc/create_organs(mob/living/carbon/human/organless_human) //Handles creation of mob organs and limbs. - - organless_human.limbs = list() - organless_human.internal_organs = list() - organless_human.internal_organs_by_name = list() - - //This is a basic humanoid limb setup. - var/datum/limb/chest/new_chest = new(null, organless_human) - organless_human.limbs += new_chest - var/datum/limb/groin/new_groin = new(new_chest, organless_human) - organless_human.limbs += new_groin - organless_human.limbs += new/datum/limb/head(new_chest, organless_human) - var/datum/limb/l_arm/new_l_arm = new(new_chest, organless_human) - organless_human.limbs += new_l_arm - var/datum/limb/r_arm/new_r_arm = new(new_chest, organless_human) - organless_human.limbs += new_r_arm - var/datum/limb/l_leg/new_l_leg = new(new_groin, organless_human) - organless_human.limbs += new_l_leg - var/datum/limb/r_leg/new_r_leg = new(new_groin, organless_human) - organless_human.limbs += new_r_leg - organless_human.limbs += new/datum/limb/hand/l_hand(new_l_arm, organless_human) - organless_human.limbs += new/datum/limb/hand/r_hand(new_r_arm, organless_human) - organless_human.limbs += new/datum/limb/foot/l_foot(new_l_leg, organless_human) - organless_human.limbs += new/datum/limb/foot/r_foot(new_r_leg, organless_human) - - for(var/datum/internal_organ/organ AS in has_organ) - var/datum/internal_organ/organ_type = has_organ[organ] - organless_human.internal_organs_by_name[organ] = new organ_type(organless_human) - - if(species_flags & ROBOTIC_LIMBS) - for(var/datum/limb/robotic_limb AS in organless_human.limbs) - if(robotic_limb.limb_status & LIMB_DESTROYED) - continue - robotic_limb.add_limb_flags(LIMB_ROBOT) - -/datum/species/proc/hug(mob/living/carbon/human/H, mob/living/target) - if(H.zone_selected == "head") - H.visible_message(span_notice("[H] pats [target] on the head."), \ - span_notice("You pat [target] on the head."), null, 4) - else if(H.zone_selected == "l_hand" && CONFIG_GET(flag/fun_allowed)) - H.visible_message(span_notice("[H] holds [target] 's left hand."), \ - span_notice("You hold [target]'s left hand."), null, 4) - else if (H.zone_selected == "r_hand" && CONFIG_GET(flag/fun_allowed)) - H.visible_message(span_notice("[H] holds [target] 's right hand."), \ - span_notice("You hold [target]'s right hand."), null, 4) - else - H.visible_message(span_notice("[H] hugs [target] to make [target.p_them()] feel better!"), \ - span_notice("You hug [target] to make [target.p_them()] feel better!"), null, 4) - -/datum/species/proc/random_name(gender) - return GLOB.namepool[namepool].get_random_name(gender) - -/datum/species/proc/prefs_name(datum/preferences/prefs) - return prefs.real_name - -/datum/species/human/prefs_name(datum/preferences/prefs) - . = ..() - if(CONFIG_GET(flag/humans_need_surnames)) - var/firstspace = findtext(., " ") - if(!firstspace || firstspace == length(.)) - . += " " + pick(SSstrings.get_list_from_file("names/last_name")) - -/datum/species/synthetic/prefs_name(datum/preferences/prefs) - . = prefs.synthetic_name - if(!. || . == "Undefined") //In case they don't have a name set. - switch(prefs.gender) - if(MALE) - . = "David" - if(FEMALE) - . = "Anna" - else - . = "Jeri" - to_chat(prefs.parent, span_warning("You forgot to set your synthetic name in your preferences. Please do so next time.")) - -/datum/species/early_synthetic/prefs_name(datum/preferences/prefs) - . = prefs.synthetic_name - if(!. || . == "Undefined") //In case they don't have a name set. - switch(prefs.gender) - if(MALE) - . = "David" - if(FEMALE) - . = "Anna" - else - . = "Jeri" - to_chat(prefs.parent, span_warning("You forgot to set your synthetic name in your preferences. Please do so next time.")) - -/datum/species/robot/prefs_name(datum/preferences/prefs) - . = prefs.squad_robot_name - if(!. || . == "Undefined") //In case they don't have a name set. - . = GLOB.namepool[namepool].get_random_name() - to_chat(prefs.parent, span_warning("You forgot to set your robot in your preferences. Please do so next time.")) - -/datum/species/proc/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) - SHOULD_CALL_PARENT(TRUE) //remember to call base procs kids - for(var/slot_id in no_equip) - var/obj/item/thing = H.get_item_by_slot(slot_id) - if(thing && !is_type_in_list(src,thing.species_exception)) - H.dropItemToGround(thing) - for(var/newtrait in inherent_traits) - ADD_TRAIT(H, newtrait, SPECIES_TRAIT) - H.maxHealth += total_health - (old_species ? old_species.total_health : initial(H.maxHealth)) - -//special things to change after we're no longer that species -/datum/species/proc/post_species_loss(mob/living/carbon/human/H) - SHOULD_CALL_PARENT(TRUE) - for(var/oldtrait in inherent_traits) - REMOVE_TRAIT(H, oldtrait, SPECIES_TRAIT) - -/// Removes all species-specific verbs and actions -/datum/species/proc/remove_inherent_abilities(mob/living/carbon/human/H) - if(inherent_verbs) - remove_verb(H, inherent_verbs) - if(inherent_actions) - for(var/action_path in inherent_actions) - var/datum/action/old_species_action = H.actions_by_path[action_path] - qdel(old_species_action) - return - -/// Adds all species-specific verbs and actions -/datum/species/proc/add_inherent_abilities(mob/living/carbon/human/H) - if(inherent_verbs) - add_verb(H, inherent_verbs) - if(inherent_actions) - for(var/action_path in inherent_actions) - var/datum/action/new_species_action = new action_path(H) - new_species_action.give_action(H) - return - -/datum/species/proc/handle_post_spawn(mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. - add_inherent_abilities(H) - -/datum/species/proc/handle_death(mob/living/carbon/human/H) //Handles any species-specific death events. - -//TODO KILL ME -///Snowflake proc for monkeys so they can call attackpaw -/datum/species/proc/spec_unarmedattack(mob/living/carbon/human/user, atom/target) - return FALSE - -//Only used by horrors at the moment. Only triggers if the mob is alive and not dead. -/datum/species/proc/handle_unique_behavior(mob/living/carbon/human/H) - return - -/// Used to update alien icons for aliens. -/datum/species/proc/handle_login_special(mob/living/carbon/human/H) - return - -// As above. -/datum/species/proc/handle_logout_special(mob/living/carbon/human/H) - return - -// Builds the HUD using species-specific icons and usable slots. -/datum/species/proc/build_hud(mob/living/carbon/human/H) - return - -// Grabs the window recieved when you click-drag someone onto you. -/datum/species/proc/get_inventory_dialogue(mob/living/carbon/human/H) - return - -//Used by xenos understanding larvae and dionaea understanding nymphs. -/datum/species/proc/can_understand(mob/other) - return - -/datum/species/proc/handle_fire(mob/living/carbon/human/H) - return - -/datum/species/proc/update_body(mob/living/carbon/human/H) - return - -/datum/species/proc/update_inv_head(mob/living/carbon/human/H) - return - -/datum/species/proc/update_inv_w_uniform(mob/living/carbon/human/H) - return - -/datum/species/proc/update_inv_wear_suit(mob/living/carbon/human/H) - return - -/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) - if(CHECK_BITFIELD(species_flags, NO_CHEM_METABOLIZATION)) //explicit - H.reagents.del_reagent(chem.type) //for the time being - return TRUE - if(CHECK_BITFIELD(species_flags, NO_POISON) && istype(chem, /datum/reagent/toxin)) - H.reagents.remove_reagent(chem.type, chem.custom_metabolism * H.metabolism_efficiency) - return TRUE -//RUTGMC EDIT ADDITION BEGIN - Preds - if(isyautja(H) && istype(chem, /datum/reagent/medicine)) - H.reagents.remove_reagent(chem.type, chem.custom_metabolism * H.metabolism_efficiency) - return TRUE -//RUTGMC EDIT ADDITION END - if(CHECK_BITFIELD(species_flags, NO_OVERDOSE)) //no stacking - if(chem.overdose_threshold && chem.volume > chem.overdose_threshold) - H.reagents.remove_reagent(chem.type, chem.volume - chem.overdose_threshold) - return FALSE - -/datum/species/human - name = "Human" - name_plural = "Humans" - unarmed_type = /datum/unarmed_attack/punch - species_flags = HAS_SKIN_TONE|HAS_LIPS|HAS_UNDERWEAR - count_human = TRUE - - screams = list(MALE = "male_scream", FEMALE = "female_scream") - paincries = list(MALE = "male_pain", FEMALE = "female_pain") - goredcries = list(MALE = "male_gored", FEMALE = "female_gored") - gasps = list(MALE = "male_gasp", FEMALE = "female_gasp") - coughs = list(MALE = "male_cough", FEMALE = "female_cough") - burstscreams = list(MALE = "male_preburst", FEMALE = "female_preburst") - warcries = list(MALE = "male_warcry", FEMALE = "female_warcry") - laughs = list(MALE = "male_laugh", FEMALE = "female_laugh") - special_death_message = "You have perished.
But it is not the end of you yet... if you still have your body with your head still attached, wait until somebody can resurrect you..." - joinable_roundstart = TRUE - - -/datum/species/human/vatborn - name = "Vatborn" - name_plural = "Vatborns" - icobase = 'icons/mob/human_races/r_vatborn.dmi' - namepool = /datum/namepool/vatborn - -/datum/species/human/vatborn/prefs_name(datum/preferences/prefs) - return prefs.real_name - -/datum/species/human/vatgrown - name = "Vat-Grown Human" - name_plural = "Vat-Grown Humans" - icobase = 'icons/mob/human_races/r_vatgrown.dmi' - brute_mod = 1.05 - burn_mod = 1.05 - slowdown = 0.05 - joinable_roundstart = FALSE - -/datum/species/human/vatgrown/random_name(gender) - return "CS-[gender == FEMALE ? "F": "M"]-[rand(111,999)]" - -/datum/species/human/vatgrown/prefs_name(datum/preferences/prefs) - return prefs.real_name - -/datum/species/human/vatgrown/handle_post_spawn(mob/living/carbon/human/H) - . = ..() - H.h_style = "Bald" - H.set_skills(getSkillsType(/datum/skills/vatgrown)) - -/datum/species/human/vatgrown/early - name = "Early Vat-Grown Human" - name_plural = "Early Vat-Grown Humans" - brute_mod = 1.3 - burn_mod = 1.3 - slowdown = 0.3 - - var/timerid - -/datum/species/human/vatgrown/early/handle_post_spawn(mob/living/carbon/human/H) - . = ..() - H.set_skills(getSkillsType(/datum/skills/vatgrown/early)) - timerid = addtimer(CALLBACK(src, PROC_REF(handle_age), H), 15 MINUTES, TIMER_STOPPABLE) - -/datum/species/human/vatgrown/early/post_species_loss(mob/living/carbon/human/H) - . = ..() - // Ensure we don't update the species again - if(timerid) - deltimer(timerid) - timerid = null - -/datum/species/human/vatgrown/early/proc/handle_age(mob/living/carbon/human/H) - H.set_species("Vat-Grown Human") - - -/datum/species/robot - name = "Combat Robot" - name_plural = "Combat Robots" - species_type = SPECIES_COMBAT_ROBOT - icobase = 'icons/mob/human_races/r_robot.dmi' - damage_mask_icon = 'icons/mob/dam_mask_robot.dmi' - brute_damage_icon_state = "robot_brute" - burn_damage_icon_state = "robot_burn" - eyes = "blank_eyes" - hud_type = /datum/hud_data/robotic - default_language_holder = /datum/language_holder/robot - namepool = /datum/namepool/robotic - - unarmed_type = /datum/unarmed_attack/punch/strong - total_health = 100 - slowdown = SHOES_SLOWDOWN //because they don't wear boots. - - cold_level_1 = -1 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 500 - heat_level_2 = 1000 - heat_level_3 = 2000 - - body_temperature = 350 - - inherent_traits = list(TRAIT_NON_FLAMMABLE, TRAIT_IMMEDIATE_DEFIB) - species_flags = NO_BREATHE|NO_BLOOD|NO_POISON|NO_PAIN|NO_CHEM_METABOLIZATION|NO_STAMINA|DETACHABLE_HEAD|HAS_NO_HAIR|ROBOTIC_LIMBS|IS_INSULATED - - no_equip = list( - SLOT_W_UNIFORM, - SLOT_HEAD, - SLOT_WEAR_MASK, - SLOT_WEAR_SUIT, - SLOT_SHOES, - SLOT_GLOVES, - SLOT_GLASSES, - ) - blood_color = "#2d2055" //"oil" color - hair_color = "#00000000" - has_organ = list() - - - screams = list(MALE = "robot_scream", FEMALE = "robot_scream", PLURAL = "robot_scream", NEUTER = "robot_scream") - paincries = list(MALE = "robot_pain", FEMALE = "robot_pain", PLURAL = "robot_pain", NEUTER = "robot_pain") - goredcries = list(MALE = "robot_scream", FEMALE = "robot_scream", PLURAL = "robot_scream", NEUTER = "robot_scream") - warcries = list(MALE = "robot_warcry", FEMALE = "robot_warcry", PLURAL = "robot_warcry", NEUTER = "robot_warcry") - laughs = list(MALE = "robot_male_laugh", FEMALE = "robot_female_laugh", PLURAL = "robot_male_laugh", NEUTER = "robot_female_laugh") - death_message = "shudders violently whilst spitting out error text before collapsing, their visual sensor darkening..." - special_death_message = "You have been shut down.
But it is not the end of you yet... if you still have your body, wait until somebody can resurrect you..." - joinable_roundstart = FALSE - - inherent_actions = list(/datum/action/repair_self) - -/datum/species/robot/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) - . = ..() - H.speech_span = SPAN_ROBOT - H.health_threshold_crit = -100 - -/datum/species/robot/post_species_loss(mob/living/carbon/human/H) - . = ..() - H.speech_span = initial(H.speech_span) - H.health_threshold_crit = -50 - -/datum/species/robot/handle_unique_behavior(mob/living/carbon/human/H) - if(H.health <= 0 && H.health > -50) - H.clear_fullscreen("robotlow") - H.overlay_fullscreen("robothalf", /atom/movable/screen/fullscreen/machine/robothalf) - else if(H.health <= -50) - H.clear_fullscreen("robothalf") - H.overlay_fullscreen("robotlow", /atom/movable/screen/fullscreen/machine/robotlow) - else - H.clear_fullscreen("robothalf") - H.clear_fullscreen("robotlow") - if(H.health > -25) //Staggerslowed if below crit threshold. - return - H.Stagger(2 SECONDS) - H.adjust_slowdown(1) - -///Lets a robot repair itself over time at the cost of being stunned and blind -/datum/action/repair_self - name = "Activate autorepair" - action_icon_state = "suit_configure" - keybinding_signals = list( - KEYBINDING_NORMAL = COMSIG_KB_ROBOT_AUTOREPAIR, - ) - -/datum/action/repair_self/can_use_action() - . = ..() - if(!.) - return - return !owner.incapacitated() - -/datum/action/repair_self/action_activate() - . = ..() - if(!. || !ishuman(owner)) - return - var/mob/living/carbon/human/howner = owner - howner.apply_status_effect(STATUS_EFFECT_REPAIR_MODE, 10 SECONDS) - howner.balloon_alert_to_viewers("Repairing") - -/datum/species/robot/alpharii - name = "Hammerhead Combat Robot" - name_plural = "Hammerhead Combat Robots" - icobase = 'icons/mob/human_races/r_robot_alpharii.dmi' - joinable_roundstart = FALSE - -/datum/species/robot/charlit - name = "Chilvaris Combat Robot" - name_plural = "Chilvaris Combat Robots" - icobase = 'icons/mob/human_races/r_robot_charlit.dmi' - joinable_roundstart = FALSE - -/datum/species/robot/deltad - name = "Ratcher Combat Robot" - name_plural = "Ratcher Combat Robots" - icobase = 'icons/mob/human_races/r_robot_deltad.dmi' - joinable_roundstart = FALSE - -/datum/species/robot/bravada - name = "Sterling Combat Robot" - name_plural = "Sterling Combat Robots" - icobase = 'icons/mob/human_races/r_robot_bravada.dmi' - joinable_roundstart = FALSE - -/mob/living/carbon/human/species/robot/binarycheck(mob/H) - return TRUE - -/datum/species/synthetic - name = "Synthetic" - name_plural = "Synthetics" - - hud_type = /datum/hud_data/robotic - default_language_holder = /datum/language_holder/synthetic - unarmed_type = /datum/unarmed_attack/punch - rarity_value = 2 - - total_health = 125 //more health than regular humans - - brute_mod = 0.70 - burn_mod = 0.70 //Synthetics should not be instantly melted by acid compared to humans - This is a test to hopefully fix very glaring issues involving synthetics taking 2.6 trillion damage when so much as touching acid - - cold_level_1 = -1 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 500 - heat_level_2 = 1000 - heat_level_3 = 2000 - - body_temperature = 350 - - species_flags = NO_BREATHE|NO_SCAN|NO_BLOOD|NO_POISON|NO_PAIN|IS_SYNTHETIC|NO_CHEM_METABOLIZATION|NO_STAMINA|DETACHABLE_HEAD|HAS_LIPS|HAS_UNDERWEAR|HAS_SKIN_COLOR|ROBOTIC_LIMBS|GREYSCALE_BLOOD - - blood_color = "#EEEEEE" - - has_organ = list() - - lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE - see_in_dark = 8 - - screams = list(MALE = "male_scream", FEMALE = "female_scream") - paincries = list(MALE = "male_pain", FEMALE = "female_pain") - goredcries = list(MALE = "male_gored", FEMALE = "female_gored") - warcries = list(MALE = "male_warcry", FEMALE = "female_warcry") - laughs = list(MALE = "male_laugh", FEMALE = "female_laugh") - special_death_message = "You have been shut down.
But it is not the end of you yet... if you still have your body, wait until somebody can resurrect you..." - -/datum/species/synthetic/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) - . = ..() - var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED_SYNTH] - AH.add_hud_to(H) - - -/datum/species/synthetic/post_species_loss(mob/living/carbon/human/H) - . = ..() - var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED_SYNTH] - AH.remove_hud_from(H) - -/mob/living/carbon/human/species/synthetic/binarycheck(mob/H) - return TRUE - -/datum/species/early_synthetic // Worse at medical, better at engineering. Tougher in general than later synthetics. - name = "Early Synthetic" - name_plural = "Early Synthetics" - icobase = 'icons/mob/human_races/r_synthetic.dmi' - hud_type = /datum/hud_data/robotic - default_language_holder = /datum/language_holder/synthetic - unarmed_type = /datum/unarmed_attack/punch - rarity_value = 1.5 - slowdown = 1.15 //Slower than Late Synths. - total_health = 200 //Tough boys, very tough boys. - brute_mod = 0.6 - burn_mod = 0.6 - - cold_level_1 = -1 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 500 - heat_level_2 = 1000 - heat_level_3 = 2000 - - body_temperature = 350 - - species_flags = NO_BREATHE|NO_SCAN|NO_BLOOD|NO_POISON|NO_PAIN|IS_SYNTHETIC|NO_CHEM_METABOLIZATION|NO_STAMINA|DETACHABLE_HEAD|HAS_UNDERWEAR|ROBOTIC_LIMBS|GREYSCALE_BLOOD - - blood_color = "#EEEEEE" - hair_color = "#000000" - has_organ = list() - - lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE - see_in_dark = 8 - - screams = list(MALE = "male_scream", FEMALE = "female_scream") - paincries = list(MALE = "male_pain", FEMALE = "female_pain") - goredcries = list(MALE = "male_gored", FEMALE = "female_gored") - warcries = list(MALE = "male_warcry", FEMALE = "female_warcry") - laughs = list(MALE = "male_laugh", FEMALE = "female_laugh") - special_death_message = "You have been shut down.
But it is not the end of you yet... if you still have your body, wait until somebody can resurrect you..." - -/datum/species/early_synthetic/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) - . = ..() - var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED_SYNTH] - AH.add_hud_to(H) - - -/datum/species/early_synthetic/post_species_loss(mob/living/carbon/human/H) - . = ..() - var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED_SYNTH] - AH.remove_hud_from(H) - -/mob/living/carbon/human/species/early_synthetic/binarycheck(mob/H) - return TRUE - - -/mob/living/carbon/human/proc/reset_jitteriness() //todo kill this - jitteriness = 0 - -//todo: wound overlays are strange for monkeys and should likely use icon adding instead -//im not about to cram in that refactor with a carbon -> species refactor though -/datum/species/monkey - name = "Monkey" - name_plural = "Monkeys" - icobase = 'icons/mob/human_races/r_monkey.dmi' - species_flags = HAS_NO_HAIR|NO_STAMINA|DETACHABLE_HEAD - inherent_traits = list(TRAIT_CAN_VENTCRAWL) - reagent_tag = IS_MONKEY - eyes = "blank_eyes" - speech_verb_override = "chimpers" - unarmed_type = /datum/unarmed_attack/bite/strong - secondary_unarmed_type = /datum/unarmed_attack/punch/strong - joinable_roundstart = FALSE - has_fine_manipulation = TRUE //monki gun - death_message = "lets out a faint chimper as it collapses and stops moving..." - dusted_anim = "dust-m" - gibbed_anim = "gibbed-m" - is_sentient = FALSE - -/datum/species/monkey/handle_unique_behavior(mob/living/carbon/human/H) - if(!H.client && H.stat == CONSCIOUS) - if(prob(33) && H.canmove && !H.buckled && isturf(H.loc) && !H.pulledby) //won't move if being pulled - step(H, pick(GLOB.cardinals)) - - if(prob(1)) - H.emote(pick("scratch","jump","roll","tail")) - -/datum/species/monkey/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) - . = ..() - H.allow_pass_flags |= PASS_LOW_STRUCTURE - -/datum/species/monkey/spec_unarmedattack(mob/living/carbon/human/user, atom/target) - if(!iscarbon(target)) - return FALSE - var/mob/living/carbon/victim = target - if(prob(25)) - victim.visible_message(span_danger("[user]'s bite misses [victim]!"), - span_danger("You avoid [user]'s bite!"), span_hear("You hear jaws snapping shut!")) - to_chat(user, span_danger("Your bite misses [victim]!")) - return TRUE - victim.apply_damage(rand(10, 20), BRUTE, "chest", updating_health = TRUE) - victim.visible_message(span_danger("[name] bites [victim]!"), - span_userdanger("[name] bites you!"), span_hear("You hear a chomp!")) - to_chat(user, span_danger("You bite [victim]!")) - target.attack_hand(user) - return TRUE - -/datum/species/monkey/random_name(gender,unique,lastname) - return "[lowertext(name)] ([rand(1,999)])" - -/datum/species/monkey/tajara - name = "Farwa" - icobase = 'icons/mob/human_races/r_farwa.dmi' - speech_verb_override = "mews" - -/datum/species/monkey/skrell - name = "Naera" - icobase = 'icons/mob/human_races/r_naera.dmi' - speech_verb_override = "squiks" - -/datum/species/monkey/unathi - name = "Stok" - icobase = 'icons/mob/human_races/r_stok.dmi' - speech_verb_override = "hisses" - -/datum/species/monkey/yiren - name = "Yiren" - icobase = 'icons/mob/human_races/r_yiren.dmi' - speech_verb_override = "grumbles" - cold_level_1 = ICE_COLONY_TEMPERATURE - 20 - cold_level_2 = ICE_COLONY_TEMPERATURE - 40 - cold_level_3 = ICE_COLONY_TEMPERATURE - 80 - -/datum/species/sectoid - name = "Sectoid" - name_plural = "Sectoids" - icobase = 'icons/mob/human_races/r_sectoid.dmi' - default_language_holder = /datum/language_holder/sectoid - eyes = "blank_eyes" - speech_verb_override = "transmits" - count_human = TRUE - total_health = 80 - - species_flags = HAS_NO_HAIR|NO_BREATHE|NO_POISON|NO_PAIN|USES_ALIEN_WEAPONS|NO_DAMAGE_OVERLAY - - paincries = list("neuter" = 'sound/voice/sectoid_death.ogg') - death_sound = 'sound/voice/sectoid_death.ogg' - - blood_color = "#00FF00" - flesh_color = "#C0C0C0" - - reagent_tag = IS_SECTOID - - namepool = /datum/namepool/sectoid - special_death_message = "You have perished." - -/datum/species/moth - name = "Moth" - name_plural = "Moth" - icobase = 'icons/mob/human_races/r_moth.dmi' - default_language_holder = /datum/language_holder/moth - eyes = "blank_eyes" - speech_verb_override = "flutters" - count_human = TRUE - - species_flags = HAS_LIPS|HAS_NO_HAIR - preferences = list("moth_wings" = "Wings") - - screams = list("neuter" = 'sound/voice/moth_scream.ogg') - paincries = list("neuter" = 'sound/voice/human/male/pain_3.ogg') - goredcries = list("neuter" = 'sound/voice/moth_scream.ogg') - burstscreams = list("neuter" = 'sound/voice/moth_scream.ogg') - warcries = list("neuter" = 'sound/voice/moth_scream.ogg') - laughs = list("neuter" = 'sound/voice/silly_laugh.ogg') - - flesh_color = "#E5CD99" - - reagent_tag = IS_MOTH - - namepool = /datum/namepool/moth - -/datum/species/moth/handle_fire(mob/living/carbon/human/H) - if(H.moth_wings != "Burnt Off" && H.bodytemperature >= 400 && H.fire_stacks > 0) - to_chat(H, span_danger("Your precious wings burn to a crisp!")) - H.moth_wings = "Burnt Off" - H.update_body() - -/datum/species/moth/proc/update_moth_wings(mob/living/carbon/human/H) - H.remove_overlay(MOTH_WINGS_LAYER) - H.remove_underlay(MOTH_WINGS_BEHIND_LAYER) - - var/datum/sprite_accessory/moth_wings/wings = GLOB.moth_wings_list[H.moth_wings] - - if(wings) - H.overlays_standing[MOTH_WINGS_LAYER] = image(wings.icon, icon_state = "m_moth_wings_[wings.icon_state]_FRONT") - H.underlays_standing[MOTH_WINGS_BEHIND_LAYER] = image(wings.icon, icon_state = "m_moth_wings_[wings.icon_state]_BEHIND") - H.apply_overlay(MOTH_WINGS_LAYER) - H.apply_underlay(MOTH_WINGS_BEHIND_LAYER) - -/datum/species/moth/update_body(mob/living/carbon/human/H) - update_moth_wings(H) - -/datum/species/moth/update_inv_head(mob/living/carbon/human/H) - update_moth_wings(H) - -/datum/species/moth/update_inv_w_uniform(mob/living/carbon/human/H) - update_moth_wings(H) - -/datum/species/moth/update_inv_wear_suit(mob/living/carbon/human/H) - update_moth_wings(H) - -/datum/species/moth/post_species_loss(mob/living/carbon/human/H) - . = ..() - H.remove_overlay(MOTH_WINGS_LAYER) - H.remove_underlay(MOTH_WINGS_BEHIND_LAYER) - - -/datum/species/skeleton - name = "Skeleton" - name_plural = "skeletons" - icobase = 'icons/mob/human_races/r_skeleton.dmi' - unarmed_type = /datum/unarmed_attack/punch - speech_verb_override = "rattles" - count_human = TRUE - - species_flags = NO_BREATHE|NO_SCAN|NO_BLOOD|NO_POISON|NO_CHEM_METABOLIZATION|DETACHABLE_HEAD // Where we're going, we don't NEED underwear. - - screams = list("neuter" = 'sound/voice/skeleton_scream.ogg') // RATTLE ME BONES - paincries = list("neuter" = 'sound/voice/skeleton_scream.ogg') - goredcries = list("neuter" = 'sound/voice/skeleton_scream.ogg') - burstscreams = list("neuter" = 'sound/voice/moth_scream.ogg') - death_message = "collapses in a pile of bones, with a final rattle..." - death_sound = list("neuter" = 'sound/voice/skeleton_scream.ogg') - warcries = list("neuter" = 'sound/voice/skeleton_warcry.ogg') // AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - namepool = /datum/namepool/skeleton - -///Called when using the shredding behavior. -/datum/species/proc/can_shred(mob/living/carbon/human/H) - if(H.a_intent != INTENT_HARM) - return FALSE - - if(unarmed.is_usable(H)) - if(unarmed.shredding) - return TRUE - else if(secondary_unarmed.is_usable(H)) - if(secondary_unarmed.shredding) - return TRUE - return FALSE - -//Species unarmed attacks -/datum/unarmed_attack - var/attack_verb = list("attack") // Empty hand hurt intent verb. - var/damage = 0 // Extra empty hand attack damage. - var/attack_sound = "punch" - var/miss_sound = 'sound/weapons/punchmiss.ogg' - var/shredding = 0 // Calls the old attack_alien() behavior on objects/mobs when on harm intent. - var/sharp = 0 - var/edge = 0 - -/datum/unarmed_attack/proc/is_usable(mob/living/carbon/human/user) - if(user.restrained()) - return FALSE - - // Check if they have a functioning hand. - var/datum/limb/E = user.get_limb("l_hand") - if(E?.is_usable()) - return TRUE - - E = user.get_limb("r_hand") - if(E?.is_usable()) - return TRUE - return FALSE - -/datum/unarmed_attack/bite - attack_verb = list("bite") // 'x has biteed y', needs work. - attack_sound = 'sound/weapons/bite.ogg' - shredding = 0 - damage = 5 - sharp = 1 - edge = 1 - -/datum/unarmed_attack/bite/is_usable(mob/living/carbon/human/user) - if (user.wear_mask && istype(user.wear_mask, /obj/item/clothing/mask/muzzle)) - return FALSE - return TRUE - -/datum/unarmed_attack/punch - attack_verb = list("punch") - damage = 3 - -/datum/unarmed_attack/punch/strong - attack_verb = list("punch","bust","jab") - damage = 10 - -/datum/unarmed_attack/claws - attack_verb = list("scratch", "claw") - attack_sound = 'sound/weapons/slice.ogg' - miss_sound = 'sound/weapons/slashmiss.ogg' - damage = 5 - sharp = 1 - edge = 1 - -/datum/unarmed_attack/claws/strong - attack_verb = list("slash") - damage = 10 - shredding = 1 - -/datum/unarmed_attack/bite/strong - attack_verb = list("maul") - damage = 15 - shredding = 1 - -/datum/hud_data - var/icon // If set, overrides ui_style. - var/has_a_intent = TRUE // Set to draw intent box. - var/has_m_intent = TRUE // Set to draw move intent box. - var/has_warnings = TRUE // Set to draw environment warnings. - var/has_pressure = TRUE // Draw the pressure indicator. - var/has_nutrition = TRUE // Draw the nutrition indicator. - var/has_bodytemp = TRUE // Draw the bodytemp indicator. - var/has_hands = TRUE // Set to draw shand. - var/has_drop = TRUE // Set to draw drop button. - var/has_throw = TRUE // Set to draw throw button. - var/has_resist = TRUE // Set to draw resist button. - var/list/equip_slots = list() // Checked by mob_can_equip(). - - // Contains information on the position and tag for all inventory slots - // to be drawn for the mob. This is fairly delicate, try to avoid messing with it - // unless you know exactly what it does. - var/list/gear = list( - "i_clothing" = list("loc" = ui_iclothing, "slot" = SLOT_W_UNIFORM, "state" = "uniform", "toggle" = TRUE), - "o_clothing" = list("loc" = ui_oclothing, "slot" = SLOT_WEAR_SUIT, "state" = "suit", "toggle" = TRUE), - "mask" = list("loc" = ui_mask, "slot" = SLOT_WEAR_MASK, "state" = "mask", "toggle" = TRUE), - "gloves" = list("loc" = ui_gloves, "slot" = SLOT_GLOVES, "state" = "gloves", "toggle" = TRUE), - "eyes" = list("loc" = ui_glasses, "slot" = SLOT_GLASSES, "state" = "glasses","toggle" = TRUE), - "wear_ear" = list("loc" = ui_wear_ear, "slot" = SLOT_EARS, "state" = "ears", "toggle" = TRUE), - "head" = list("loc" = ui_head, "slot" = SLOT_HEAD, "state" = "head", "toggle" = TRUE), - "shoes" = list("loc" = ui_shoes, "slot" = SLOT_SHOES, "state" = "shoes", "toggle" = TRUE), - "suit storage" = list("loc" = ui_sstore1, "slot" = SLOT_S_STORE, "state" = "suit_storage"), - "back" = list("loc" = ui_back, "slot" = SLOT_BACK, "state" = "back"), - "id" = list("loc" = ui_id, "slot" = SLOT_WEAR_ID, "state" = "id"), - "storage1" = list("loc" = ui_storage1, "slot" = SLOT_L_STORE, "state" = "pocket"), - "storage2" = list("loc" = ui_storage2, "slot" = SLOT_R_STORE, "state" = "pocket"), - "belt" = list("loc" = ui_belt, "slot" = SLOT_BELT, "state" = "belt") - ) - -/datum/hud_data/New() - . = ..() - for(var/slot in gear) - equip_slots |= gear[slot]["slot"] - - if(has_hands) - equip_slots |= SLOT_L_HAND - equip_slots |= SLOT_R_HAND - equip_slots |= SLOT_HANDCUFFED - if(SLOT_HEAD in equip_slots) - equip_slots |= SLOT_IN_HEAD - if(SLOT_BACK in equip_slots) - equip_slots |= SLOT_IN_BACKPACK - equip_slots |= SLOT_IN_B_HOLSTER - if(SLOT_BELT in equip_slots) - equip_slots |= SLOT_IN_HOLSTER - equip_slots |= SLOT_IN_BELT - if(SLOT_WEAR_SUIT in equip_slots) - equip_slots |= SLOT_IN_S_HOLSTER - equip_slots |= SLOT_IN_SUIT - if(SLOT_SHOES in equip_slots) - equip_slots |= SLOT_IN_BOOT - if(SLOT_W_UNIFORM in equip_slots) - equip_slots |= SLOT_IN_STORAGE - equip_slots |= SLOT_IN_L_POUCH - equip_slots |= SLOT_IN_R_POUCH - equip_slots |= SLOT_ACCESSORY - equip_slots |= SLOT_IN_ACCESSORY - -/datum/hud_data/robotic - has_nutrition = FALSE - -///damage override at the species level, called by /mob/living/proc/apply_damage -/datum/species/proc/apply_damage(damage = 0, damagetype = BRUTE, def_zone, blocked = 0, sharp = FALSE, edge = FALSE, updating_health = FALSE, penetration, mob/living/carbon/human/victim, mob/attacker) - var/datum/limb/organ = null - if(isorgan(def_zone)) //Got sent a limb datum, convert to a zone define - organ = def_zone - def_zone = organ.name - - if(!def_zone) - def_zone = ran_zone(def_zone) - if(!organ) - organ = victim.get_limb(check_zone(def_zone)) - if(!organ) - return FALSE - - if(isnum(blocked)) - damage -= clamp(damage * (blocked - penetration) * 0.01, 0, damage) - else - damage = victim.modify_by_armor(damage, blocked, penetration, def_zone) - - if(victim.protection_aura) - damage = round(damage * ((20 - victim.protection_aura) / 20)) - - if(!damage) - return 0 - - - switch(damagetype) - if(BRUTE) - victim.damageoverlaytemp = 20 - if(brute_mod) - damage *= brute_mod - var/old_status = organ.limb_status - if(organ.take_damage_limb(damage, 0, sharp, edge)) - victim.UpdateDamageIcon() - record_internal_injury(victim, attacker, old_status, organ.limb_status) - if(BURN) - victim.damageoverlaytemp = 20 - if(burn_mod) - damage *= burn_mod - if(organ.take_damage_limb(0, damage, sharp, edge)) - victim.UpdateDamageIcon() - return - switch(damage) - if(-INFINITY to 0) - return FALSE - if(25 to 50) - if(prob(20)) - victim.emote("pain") - if(50 to INFINITY) - if(prob(60)) - victim.emote("pain") - if(TOX) - victim.adjustToxLoss(damage) - if(OXY) - victim.adjustOxyLoss(damage) - if(CLONE) - victim.adjustCloneLoss(damage) - if(STAMINA) - if(species_flags & NO_STAMINA) - return - victim.adjustStaminaLoss(damage) - - // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life(). - SEND_SIGNAL(victim, COMSIG_HUMAN_DAMAGE_TAKEN, damage) - - if(updating_health) - victim.updatehealth() - return damage - -/datum/species/necoarc - name = "Neco Arc" - name_plural = "Neco Arc" - icobase = 'icons/mob/human_races/r_NecoArc.dmi' - default_language_holder = /datum/language_holder/sectoid - eyes = "blank_eyes" - speech_verb_override = "transmits" - count_human = TRUE - total_health = 80 - - species_flags = HAS_NO_HAIR|NO_BREATHE|NO_POISON|NO_PAIN|USES_ALIEN_WEAPONS|NO_DAMAGE_OVERLAY - - paincries = list("neuter" = 'sound/voice/necoarc/NecoVIBIVII!!.ogg') - death_sound = 'sound/voice/necoarc/Necojooooonoooooooo.ogg' - - blood_color = "#00FF00" - flesh_color = "#C0C0C0" - - reagent_tag = IS_SECTOID - - namepool = /datum/namepool/necoarc - special_death_message = "You have perished." diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm new file mode 100644 index 00000000000..52f09ed27e3 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -0,0 +1,368 @@ +/datum/species + /// Species name + var/name + var/name_plural + /// What kind of species it is considered + var/species_type = SPECIES_HUMAN + + /// Normal icon file + var/icobase = 'icons/mob/human_races/r_human.dmi' + /// Icon state for calculating brute damage icons + var/brute_damage_icon_state = "human_brute" + /// Icon state for calculating brute damage icons + var/burn_damage_icon_state = "human_burn" + /// Damage mask icon we want to use when drawing wounds + var/damage_mask_icon = 'icons/mob/dam_mask.dmi' + /// If set, draws this from icobase when mob is prone. + var/prone_icon + /// Icon for eyes + var/eyes = "eyes_s" + + /// For empty hand harm-intent attack + var/datum/unarmed_attack/unarmed + /// For empty hand harm-intent attack if the first fails. + var/datum/unarmed_attack/secondary_unarmed + var/datum/hud_data/hud + var/hud_type + var/slowdown = 0 + var/taste_sensitivity = TASTE_NORMAL + var/datum/unarmed_attack/unarmed_type = /datum/unarmed_attack + var/secondary_unarmed_type = /datum/unarmed_attack/bite + var/default_language_holder = /datum/language_holder + var/speech_verb_override + /// The names of secondary languages that are available to this species. + var/secondary_langs = list() + /// A list of sounds to potentially play when speaking. + var/list/speech_sounds + var/list/speech_chance + /// Does this count as a human? + var/count_human = FALSE + + /// Inventory slots the race can't equip stuff to. Robots cannot wear shoes and gloves, for example. + var/list/no_equip = list() + + // Some species-specific gibbing data. + var/gibbed_anim = "gibbed-h" + var/dusted_anim = "dust-h" + var/remains_type = /obj/effect/decal/cleanable/ash + var/death_sound + var/death_message = "seizes up and falls limp, their eyes dead and lifeless..." + + /// new maxHealth [/mob/living/carbon/human/var/maxHealth] of the human mob once species is applied + var/total_health = 100 + var/max_stamina = 50 + + /// Cold damage level 1 below this point. + var/cold_level_1 = BODYTEMP_COLD_DAMAGE_LIMIT_ONE + /// Cold damage level 2 below this point. + var/cold_level_2 = BODYTEMP_COLD_DAMAGE_LIMIT_TWO + /// Cold damage level 3 below this point. + var/cold_level_3 = BODYTEMP_COLD_DAMAGE_LIMIT_THREE + + /// Heat damage level 1 above this point. + var/heat_level_1 = BODYTEMP_HEAT_DAMAGE_LIMIT_ONE + /// Heat damage level 2 above this point. + var/heat_level_2 = BODYTEMP_HEAT_DAMAGE_LIMIT_TWO + /// Heat damage level 2 above this point. + var/heat_level_3 = BODYTEMP_HEAT_DAMAGE_LIMIT_THREE + + /// non-IS_SYNTHETIC species will try to stabilize at this temperature. (also affects temperature processing) + var/body_temperature = BODYTEMP_NORMAL + /// Used for metabolizing reagents. + var/reagent_tag + + /// Converts into see_in_dark on update_sight() + var/darksight = 2 + + /// Physical damage reduction/malus. + var/brute_mod = null + /// Burn damage reduction/malus. + var/burn_mod = null + + /// Whether this mob will tell when the user has logged out + var/is_sentient = TRUE + + /// Generic traits tied to having the species. + var/list/inherent_traits = list() + /// Various specific features. + var/species_flags = NONE + + var/list/preferences = list() + var/list/screams = list() + var/list/paincries = list() + var/list/goredcries = list() + var/list/gasps = list() + var/list/coughs = list() + var/list/burstscreams = list() + var/list/warcries = list() + var/list/laughs = list() + + /// Red. + var/blood_color = "#A10808" + /// Pink. + var/flesh_color = "#FFC896" + /// Used when setting species. + var/base_color + /// If the species only has one hair color + var/hair_color + + // Used in icon caching. + var/race_key = 0 + var/icon/icon_template + + /// inherent Species-specific verbs. + var/list/inherent_verbs + /// inherent species-specific actions + var/list/inherent_actions + var/list/has_organ = list( + ORGAN_SLOT_HEART = /datum/internal_organ/heart, + ORGAN_SLOT_LUNGS = /datum/internal_organ/lungs, + ORGAN_SLOT_LIVER = /datum/internal_organ/liver, + ORGAN_SLOT_STOMACH = /datum/internal_organ/stomach, + ORGAN_SLOT_KIDNEYS = /datum/internal_organ/kidneys, + ORGAN_SLOT_BRAIN = /datum/internal_organ/brain, + ORGAN_SLOT_APPENDIX = /datum/internal_organ/appendix, + ORGAN_SLOT_EYES = /datum/internal_organ/eyes + ) + var/lighting_alpha + var/see_in_dark + + var/datum/namepool/namepool = /datum/namepool + /// Special death message that gets overwritten if possible. + var/special_death_message = "You have perished." + /// Whether it is possible with this race roundstart + var/joinable_roundstart = FALSE + +/datum/species/New() + if(hud_type) + hud = new hud_type() + else + hud = new() + + if(unarmed_type) + unarmed = new unarmed_type() + if(secondary_unarmed_type) + secondary_unarmed = new secondary_unarmed_type() + if(species_flags & GREYSCALE_BLOOD) + brute_damage_icon_state = "grayscale" + +/// Handles creation of mob organs and limbs. +/datum/species/proc/create_organs(mob/living/carbon/human/organless_human) + + organless_human.limbs = list() + organless_human.internal_organs = list() + organless_human.internal_organs_by_name = list() + + //This is a basic humanoid limb setup. + var/datum/limb/chest/new_chest = new(null, organless_human) + organless_human.limbs += new_chest + var/datum/limb/groin/new_groin = new(new_chest, organless_human) + organless_human.limbs += new_groin + organless_human.limbs += new/datum/limb/head(new_chest, organless_human) + var/datum/limb/l_arm/new_l_arm = new(new_chest, organless_human) + organless_human.limbs += new_l_arm + var/datum/limb/r_arm/new_r_arm = new(new_chest, organless_human) + organless_human.limbs += new_r_arm + var/datum/limb/l_leg/new_l_leg = new(new_groin, organless_human) + organless_human.limbs += new_l_leg + var/datum/limb/r_leg/new_r_leg = new(new_groin, organless_human) + organless_human.limbs += new_r_leg + organless_human.limbs += new/datum/limb/hand/l_hand(new_l_arm, organless_human) + organless_human.limbs += new/datum/limb/hand/r_hand(new_r_arm, organless_human) + organless_human.limbs += new/datum/limb/foot/l_foot(new_l_leg, organless_human) + organless_human.limbs += new/datum/limb/foot/r_foot(new_r_leg, organless_human) + + for(var/datum/internal_organ/organ AS in has_organ) + var/datum/internal_organ/organ_type = has_organ[organ] + organless_human.internal_organs_by_name[organ] = new organ_type(organless_human) + + if(!(species_flags & ROBOTIC_LIMBS)) + return + for(var/datum/limb/robotic_limb AS in organless_human.limbs) + if(robotic_limb.limb_status & LIMB_DESTROYED) + continue + robotic_limb.add_limb_flags(LIMB_ROBOT) + +///damage override at the species level, called by /mob/living/proc/apply_damage +/datum/species/proc/apply_damage(damage = 0, damagetype = BRUTE, def_zone, blocked = 0, sharp = FALSE, edge = FALSE, updating_health = FALSE, penetration, mob/living/carbon/human/victim, mob/attacker) + var/datum/limb/organ = null + if(isorgan(def_zone)) //Got sent a limb datum, convert to a zone define + organ = def_zone + def_zone = organ.name + + if(!def_zone) + def_zone = ran_zone(def_zone) + if(!organ) + organ = victim.get_limb(check_zone(def_zone)) + if(!organ) + return FALSE + + if(isnum(blocked)) + damage -= clamp(damage * (blocked - penetration) * 0.01, 0, damage) + else + damage = victim.modify_by_armor(damage, blocked, penetration, def_zone) + + if(victim.protection_aura) + damage = round(damage * ((20 - victim.protection_aura) / 20)) + + if(!damage) + return FALSE + + switch(damagetype) + if(BRUTE) + victim.damageoverlaytemp = 20 + if(brute_mod) + damage *= brute_mod + var/old_status = organ.limb_status + if(organ.take_damage_limb(damage, 0, sharp, edge)) + victim.UpdateDamageIcon() + record_internal_injury(victim, attacker, old_status, organ.limb_status) + if(BURN) + victim.damageoverlaytemp = 20 + if(burn_mod) + damage *= burn_mod + if(organ.take_damage_limb(0, damage, sharp, edge)) + victim.UpdateDamageIcon() + return + switch(damage) + if(-INFINITY to 0) + return FALSE + if(25 to 50) + if(prob(20)) + victim.emote("pain") + if(50 to INFINITY) + if(prob(60)) + victim.emote("pain") + if(TOX) + victim.adjustToxLoss(damage) + if(OXY) + victim.adjustOxyLoss(damage) + if(CLONE) + victim.adjustCloneLoss(damage) + if(STAMINA) + if(species_flags & NO_STAMINA) + return + victim.adjustStaminaLoss(damage) + + // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life(). + SEND_SIGNAL(victim, COMSIG_HUMAN_DAMAGE_TAKEN, damage) + + if(updating_health) + victim.updatehealth() + return damage + +/// Handles how the species hugs another mobs. +/datum/species/proc/hug(mob/living/carbon/human/H, mob/living/target) + if(H.zone_selected == "head") + H.visible_message(span_notice("[H] pats [target] on the head."), \ + span_notice("You pat [target] on the head."), null, 4) + else if(H.zone_selected == "l_hand" && CONFIG_GET(flag/fun_allowed)) + H.visible_message(span_notice("[H] holds [target] 's left hand."), \ + span_notice("You hold [target]'s left hand."), null, 4) + else if (H.zone_selected == "r_hand" && CONFIG_GET(flag/fun_allowed)) + H.visible_message(span_notice("[H] holds [target] 's right hand."), \ + span_notice("You hold [target]'s right hand."), null, 4) + else + H.visible_message(span_notice("[H] hugs [target] to make [target.p_them()] feel better!"), \ + span_notice("You hug [target] to make [target.p_them()] feel better!"), null, 4) + +/// Handles setting of the random name. +/datum/species/proc/random_name(gender) + return GLOB.namepool[namepool].get_random_name(gender) + +/datum/species/proc/prefs_name(datum/preferences/prefs) + return prefs.real_name + +/// What will this species do on being gained by human +/datum/species/proc/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) + SHOULD_CALL_PARENT(TRUE) //remember to call base procs kids + for(var/slot_id in no_equip) + var/obj/item/thing = H.get_item_by_slot(slot_id) + if(thing && !is_type_in_list(src,thing.species_exception)) + H.dropItemToGround(thing) + for(var/newtrait in inherent_traits) + ADD_TRAIT(H, newtrait, SPECIES_TRAIT) + H.maxHealth += total_health - (old_species ? old_species.total_health : initial(H.maxHealth)) + +/// Special things to change after we're no longer that species +/datum/species/proc/post_species_loss(mob/living/carbon/human/H) + SHOULD_CALL_PARENT(TRUE) + for(var/oldtrait in inherent_traits) + REMOVE_TRAIT(H, oldtrait, SPECIES_TRAIT) + +/// Removes all species-specific verbs and actions +/datum/species/proc/remove_inherent_abilities(mob/living/carbon/human/H) + if(inherent_verbs) + remove_verb(H, inherent_verbs) + if(inherent_actions) + for(var/action_path in inherent_actions) + var/datum/action/old_species_action = H.actions_by_path[action_path] + qdel(old_species_action) + return + +/// Adds all species-specific verbs and actions +/datum/species/proc/add_inherent_abilities(mob/living/carbon/human/H) + if(inherent_verbs) + add_verb(H, inherent_verbs) + if(inherent_actions) + for(var/action_path in inherent_actions) + var/datum/action/new_species_action = new action_path(H) + new_species_action.give_action(H) + return + +/// Handles anything not already covered by basic species assignment. +/datum/species/proc/handle_post_spawn(mob/living/carbon/human/H) + add_inherent_abilities(H) + +/// Handles any species-specific death events. +/datum/species/proc/handle_death(mob/living/carbon/human/H) + return + +//TODO KILL ME +///Snowflake proc for monkeys so they can call attackpaw +/datum/species/proc/spec_unarmedattack(mob/living/carbon/human/user, atom/target) + return FALSE + +//Only used by horrors at the moment. Only triggers if the mob is alive and not dead. +/datum/species/proc/handle_unique_behavior(mob/living/carbon/human/H) + return + +/datum/species/proc/handle_fire(mob/living/carbon/human/H) + return + +/datum/species/proc/update_body(mob/living/carbon/human/H) + return + +/datum/species/proc/update_inv_head(mob/living/carbon/human/H) + return + +/datum/species/proc/update_inv_w_uniform(mob/living/carbon/human/H) + return + +/datum/species/proc/update_inv_wear_suit(mob/living/carbon/human/H) + return + +/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(CHECK_BITFIELD(species_flags, NO_CHEM_METABOLIZATION)) //explicit + H.reagents.del_reagent(chem.type) //for the time being + return TRUE + if(CHECK_BITFIELD(species_flags, NO_POISON) && istype(chem, /datum/reagent/toxin)) + H.reagents.remove_reagent(chem.type, chem.custom_metabolism * H.metabolism_efficiency) + return TRUE + if(CHECK_BITFIELD(species_flags, NO_OVERDOSE)) //no stacking + if(chem.overdose_threshold && chem.volume > chem.overdose_threshold) + H.reagents.remove_reagent(chem.type, chem.volume - chem.overdose_threshold) + return FALSE + +///Called when using the shredding behavior. +/datum/species/proc/can_shred(mob/living/carbon/human/H) + if(H.a_intent != INTENT_HARM) + return FALSE + + if(unarmed.is_usable(H)) + if(unarmed.shredding) + return TRUE + else if(secondary_unarmed.is_usable(H)) + if(secondary_unarmed.shredding) + return TRUE + return FALSE diff --git a/code/modules/mob/living/carbon/human/species/early_synthetic.dm b/code/modules/mob/living/carbon/human/species/early_synthetic.dm new file mode 100644 index 00000000000..ae3f7adba84 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/early_synthetic.dm @@ -0,0 +1,63 @@ +//It really should be just a subtype of synthetic +/datum/species/early_synthetic // Worse at medical, better at engineering. Tougher in general than later synthetics. + name = "Early Synthetic" + name_plural = "Early Synthetics" + icobase = 'icons/mob/human_races/r_synthetic.dmi' + hud_type = /datum/hud_data/robotic + default_language_holder = /datum/language_holder/synthetic + unarmed_type = /datum/unarmed_attack/punch + slowdown = 1.15 //Slower than Late Synths. + total_health = 200 //Tough boys, very tough boys. + brute_mod = 0.6 + burn_mod = 0.6 + + cold_level_1 = -1 + cold_level_2 = -1 + cold_level_3 = -1 + + heat_level_1 = 500 + heat_level_2 = 1000 + heat_level_3 = 2000 + + body_temperature = 350 + + species_flags = NO_BREATHE|NO_SCAN|NO_BLOOD|NO_POISON|NO_PAIN|IS_SYNTHETIC|NO_CHEM_METABOLIZATION|NO_STAMINA|DETACHABLE_HEAD|HAS_UNDERWEAR|ROBOTIC_LIMBS|GREYSCALE_BLOOD + + blood_color = "#EEEEEE" + hair_color = "#000000" + has_organ = list() + + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + see_in_dark = 8 + + screams = list(MALE = "male_scream", FEMALE = "female_scream") + paincries = list(MALE = "male_pain", FEMALE = "female_pain") + goredcries = list(MALE = "male_gored", FEMALE = "female_gored") + warcries = list(MALE = "male_warcry", FEMALE = "female_warcry") + laughs = list(MALE = "male_laugh", FEMALE = "female_laugh") + special_death_message = "You have been shut down.
But it is not the end of you yet... if you still have your body, wait until somebody can resurrect you..." + +/datum/species/early_synthetic/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) + . = ..() + var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED_SYNTH] + AH.add_hud_to(H) + +/datum/species/early_synthetic/post_species_loss(mob/living/carbon/human/H) + . = ..() + var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED_SYNTH] + AH.remove_hud_from(H) + +/mob/living/carbon/human/species/early_synthetic/binarycheck(mob/H) + return TRUE + +/datum/species/early_synthetic/prefs_name(datum/preferences/prefs) + . = prefs.synthetic_name + if(!. || . == "Undefined") //In case they don't have a name set. + switch(prefs.gender) + if(MALE) + . = "David" + if(FEMALE) + . = "Anna" + else + . = "Jeri" + to_chat(prefs.parent, span_warning("You forgot to set your synthetic name in your preferences. Please do so next time.")) diff --git a/code/modules/mob/living/carbon/human/species/hud_data.dm b/code/modules/mob/living/carbon/human/species/hud_data.dm new file mode 100644 index 00000000000..3eaa20968d8 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/hud_data.dm @@ -0,0 +1,65 @@ +/datum/hud_data + var/icon // If set, overrides ui_style. + var/has_a_intent = TRUE // Set to draw intent box. + var/has_m_intent = TRUE // Set to draw move intent box. + var/has_warnings = TRUE // Set to draw environment warnings. + var/has_pressure = TRUE // Draw the pressure indicator. + var/has_nutrition = TRUE // Draw the nutrition indicator. + var/has_bodytemp = TRUE // Draw the bodytemp indicator. + var/has_hands = TRUE // Set to draw shand. + var/has_drop = TRUE // Set to draw drop button. + var/has_throw = TRUE // Set to draw throw button. + var/has_resist = TRUE // Set to draw resist button. + var/list/equip_slots = list() // Checked by mob_can_equip(). + + // Contains information on the position and tag for all inventory slots + // to be drawn for the mob. This is fairly delicate, try to avoid messing with it + // unless you know exactly what it does. + var/list/gear = list( + "i_clothing" = list("loc" = ui_iclothing, "slot" = SLOT_W_UNIFORM, "state" = "uniform", "toggle" = TRUE), + "o_clothing" = list("loc" = ui_oclothing, "slot" = SLOT_WEAR_SUIT, "state" = "suit", "toggle" = TRUE), + "mask" = list("loc" = ui_mask, "slot" = SLOT_WEAR_MASK, "state" = "mask", "toggle" = TRUE), + "gloves" = list("loc" = ui_gloves, "slot" = SLOT_GLOVES, "state" = "gloves", "toggle" = TRUE), + "eyes" = list("loc" = ui_glasses, "slot" = SLOT_GLASSES, "state" = "glasses","toggle" = TRUE), + "wear_ear" = list("loc" = ui_wear_ear, "slot" = SLOT_EARS, "state" = "ears", "toggle" = TRUE), + "head" = list("loc" = ui_head, "slot" = SLOT_HEAD, "state" = "head", "toggle" = TRUE), + "shoes" = list("loc" = ui_shoes, "slot" = SLOT_SHOES, "state" = "shoes", "toggle" = TRUE), + "suit storage" = list("loc" = ui_sstore1, "slot" = SLOT_S_STORE, "state" = "suit_storage"), + "back" = list("loc" = ui_back, "slot" = SLOT_BACK, "state" = "back"), + "id" = list("loc" = ui_id, "slot" = SLOT_WEAR_ID, "state" = "id"), + "storage1" = list("loc" = ui_storage1, "slot" = SLOT_L_STORE, "state" = "pocket"), + "storage2" = list("loc" = ui_storage2, "slot" = SLOT_R_STORE, "state" = "pocket"), + "belt" = list("loc" = ui_belt, "slot" = SLOT_BELT, "state" = "belt") + ) + +/datum/hud_data/New() + . = ..() + for(var/slot in gear) + equip_slots |= gear[slot]["slot"] + + if(has_hands) + equip_slots |= SLOT_L_HAND + equip_slots |= SLOT_R_HAND + equip_slots |= SLOT_HANDCUFFED + if(SLOT_HEAD in equip_slots) + equip_slots |= SLOT_IN_HEAD + if(SLOT_BACK in equip_slots) + equip_slots |= SLOT_IN_BACKPACK + equip_slots |= SLOT_IN_B_HOLSTER + if(SLOT_BELT in equip_slots) + equip_slots |= SLOT_IN_HOLSTER + equip_slots |= SLOT_IN_BELT + if(SLOT_WEAR_SUIT in equip_slots) + equip_slots |= SLOT_IN_S_HOLSTER + equip_slots |= SLOT_IN_SUIT + if(SLOT_SHOES in equip_slots) + equip_slots |= SLOT_IN_BOOT + if(SLOT_W_UNIFORM in equip_slots) + equip_slots |= SLOT_IN_STORAGE + equip_slots |= SLOT_IN_L_POUCH + equip_slots |= SLOT_IN_R_POUCH + equip_slots |= SLOT_ACCESSORY + equip_slots |= SLOT_IN_ACCESSORY + +/datum/hud_data/robotic + has_nutrition = FALSE diff --git a/code/modules/mob/living/carbon/human/species/human.dm b/code/modules/mob/living/carbon/human/species/human.dm new file mode 100644 index 00000000000..0a4927524e2 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/human.dm @@ -0,0 +1,25 @@ +/datum/species/human + name = "Human" + name_plural = "Humans" + unarmed_type = /datum/unarmed_attack/punch + species_flags = HAS_SKIN_TONE|HAS_LIPS|HAS_UNDERWEAR + count_human = TRUE + + screams = list(MALE = "male_scream", FEMALE = "female_scream") + paincries = list(MALE = "male_pain", FEMALE = "female_pain") + goredcries = list(MALE = "male_gored", FEMALE = "female_gored") + gasps = list(MALE = "male_gasp", FEMALE = "female_gasp") + coughs = list(MALE = "male_cough", FEMALE = "female_cough") + burstscreams = list(MALE = "male_preburst", FEMALE = "female_preburst") + warcries = list(MALE = "male_warcry", FEMALE = "female_warcry") + laughs = list(MALE = "male_laugh", FEMALE = "female_laugh") + special_death_message = "You have perished.
But it is not the end of you yet... if you still have your body with your head still attached, wait until somebody can resurrect you..." + joinable_roundstart = TRUE + +/datum/species/human/prefs_name(datum/preferences/prefs) + . = ..() + if(!CONFIG_GET(flag/humans_need_surnames)) + return + var/firstspace = findtext(., " ") + if(!firstspace || firstspace == length(.)) + . += " " + pick(SSstrings.get_list_from_file("names/last_name")) diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm new file mode 100644 index 00000000000..edd1a509461 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -0,0 +1,73 @@ +//todo: wound overlays are strange for monkeys and should likely use icon adding instead +//im not about to cram in that refactor with a carbon -> species refactor though +/datum/species/monkey + name = "Monkey" + name_plural = "Monkeys" + icobase = 'icons/mob/human_races/r_monkey.dmi' + species_flags = HAS_NO_HAIR|NO_STAMINA|DETACHABLE_HEAD + inherent_traits = list(TRAIT_CAN_VENTCRAWL) + reagent_tag = IS_MONKEY + eyes = "blank_eyes" + speech_verb_override = "chimpers" + unarmed_type = /datum/unarmed_attack/bite/strong + secondary_unarmed_type = /datum/unarmed_attack/punch/strong + joinable_roundstart = FALSE + death_message = "lets out a faint chimper as it collapses and stops moving..." + dusted_anim = "dust-m" + gibbed_anim = "gibbed-m" + is_sentient = FALSE + +/datum/species/monkey/handle_unique_behavior(mob/living/carbon/human/H) + if(H.client || H.stat != CONSCIOUS) + return + if(prob(33) && H.canmove && !H.buckled && isturf(H.loc) && !H.pulledby) //won't move if being pulled + step(H, pick(GLOB.cardinals)) + + if(prob(1)) + H.emote(pick("scratch","jump","roll","tail")) + +/datum/species/monkey/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) + . = ..() + H.allow_pass_flags |= PASS_LOW_STRUCTURE + +/datum/species/monkey/spec_unarmedattack(mob/living/carbon/human/user, atom/target) + if(!iscarbon(target)) + return FALSE + var/mob/living/carbon/victim = target + if(prob(25)) + victim.visible_message(span_danger("[user]'s bite misses [victim]!"), + span_danger("You avoid [user]'s bite!"), span_hear("You hear jaws snapping shut!")) + to_chat(user, span_danger("Your bite misses [victim]!")) + return TRUE + victim.apply_damage(rand(10, 20), BRUTE, "chest", updating_health = TRUE) + victim.visible_message(span_danger("[name] bites [victim]!"), + span_userdanger("[name] bites you!"), span_hear("You hear a chomp!")) + to_chat(user, span_danger("You bite [victim]!")) + target.attack_hand(user) + return TRUE + +/datum/species/monkey/random_name(gender,unique,lastname) + return "[lowertext(name)] ([rand(1,999)])" + +/datum/species/monkey/tajara + name = "Farwa" + icobase = 'icons/mob/human_races/r_farwa.dmi' + speech_verb_override = "mews" + +/datum/species/monkey/skrell + name = "Naera" + icobase = 'icons/mob/human_races/r_naera.dmi' + speech_verb_override = "squiks" + +/datum/species/monkey/unathi + name = "Stok" + icobase = 'icons/mob/human_races/r_stok.dmi' + speech_verb_override = "hisses" + +/datum/species/monkey/yiren + name = "Yiren" + icobase = 'icons/mob/human_races/r_yiren.dmi' + speech_verb_override = "grumbles" + cold_level_1 = ICE_COLONY_TEMPERATURE - 20 + cold_level_2 = ICE_COLONY_TEMPERATURE - 40 + cold_level_3 = ICE_COLONY_TEMPERATURE - 80 diff --git a/code/modules/mob/living/carbon/human/species/moth.dm b/code/modules/mob/living/carbon/human/species/moth.dm new file mode 100644 index 00000000000..b19076f990f --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/moth.dm @@ -0,0 +1,63 @@ +/datum/species/moth + name = "Moth" + name_plural = "Moth" + icobase = 'icons/mob/human_races/r_moth.dmi' + default_language_holder = /datum/language_holder/moth + eyes = "blank_eyes" + speech_verb_override = "flutters" + count_human = TRUE + + species_flags = HAS_LIPS|HAS_NO_HAIR + preferences = list("moth_wings" = "Wings") + + screams = list(NEUTER = 'sound/voice/moth_scream.ogg') + paincries = list(NEUTER = 'sound/voice/human/male/pain_3.ogg') + goredcries = list(NEUTER = 'sound/voice/moth_scream.ogg') + burstscreams = list(NEUTER = 'sound/voice/moth_scream.ogg') + warcries = list(NEUTER = 'sound/voice/moth_scream.ogg') + laughs = list(NEUTER = 'sound/voice/silly_laugh.ogg') + + flesh_color = "#E5CD99" + + reagent_tag = IS_MOTH + + namepool = /datum/namepool/moth + +/datum/species/moth/handle_fire(mob/living/carbon/human/H) + if(H.moth_wings == "Burnt Off") + return + if(H.bodytemperature < 400 && H.fire_stacks < 0) + return + to_chat(H, span_danger("Your precious wings burn to a crisp!")) + H.moth_wings = "Burnt Off" + H.update_body() + +/datum/species/moth/proc/update_moth_wings(mob/living/carbon/human/H) + H.remove_overlay(MOTH_WINGS_LAYER) + H.remove_underlay(MOTH_WINGS_BEHIND_LAYER) + + var/datum/sprite_accessory/moth_wings/wings = GLOB.moth_wings_list[H.moth_wings] + + if(!wings) + return + H.overlays_standing[MOTH_WINGS_LAYER] = image(wings.icon, icon_state = "m_moth_wings_[wings.icon_state]_FRONT") + H.underlays_standing[MOTH_WINGS_BEHIND_LAYER] = image(wings.icon, icon_state = "m_moth_wings_[wings.icon_state]_BEHIND") + H.apply_overlay(MOTH_WINGS_LAYER) + H.apply_underlay(MOTH_WINGS_BEHIND_LAYER) + +/datum/species/moth/update_body(mob/living/carbon/human/H) + update_moth_wings(H) + +/datum/species/moth/update_inv_head(mob/living/carbon/human/H) + update_moth_wings(H) + +/datum/species/moth/update_inv_w_uniform(mob/living/carbon/human/H) + update_moth_wings(H) + +/datum/species/moth/update_inv_wear_suit(mob/living/carbon/human/H) + update_moth_wings(H) + +/datum/species/moth/post_species_loss(mob/living/carbon/human/H) + . = ..() + H.remove_overlay(MOTH_WINGS_LAYER) + H.remove_underlay(MOTH_WINGS_BEHIND_LAYER) diff --git a/code/modules/mob/living/carbon/human/species/necoarc.dm b/code/modules/mob/living/carbon/human/species/necoarc.dm new file mode 100644 index 00000000000..9d17a5792d3 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/necoarc.dm @@ -0,0 +1,22 @@ +/datum/species/necoarc + name = "Neco Arc" + name_plural = "Neco Arc" + icobase = 'icons/mob/human_races/r_NecoArc.dmi' + default_language_holder = /datum/language_holder/sectoid + eyes = "blank_eyes" + speech_verb_override = "transmits" + count_human = TRUE + total_health = 80 + + species_flags = HAS_NO_HAIR|NO_BREATHE|NO_POISON|NO_PAIN|USES_ALIEN_WEAPONS|NO_DAMAGE_OVERLAY + + paincries = list("neuter" = 'sound/voice/necoarc/NecoVIBIVII!!.ogg') + death_sound = 'sound/voice/necoarc/Necojooooonoooooooo.ogg' + + blood_color = "#00FF00" + flesh_color = "#C0C0C0" + + reagent_tag = IS_SECTOID + + namepool = /datum/namepool/necoarc + special_death_message = "You have perished." diff --git a/code/modules/mob/living/carbon/human/species/robot.dm b/code/modules/mob/living/carbon/human/species/robot.dm new file mode 100644 index 00000000000..fd304392c2d --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/robot.dm @@ -0,0 +1,112 @@ +/datum/species/robot + name = "Combat Robot" + name_plural = "Combat Robots" + species_type = SPECIES_COMBAT_ROBOT + icobase = 'icons/mob/human_races/r_robot.dmi' + damage_mask_icon = 'icons/mob/dam_mask_robot.dmi' + brute_damage_icon_state = "robot_brute" + burn_damage_icon_state = "robot_burn" + eyes = "blank_eyes" + hud_type = /datum/hud_data/robotic + default_language_holder = /datum/language_holder/robot + namepool = /datum/namepool/robotic + + unarmed_type = /datum/unarmed_attack/punch/strong + total_health = 100 + slowdown = SHOES_SLOWDOWN //because they don't wear boots. + + cold_level_1 = -1 + cold_level_2 = -1 + cold_level_3 = -1 + + heat_level_1 = 500 + heat_level_2 = 1000 + heat_level_3 = 2000 + + body_temperature = 350 + + inherent_traits = list(TRAIT_NON_FLAMMABLE, TRAIT_IMMEDIATE_DEFIB) + species_flags = NO_BREATHE|NO_BLOOD|NO_POISON|NO_PAIN|NO_CHEM_METABOLIZATION|NO_STAMINA|DETACHABLE_HEAD|HAS_NO_HAIR|ROBOTIC_LIMBS|IS_INSULATED + + no_equip = list( + SLOT_W_UNIFORM, + SLOT_HEAD, + SLOT_WEAR_MASK, + SLOT_WEAR_SUIT, + SLOT_SHOES, + SLOT_GLOVES, + SLOT_GLASSES, + ) + blood_color = "#2d2055" //"oil" color + hair_color = "#00000000" + has_organ = list() + + + screams = list(MALE = "robot_scream", FEMALE = "robot_scream", PLURAL = "robot_scream", NEUTER = "robot_scream") + paincries = list(MALE = "robot_pain", FEMALE = "robot_pain", PLURAL = "robot_pain", NEUTER = "robot_pain") + goredcries = list(MALE = "robot_scream", FEMALE = "robot_scream", PLURAL = "robot_scream", NEUTER = "robot_scream") + warcries = list(MALE = "robot_warcry", FEMALE = "robot_warcry", PLURAL = "robot_warcry", NEUTER = "robot_warcry") + laughs = list(MALE = "robot_male_laugh", FEMALE = "robot_female_laugh", PLURAL = "robot_male_laugh", NEUTER = "robot_female_laugh") + death_message = "shudders violently whilst spitting out error text before collapsing, their visual sensor darkening..." + special_death_message = "You have been shut down.
But it is not the end of you yet... if you still have your body, wait until somebody can resurrect you..." + joinable_roundstart = FALSE + + inherent_actions = list(/datum/action/repair_self) + +/datum/species/robot/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) + . = ..() + H.speech_span = SPAN_ROBOT + H.health_threshold_crit = -100 + +/datum/species/robot/post_species_loss(mob/living/carbon/human/H) + . = ..() + H.speech_span = initial(H.speech_span) + H.health_threshold_crit = -50 + +/datum/species/robot/handle_unique_behavior(mob/living/carbon/human/H) + if(H.health <= 0 && H.health > -50) + H.clear_fullscreen("robotlow") + H.overlay_fullscreen("robothalf", /atom/movable/screen/fullscreen/machine/robothalf) + else if(H.health <= -50) + H.clear_fullscreen("robothalf") + H.overlay_fullscreen("robotlow", /atom/movable/screen/fullscreen/machine/robotlow) + else + H.clear_fullscreen("robothalf") + H.clear_fullscreen("robotlow") + if(H.health > -25) //Staggerslowed if below crit threshold. + return + H.Stagger(2 SECONDS) + H.adjust_slowdown(1) + +/mob/living/carbon/human/species/robot/binarycheck(mob/H) + return TRUE + +/datum/species/robot/prefs_name(datum/preferences/prefs) + . = prefs.squad_robot_name + if(!. || . == "Undefined") //In case they don't have a name set. + . = GLOB.namepool[namepool].get_random_name() + to_chat(prefs.parent, span_warning("You forgot to set your robot in your preferences. Please do so next time.")) + +/datum/species/robot/alpharii + name = "Hammerhead Combat Robot" + name_plural = "Hammerhead Combat Robots" + icobase = 'icons/mob/human_races/r_robot_alpharii.dmi' + joinable_roundstart = FALSE + +/datum/species/robot/charlit + name = "Chilvaris Combat Robot" + name_plural = "Chilvaris Combat Robots" + icobase = 'icons/mob/human_races/r_robot_charlit.dmi' + joinable_roundstart = FALSE + +/datum/species/robot/deltad + name = "Ratcher Combat Robot" + name_plural = "Ratcher Combat Robots" + icobase = 'icons/mob/human_races/r_robot_deltad.dmi' + joinable_roundstart = FALSE + +/datum/species/robot/bravada + name = "Sterling Combat Robot" + name_plural = "Sterling Combat Robots" + icobase = 'icons/mob/human_races/r_robot_bravada.dmi' + joinable_roundstart = FALSE diff --git a/code/modules/mob/living/carbon/human/species/sectoid.dm b/code/modules/mob/living/carbon/human/species/sectoid.dm new file mode 100644 index 00000000000..93d51a370a6 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/sectoid.dm @@ -0,0 +1,22 @@ +/datum/species/sectoid + name = "Sectoid" + name_plural = "Sectoids" + icobase = 'icons/mob/human_races/r_sectoid.dmi' + default_language_holder = /datum/language_holder/sectoid + eyes = "blank_eyes" + speech_verb_override = "transmits" + count_human = TRUE + total_health = 80 + + species_flags = HAS_NO_HAIR|NO_BREATHE|NO_POISON|NO_PAIN|USES_ALIEN_WEAPONS|NO_DAMAGE_OVERLAY + + paincries = list("neuter" = 'sound/voice/sectoid_death.ogg') + death_sound = 'sound/voice/sectoid_death.ogg' + + blood_color = "#00FF00" + flesh_color = "#C0C0C0" + + reagent_tag = IS_SECTOID + + namepool = /datum/namepool/sectoid + special_death_message = "You have perished." diff --git a/code/modules/mob/living/carbon/human/species/skeleton.dm b/code/modules/mob/living/carbon/human/species/skeleton.dm new file mode 100644 index 00000000000..41e8bb88934 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/skeleton.dm @@ -0,0 +1,18 @@ +/datum/species/skeleton + name = "Skeleton" + name_plural = "skeletons" + icobase = 'icons/mob/human_races/r_skeleton.dmi' + unarmed_type = /datum/unarmed_attack/punch + speech_verb_override = "rattles" + count_human = TRUE + + species_flags = NO_BREATHE|NO_SCAN|NO_BLOOD|NO_POISON|NO_CHEM_METABOLIZATION|DETACHABLE_HEAD // Where we're going, we don't NEED underwear. + + screams = list("neuter" = 'sound/voice/skeleton_scream.ogg') // RATTLE ME BONES + paincries = list("neuter" = 'sound/voice/skeleton_scream.ogg') + goredcries = list("neuter" = 'sound/voice/skeleton_scream.ogg') + burstscreams = list("neuter" = 'sound/voice/moth_scream.ogg') + death_message = "collapses in a pile of bones, with a final rattle..." + death_sound = list("neuter" = 'sound/voice/skeleton_scream.ogg') + warcries = list("neuter" = 'sound/voice/skeleton_warcry.ogg') // AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + namepool = /datum/namepool/skeleton diff --git a/code/modules/mob/living/carbon/human/species/synthetic.dm b/code/modules/mob/living/carbon/human/species/synthetic.dm new file mode 100644 index 00000000000..159d42dc09e --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/synthetic.dm @@ -0,0 +1,63 @@ +/datum/species/synthetic + name = "Synthetic" + name_plural = "Synthetics" + + hud_type = /datum/hud_data/robotic + default_language_holder = /datum/language_holder/synthetic + unarmed_type = /datum/unarmed_attack/punch + + total_health = 125 //more health than regular humans + + brute_mod = 0.70 + burn_mod = 0.70 //Synthetics should not be instantly melted by acid compared to humans - This is a test to hopefully fix very glaring issues involving synthetics taking 2.6 trillion damage when so much as touching acid + + cold_level_1 = -1 + cold_level_2 = -1 + cold_level_3 = -1 + + heat_level_1 = 500 + heat_level_2 = 1000 + heat_level_3 = 2000 + + body_temperature = 350 + + species_flags = NO_BREATHE|NO_SCAN|NO_BLOOD|NO_POISON|NO_PAIN|IS_SYNTHETIC|NO_CHEM_METABOLIZATION|NO_STAMINA|DETACHABLE_HEAD|HAS_LIPS|HAS_UNDERWEAR|HAS_SKIN_COLOR|ROBOTIC_LIMBS|GREYSCALE_BLOOD + + blood_color = "#EEEEEE" + + has_organ = list() + + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + see_in_dark = 8 + + screams = list(MALE = "male_scream", FEMALE = "female_scream") + paincries = list(MALE = "male_pain", FEMALE = "female_pain") + goredcries = list(MALE = "male_gored", FEMALE = "female_gored") + warcries = list(MALE = "male_warcry", FEMALE = "female_warcry") + laughs = list(MALE = "male_laugh", FEMALE = "female_laugh") + special_death_message = "You have been shut down.
But it is not the end of you yet... if you still have your body, wait until somebody can resurrect you..." + +/datum/species/synthetic/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) + . = ..() + var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED_SYNTH] + AH.add_hud_to(H) + +/datum/species/synthetic/prefs_name(datum/preferences/prefs) + . = prefs.synthetic_name + if(!. || . == "Undefined") //In case they don't have a name set. + switch(prefs.gender) + if(MALE) + . = "David" + if(FEMALE) + . = "Anna" + else + . = "Jeri" + to_chat(prefs.parent, span_warning("You forgot to set your synthetic name in your preferences. Please do so next time.")) + +/datum/species/synthetic/post_species_loss(mob/living/carbon/human/H) + . = ..() + var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED_SYNTH] + AH.remove_hud_from(H) + +/mob/living/carbon/human/species/synthetic/binarycheck(mob/H) + return TRUE diff --git a/code/modules/mob/living/carbon/human/species/unarmed_attack.dm b/code/modules/mob/living/carbon/human/species/unarmed_attack.dm new file mode 100644 index 00000000000..cddce0ffe35 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/unarmed_attack.dm @@ -0,0 +1,62 @@ +//Species unarmed attacks +/datum/unarmed_attack + var/attack_verb = list("attack") // Empty hand hurt intent verb. + var/damage = 0 // Extra empty hand attack damage. + var/attack_sound = "punch" + var/miss_sound = 'sound/weapons/punchmiss.ogg' + var/shredding = 0 // Calls the old attack_alien() behavior on objects/mobs when on harm intent. + var/sharp = 0 + var/edge = 0 + +/datum/unarmed_attack/proc/is_usable(mob/living/carbon/human/user) + if(user.restrained()) + return FALSE + + // Check if they have a functioning hand. + var/datum/limb/E = user.get_limb("l_hand") + if(E?.is_usable()) + return TRUE + + E = user.get_limb("r_hand") + if(E?.is_usable()) + return TRUE + return FALSE + +/datum/unarmed_attack/bite + attack_verb = list("bite") // 'x has biteed y', needs work. + attack_sound = 'sound/weapons/bite.ogg' + shredding = 0 + damage = 5 + sharp = 1 + edge = 1 + +/datum/unarmed_attack/bite/is_usable(mob/living/carbon/human/user) + if(user.wear_mask && istype(user.wear_mask, /obj/item/clothing/mask/muzzle)) + return FALSE + return TRUE + +/datum/unarmed_attack/punch + attack_verb = list("punch") + damage = 3 + +/datum/unarmed_attack/punch/strong + attack_verb = list("punch","bust","jab") + damage = 10 + +/datum/unarmed_attack/claws + attack_verb = list("scratch", "claw") + attack_sound = 'sound/weapons/slice.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + damage = 5 + sharp = 1 + edge = 1 + +/datum/unarmed_attack/claws/strong + attack_verb = list("slash") + damage = 10 + shredding = 1 + +/datum/unarmed_attack/bite/strong + attack_verb = list("maul") + damage = 15 + shredding = 1 diff --git a/code/modules/mob/living/carbon/human/species/vatborn.dm b/code/modules/mob/living/carbon/human/species/vatborn.dm new file mode 100644 index 00000000000..f2fad9772c2 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/vatborn.dm @@ -0,0 +1,8 @@ +/datum/species/human/vatborn + name = "Vatborn" + name_plural = "Vatborns" + icobase = 'icons/mob/human_races/r_vatborn.dmi' + namepool = /datum/namepool/vatborn + +/datum/species/human/vatborn/prefs_name(datum/preferences/prefs) + return prefs.real_name diff --git a/code/modules/mob/living/carbon/human/species/vatgrown.dm b/code/modules/mob/living/carbon/human/species/vatgrown.dm new file mode 100644 index 00000000000..a1b0f36c80d --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/vatgrown.dm @@ -0,0 +1,43 @@ +/datum/species/human/vatgrown + name = "Vat-Grown Human" + name_plural = "Vat-Grown Humans" + icobase = 'icons/mob/human_races/r_vatgrown.dmi' + brute_mod = 1.05 + burn_mod = 1.05 + slowdown = 0.05 + joinable_roundstart = FALSE + +/datum/species/human/vatgrown/random_name(gender) + return "CS-[gender == FEMALE ? "F": "M"]-[rand(111,999)]" + +/datum/species/human/vatgrown/prefs_name(datum/preferences/prefs) + return prefs.real_name + +/datum/species/human/vatgrown/handle_post_spawn(mob/living/carbon/human/H) + . = ..() + H.h_style = "Bald" + H.set_skills(getSkillsType(/datum/skills/vatgrown)) + +/datum/species/human/vatgrown/early + name = "Early Vat-Grown Human" + name_plural = "Early Vat-Grown Humans" + brute_mod = 1.3 + burn_mod = 1.3 + slowdown = 0.3 + + var/timerid + +/datum/species/human/vatgrown/early/handle_post_spawn(mob/living/carbon/human/H) + . = ..() + H.set_skills(getSkillsType(/datum/skills/vatgrown/early)) + timerid = addtimer(CALLBACK(src, PROC_REF(handle_age), H), 15 MINUTES, TIMER_STOPPABLE) + +/datum/species/human/vatgrown/early/post_species_loss(mob/living/carbon/human/H) + . = ..() + // Ensure we don't update the species again + if(timerid) + deltimer(timerid) + timerid = null + +/datum/species/human/vatgrown/early/proc/handle_age(mob/living/carbon/human/H) + H.set_species("Vat-Grown Human") diff --git a/code/modules/mob/living/carbon/human/species/yautja.dm b/code/modules/mob/living/carbon/human/species/yautja.dm new file mode 100644 index 00000000000..349e42234ca --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/yautja.dm @@ -0,0 +1,177 @@ +/datum/species/yautja + name = "Yautja" + name_plural = "Yautja" + brute_mod = 0.28 //Beefy! + burn_mod = 0.45 + reagent_tag = IS_YAUTJA + species_flags = HAS_SKIN_COLOR|NO_POISON|NO_PAIN|USES_ALIEN_WEAPONS|PARALYSE_RESISTANT + inherent_traits = list( + TRAIT_YAUTJA_TECH, + TRAIT_SUPER_STRONG, + TRAIT_FOREIGN_BIO, + ) + inherent_actions = list( + /datum/action/predator_action/mark_for_hunt, + /datum/action/predator_action/mark_panel, + ) + + screams = list(MALE = "pred_scream", FEMALE = "pred_scream") + paincries = list(MALE = "pred_pain", FEMALE = "pred_pain") + goredcries = list(MALE = "pred_pain", FEMALE = "pred_pain") + burstscreams = list(MALE = "pred_preburst", FEMALE = "pred_preburst") + warcries = list(MALE = "pred_warcry", FEMALE = "pred_warcry") + laughs = list(MALE = "pred_laugh", FEMALE = "pred_laugh") + + unarmed_type = /datum/unarmed_attack/punch/strong + secondary_unarmed_type = /datum/unarmed_attack/bite/strong + max_stamina = 250 + blood_color = "#20d450" + flesh_color = "#907E4A" + speech_sounds = list('sound/voice/predator/click1.ogg', 'sound/voice/predator/click2.ogg') + speech_chance = 100 + death_message = "clicks in agony and falls still, motionless and completely lifeless..." + + brute_damage_icon_state = "pred_brute" + burn_damage_icon_state = "pred_burn" + + darksight = 5 + slowdown = -0.5 + total_health = 175 //more health than regular humans + + default_language_holder = /datum/language_holder/yautja + + heat_level_1 = 500 + heat_level_2 = 700 + heat_level_3 = 1000 + + inherent_verbs = list( + /mob/living/carbon/human/proc/butcher, + ) + + icobase = 'icons/mob/hunter/r_predator.dmi' + +/datum/species/yautja/handle_death(mob/living/carbon/human/H, gibbed) + if(gibbed) + GLOB.yautja_mob_list -= H + + for(var/mob/living/carbon/M in H.hunter_data.dishonored_targets) + M.hunter_data.dishonored_set = null + H.hunter_data.dishonored_targets -= M + for(var/mob/living/carbon/M in H.hunter_data.honored_targets) + M.hunter_data.honored_set = null + H.hunter_data.honored_targets -= M + for(var/mob/living/carbon/M in H.hunter_data.gear_targets) + M.hunter_data.gear_set = null + H.hunter_data.gear_targets -= M + + if(H.hunter_data.prey) + var/mob/living/carbon/M = H.hunter_data.prey + H.hunter_data.prey = null + M.hunter_data.hunter = null + M.hud_set_hunter() + + set_predator_status(H, gibbed ? "Gibbed" : "Dead") + + // Notify all yautja so they start the gear recovery + message_all_yautja("[H.real_name] has died at \the [get_area_name(H)].") + + if(H.hunter_data.thrall) + var/mob/living/carbon/T = H.hunter_data.thrall + message_all_yautja("[H.real_name]'s Thrall, [T.real_name] is now masterless.") + H.message_thrall("Your master has fallen!") + H.hunter_data.thrall = null + +/datum/species/yautja/proc/set_predator_status(mob/living/carbon/human/H, status = "Alive") + if(!H.key) + return + var/datum/game_mode/GM + if(SSticker?.mode) + GM = SSticker.mode + if(H.key in GM.predators) + GM.predators[lowertext(H.key)]["Status"] = status + else + GM.predators[lowertext(H.key)] = list("Name" = H.real_name, "Status" = status) + +/datum/species/yautja/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) + . = ..() + var/datum/atom_hud/A = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + A.add_to_hud(H) + + for(var/datum/limb/limb in H.limbs) + switch(limb.name) + if("groin","chest") + limb.min_broken_damage = 120 + limb.max_damage = 350 + if("head") + limb.min_broken_damage = 100 + limb.max_damage = 350 + if("l_hand","r_hand","r_foot","l_foot") + limb.min_broken_damage = 85 + limb.max_damage = 180 + if("r_leg","r_arm","l_leg","l_arm") + limb.min_broken_damage = 100 + limb.max_damage = 225 + + set_predator_status(H, "Alive") + +/datum/species/yautja/post_species_loss(mob/living/carbon/human/H) + . = ..() + var/datum/atom_hud/A = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + A.remove_hud_from(H) + remove_inherent_abilities(H) + H.blood_type = pick("A+","A-","B+","B-","O-","O+","AB+","AB-") + H.h_style = "Bald" + GLOB.yautja_mob_list -= H + + for(var/datum/limb/limb in H.limbs) + switch(limb.name) + if("groin","chest") + limb.min_broken_damage = 60 + limb.max_damage = 200 + if("head") + limb.min_broken_damage = 40 + limb.max_damage = 125 + if("l_hand","r_hand","r_foot","l_foot") + limb.min_broken_damage = 37 + limb.max_damage = 100 + if("r_arm","l_arm") + limb.min_broken_damage = 50 + limb.max_damage = 150 + if("r_leg","l_leg") + limb.min_broken_damage = 50 + limb.max_damage = 125 + + set_predator_status(H, "Demoted") + + if(H.actions_by_path[/datum/action/minimap/yautja]) + var/datum/action/minimap/yautja/mini = H.actions_by_path[/datum/action/minimap/yautja] + mini.remove_action(src) + +/datum/species/yautja/handle_post_spawn(mob/living/carbon/human/H) + GLOB.alive_human_list -= H + + H.blood_type = "Y*" + H.h_style = H.client ? H.client.prefs.predator_h_style : "Standard" + #ifndef UNIT_TESTS // Since this is a hard ref, we shouldn't confuse create_and_destroy + GLOB.yautja_mob_list += H + #endif + + if(!H.actions_by_path[/datum/action/minimap/yautja]) + var/datum/action/minimap/yautja/mini = new + mini.give_action(H) + return ..() + +/datum/species/yautja/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(CHECK_BITFIELD(species_flags, NO_CHEM_METABOLIZATION)) //explicit + H.reagents.del_reagent(chem.type) //for the time being + return TRUE + if(CHECK_BITFIELD(species_flags, NO_POISON) && istype(chem, /datum/reagent/toxin)) + H.reagents.remove_reagent(chem.type, chem.custom_metabolism * H.metabolism_efficiency) + return TRUE + if(istype(chem, /datum/reagent/medicine)) + H.reagents.remove_reagent(chem.type, chem.custom_metabolism * H.metabolism_efficiency) + return TRUE + if(CHECK_BITFIELD(species_flags, NO_OVERDOSE)) //no stacking + if(chem.overdose_threshold && chem.volume > chem.overdose_threshold) + H.reagents.remove_reagent(chem.type, chem.volume - chem.overdose_threshold) + return FALSE diff --git a/code/modules/mob/living/carbon/human/yautja.dm b/code/modules/mob/living/carbon/human/yautja.dm index 8e28c2a5a95..770a2815169 100644 --- a/code/modules/mob/living/carbon/human/yautja.dm +++ b/code/modules/mob/living/carbon/human/yautja.dm @@ -5,214 +5,6 @@ if(client.clan_info) return client.clan_info.item[2] <= GLOB.clan_ranks_ordered.len ? GLOB.clan_ranks_ordered[client.clan_info.item[2]] : GLOB.clan_ranks_ordered[1] -/datum/species/yautja - name = "Yautja" - name_plural = "Yautja" - brute_mod = 0.28 //Beefy! - burn_mod = 0.45 - reagent_tag = IS_YAUTJA - species_flags = HAS_SKIN_COLOR|NO_POISON|NO_PAIN|USES_ALIEN_WEAPONS|PARALYSE_RESISTANT - inherent_traits = list( - TRAIT_YAUTJA_TECH, - TRAIT_SUPER_STRONG, - TRAIT_FOREIGN_BIO, - ) - inherent_actions = list( - /datum/action/predator_action/mark_for_hunt, - /datum/action/predator_action/mark_panel, - ) - - screams = list(MALE = "pred_scream", FEMALE = "pred_scream") - paincries = list(MALE = "pred_pain", FEMALE = "pred_pain") - goredcries = list(MALE = "pred_pain", FEMALE = "pred_pain") - burstscreams = list(MALE = "pred_preburst", FEMALE = "pred_preburst") - warcries = list(MALE = "pred_warcry", FEMALE = "pred_warcry") - - unarmed_type = /datum/unarmed_attack/punch/strong - secondary_unarmed_type = /datum/unarmed_attack/bite/strong - max_stamina = 250 - blood_color = "#20d450" - flesh_color = "#907E4A" - speech_sounds = list('sound/voice/predator/click1.ogg', 'sound/voice/predator/click2.ogg') - speech_chance = 100 - death_message = "clicks in agony and falls still, motionless and completely lifeless..." - - brute_damage_icon_state = "pred_brute" - burn_damage_icon_state = "pred_burn" - - darksight = 5 - slowdown = -0.5 - total_health = 175 //more health than regular humans - - default_language_holder = /datum/language_holder/yautja - - heat_level_1 = 500 - heat_level_2 = 700 - heat_level_3 = 1000 - - inherent_verbs = list( - /mob/living/carbon/human/proc/butcher, - ) - - knock_down_reduction = 4 - stun_reduction = 4 - - icobase = 'icons/mob/hunter/r_predator.dmi' - -/datum/species/yautja/handle_death(mob/living/carbon/human/H, gibbed) - if(gibbed) - GLOB.yautja_mob_list -= H - - for(var/mob/living/carbon/M in H.hunter_data.dishonored_targets) - M.hunter_data.dishonored_set = null - H.hunter_data.dishonored_targets -= M - for(var/mob/living/carbon/M in H.hunter_data.honored_targets) - M.hunter_data.honored_set = null - H.hunter_data.honored_targets -= M - for(var/mob/living/carbon/M in H.hunter_data.gear_targets) - M.hunter_data.gear_set = null - H.hunter_data.gear_targets -= M - - if(H.hunter_data.prey) - var/mob/living/carbon/M = H.hunter_data.prey - H.hunter_data.prey = null - M.hunter_data.hunter = null - M.hud_set_hunter() - - set_predator_status(H, gibbed ? "Gibbed" : "Dead") - - // Notify all yautja so they start the gear recovery - message_all_yautja("[H.real_name] has died at \the [get_area_name(H)].") - - if(H.hunter_data.thrall) - var/mob/living/carbon/T = H.hunter_data.thrall - message_all_yautja("[H.real_name]'s Thrall, [T.real_name] is now masterless.") - H.message_thrall("Your master has fallen!") - H.hunter_data.thrall = null - -/datum/species/yautja/proc/set_predator_status(mob/living/carbon/human/H, status = "Alive") - if(!H.key) - return - var/datum/game_mode/GM - if(SSticker?.mode) - GM = SSticker.mode - if(H.key in GM.predators) - GM.predators[lowertext(H.key)]["Status"] = status - else - GM.predators[lowertext(H.key)] = list("Name" = H.real_name, "Status" = status) - -/datum/species/yautja/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) - . = ..() - var/datum/atom_hud/A = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] - A.add_to_hud(H) - - for(var/datum/limb/limb in H.limbs) - switch(limb.name) - if("groin","chest") - limb.min_broken_damage = 120 - limb.max_damage = 350 - if("head") - limb.min_broken_damage = 100 - limb.max_damage = 350 - if("l_hand","r_hand","r_foot","l_foot") - limb.min_broken_damage = 85 - limb.max_damage = 180 - if("r_leg","r_arm","l_leg","l_arm") - limb.min_broken_damage = 100 - limb.max_damage = 225 - - set_predator_status(H, "Alive") - -/datum/species/yautja/post_species_loss(mob/living/carbon/human/H) - ..() - var/datum/atom_hud/A = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] - A.remove_hud_from(H) - remove_inherent_abilities(H) - H.blood_type = pick("A+","A-","B+","B-","O-","O+","AB+","AB-") - H.h_style = "Bald" - GLOB.yautja_mob_list -= H - - for(var/datum/limb/limb in H.limbs) - switch(limb.name) - if("groin","chest") - limb.min_broken_damage = 60 - limb.max_damage = 200 - if("head") - limb.min_broken_damage = 40 - limb.max_damage = 125 - if("l_hand","r_hand","r_foot","l_foot") - limb.min_broken_damage = 37 - limb.max_damage = 100 - if("r_arm","l_arm") - limb.min_broken_damage = 50 - limb.max_damage = 150 - if("r_leg","l_leg") - limb.min_broken_damage = 50 - limb.max_damage = 125 - - set_predator_status(H, "Demoted") - - if(H.actions_by_path[/datum/action/minimap/yautja]) - var/datum/action/minimap/yautja/mini = H.actions_by_path[/datum/action/minimap/yautja] - mini.remove_action(src) - -/datum/species/yautja/handle_post_spawn(mob/living/carbon/human/H) - GLOB.alive_human_list -= H - - H.blood_type = "Y*" - H.h_style = H.client ? H.client.prefs.predator_h_style : "Standard" - #ifndef UNIT_TESTS // Since this is a hard ref, we shouldn't confuse create_and_destroy - GLOB.yautja_mob_list += H - #endif - - if(!H.actions_by_path[/datum/action/minimap/yautja]) - var/datum/action/minimap/yautja/mini = new - mini.give_action(H) - - return ..() - -/mob/proc/hud_set_hunter() - return - -/mob/living/carbon/hud_set_hunter() - var/image/holder = hud_list[HUNTER_HUD] - if(!holder) - return - holder.icon_state = "" - holder.overlays.Cut() - if(hunter_data.hunted) - holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_hunted") - - if(hunter_data.dishonored) - holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_dishonored") - else if(hunter_data.honored) - holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_honored") - - if(hunter_data.thralled) - holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_thralled") - else if(hunter_data.gear) - holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_gear") - - hud_list[HUNTER_HUD] = holder - -/mob/living/carbon/xenomorph/hud_set_hunter() - var/image/holder = hud_list[HUNTER_HUD] - if(!holder) - return - holder.icon_state = "" - holder.overlays.Cut() - holder.pixel_x = -17 - holder.pixel_y = 20 - if(hunter_data.hunted) - holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_hunted") - - if(hunter_data.dishonored) - holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_dishonored") - else if(hunter_data.honored) - holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_honored") - - hud_list[HUNTER_HUD] = holder - /mob/living/carbon/human/species/yautja/hud_set_hunter() . = ..() @@ -242,29 +34,6 @@ . = bracer.embedded_id return . -/mob/living/carbon/human/proc/disable_special_items() - set waitfor = FALSE // Scout decloak animation uses sleep(), which is problematic for taser gun - - if(istype(back, /obj/item/storage/backpack/marine/satchel/scout_cloak)) - var/obj/item/storage/backpack/marine/satchel/scout_cloak/SC = back - if(SC.camo_active) - SC.camo_off(src) - return - var/list/cont = list() - for(var/atom/A in contents) - cont += A - if(A.contents.len) - cont += A.contents - - for(var/i in cont) - if(istype(i, /obj/item/assembly/prox_sensor)) - var/obj/item/assembly/prox_sensor/prox = i - if(prox.scanning) - prox.toggle_scan() - if(istype(i, /obj/item/attachable/motiondetector)) - var/obj/item/attachable/motiondetector/md = i - md.clean_operator() - /mob/living/carbon/human/species/yautja/get_reagent_tags() return species?.reagent_tag diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm index bede5c0511a..d38104ae7e8 100644 --- a/code/modules/mob/living/carbon/update_icons.dm +++ b/code/modules/mob/living/carbon/update_icons.dm @@ -38,3 +38,24 @@ if(changed) animate(src, transform = ntransform, time = (lying_prev == 0 || lying_angle == 0) ? 0.2 SECONDS : 0, pixel_y = final_pixel_y, dir = final_dir, easing = (EASE_IN|EASE_OUT)) + +/mob/living/carbon/hud_set_hunter() + var/image/holder = hud_list[HUNTER_HUD] + if(!holder) + return + holder.icon_state = "" + holder.overlays.Cut() + if(hunter_data.hunted) + holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_hunted") + + if(hunter_data.dishonored) + holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_dishonored") + else if(hunter_data.honored) + holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_honored") + + if(hunter_data.thralled) + holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_thralled") + else if(hunter_data.gear) + holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_gear") + + hud_list[HUNTER_HUD] = holder diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index 7df6bc58996..ba5cc47514a 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -514,40 +514,33 @@ keybinding_signals = list( KEYBINDING_NORMAL = COMSIG_XENOABILITY_EMIT_RECOVERY, ) + hidden = TRUE /datum/action/ability/xeno_action/pheromones/emit_recovery/action_activate() apply_pheros(AURA_XENO_RECOVERY) -/datum/action/ability/xeno_action/pheromones/emit_recovery/should_show() - return FALSE - /datum/action/ability/xeno_action/pheromones/emit_warding name = "Toggle Warding Pheromones" desc = "Increases armor for yourself and nearby teammates." keybinding_signals = list( KEYBINDING_NORMAL = COMSIG_XENOABILITY_EMIT_WARDING, ) + hidden = TRUE /datum/action/ability/xeno_action/pheromones/emit_warding/action_activate() apply_pheros(AURA_XENO_WARDING) -/datum/action/ability/xeno_action/pheromones/emit_warding/should_show() - return FALSE - /datum/action/ability/xeno_action/pheromones/emit_frenzy name = "Toggle Frenzy Pheromones" desc = "Increases damage for yourself and nearby teammates." keybinding_signals = list( KEYBINDING_NORMAL = COMSIG_XENOABILITY_EMIT_FRENZY, ) + hidden = TRUE /datum/action/ability/xeno_action/pheromones/emit_frenzy/action_activate() apply_pheros(AURA_XENO_FRENZY) -/datum/action/ability/xeno_action/pheromones/emit_frenzy/should_show() - return FALSE - - /datum/action/ability/activable/xeno/transfer_plasma name = "Transfer Plasma" action_icon_state = "transfer_plasma" @@ -1382,9 +1375,7 @@ KEYBINDING_NORMAL = COMSIG_XENOABILITY_BLESSINGSMENU, ) use_state_flags = ABILITY_USE_LYING|ABILITY_USE_CRESTED - -/datum/action/ability/xeno_action/blessing_menu/should_show() - return FALSE // Blessings meni now done through hive status UI! + hidden = TRUE /datum/action/ability/xeno_action/blessing_menu/action_activate() var/mob/living/carbon/xenomorph/X = owner diff --git a/code/modules/mob/living/carbon/xenomorph/castes/carrier/abilities_carrier.dm b/code/modules/mob/living/carbon/xenomorph/castes/carrier/abilities_carrier.dm index 2a832977002..b319513d4c4 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/carrier/abilities_carrier.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/carrier/abilities_carrier.dm @@ -347,10 +347,10 @@ GLOBAL_LIST_INIT(hugger_images_list, list( to_chat(owner, span_xenowarning("No weeds here!")) return FALSE - if(!T.check_alien_construction(owner, silent, /obj/structure/xeno/xeno_turret) || !T.check_disallow_alien_fortification(owner)) + if(!T.check_alien_construction(owner, silent, /obj/structure/xeno/turret) || !T.check_disallow_alien_fortification(owner)) return FALSE - for(var/obj/structure/xeno/xeno_turret/turret AS in GLOB.xeno_resin_turrets_by_hive[blocker.hivenumber]) + for(var/obj/structure/xeno/turret/turret AS in GLOB.xeno_resin_turrets_by_hive[blocker.hivenumber]) if(get_dist(turret, owner) < 6) if(!silent) to_chat(owner, span_xenowarning("Another turret is too close!")) @@ -364,7 +364,7 @@ GLOBAL_LIST_INIT(hugger_images_list, list( return FALSE var/mob/living/carbon/xenomorph/carrier/caster = owner - var/obj/structure/xeno/xeno_turret/hugger_turret/turret = new (get_turf(owner), caster.hivenumber) + var/obj/structure/xeno/turret/facehugger/turret = new (get_turf(owner), caster.hivenumber) turret.ammo = GLOB.ammo_list[GLOB.hugger_to_ammo[caster.selected_hugger_type]] succeed_activate() add_cooldown() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/defender/abilities_defender.dm b/code/modules/mob/living/carbon/xenomorph/castes/defender/abilities_defender.dm index 5edf369cf18..7c31dcfef05 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/defender/abilities_defender.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/defender/abilities_defender.dm @@ -15,32 +15,32 @@ /datum/action/ability/xeno_action/tail_sweep/can_use_action(silent, override_flags) . = ..() - var/mob/living/carbon/xenomorph/X = owner - if(X.crest_defense && X.plasma_stored < (ability_cost * 2)) - to_chat(X, span_xenowarning("We don't have enough plasma, we need [(ability_cost * 2) - X.plasma_stored] more plasma!")) + var/mob/living/carbon/xenomorph/xeno_owner = owner + if(xeno_owner.crest_defense && xeno_owner.plasma_stored < (ability_cost * 2)) + to_chat(xeno_owner, span_xenowarning("We don't have enough plasma, we need [(ability_cost * 2) - xeno_owner.plasma_stored] more plasma!")) return FALSE /datum/action/ability/xeno_action/tail_sweep/action_activate() - var/mob/living/carbon/xenomorph/X = owner + var/mob/living/carbon/xenomorph/xeno_owner = owner GLOB.round_statistics.defender_tail_sweeps++ SSblackbox.record_feedback(FEEDBACK_TALLY, "round_statistics", 1, "defender_tail_sweeps") - X.visible_message(span_xenowarning("\The [X] sweeps its tail in a wide circle!"), \ + xeno_owner.visible_message(span_xenowarning("\The [xeno_owner] sweeps its tail in a wide circle!"), \ span_xenowarning("We sweep our tail in a wide circle!")) - X.add_filter("defender_tail_sweep", 2, gauss_blur_filter(1)) //Add cool SFX - X.spin(4, 1) - X.enable_throw_parry(0.6 SECONDS) - playsound(X,pick('sound/effects/alien/tail_swipe1.ogg','sound/effects/alien/tail_swipe2.ogg','sound/effects/alien/tail_swipe3.ogg'), 25, 1) //Sound effects + xeno_owner.add_filter("defender_tail_sweep", 2, gauss_blur_filter(1)) //Add cool SFX + xeno_owner.spin(4, 1) + xeno_owner.enable_throw_parry(0.6 SECONDS) + playsound(xeno_owner,pick('sound/effects/alien/tail_swipe1.ogg','sound/effects/alien/tail_swipe2.ogg','sound/effects/alien/tail_swipe3.ogg'), 25, 1) //Sound effects var/sweep_range = 1 - var/list/L = orange(sweep_range, X) // Not actually the fruit + var/list/L = orange(sweep_range, xeno_owner) // Not actually the fruit for(var/obj/item/explosive/grenade/G in L) - G.knockback(X, 6, 2) + G.knockback(xeno_owner, 6, 2) for(var/obj/machinery/deployable/mounted/sentry/sentry in L) - var/damage = X.xeno_caste.melee_damage + var/damage = xeno_owner.xeno_caste.melee_damage sentry.take_damage(damage, BRUTE, MELEE) sentry.knock_down() @@ -49,11 +49,11 @@ continue H.add_filter("defender_tail_sweep", 2, gauss_blur_filter(1)) //Add cool SFX; motion blur addtimer(CALLBACK(H, TYPE_PROC_REF(/atom, remove_filter), "defender_tail_sweep"), 0.5 SECONDS) //Remove cool SFX - var/damage = X.xeno_caste.melee_damage + var/damage = xeno_owner.xeno_caste.melee_damage var/affecting = H.get_limb(ran_zone(null, 0)) if(!affecting) //Still nothing?? affecting = H.get_limb("chest") //Gotta have a torso?! - H.knockback(X, sweep_range, 4) + H.knockback(xeno_owner, sweep_range, 4) H.apply_damage(damage, BRUTE, affecting, MELEE) H.apply_damage(damage, STAMINA, updating_health = TRUE) H.Paralyze(0.5 SECONDS) //trip and go @@ -61,18 +61,18 @@ SSblackbox.record_feedback(FEEDBACK_TALLY, "round_statistics", 1, "defender_tail_sweep_hits") shake_camera(H, 2, 1) - to_chat(H, span_xenowarning("We are struck by \the [X]'s tail sweep!")) + to_chat(H, span_xenowarning("We are struck by \the [xeno_owner]'s tail sweep!")) playsound(H,'sound/weapons/alien_claw_block.ogg', 50, 1) - addtimer(CALLBACK(X, TYPE_PROC_REF(/atom, remove_filter), "defender_tail_sweep"), 0.5 SECONDS) //Remove cool SFX + addtimer(CALLBACK(xeno_owner, TYPE_PROC_REF(/atom, remove_filter), "defender_tail_sweep"), 0.5 SECONDS) //Remove cool SFX succeed_activate() - if(X.crest_defense) - X.use_plasma(ability_cost) + if(xeno_owner.crest_defense) + xeno_owner.use_plasma(ability_cost) add_cooldown() /datum/action/ability/xeno_action/tail_sweep/on_cooldown_finish() - var/mob/living/carbon/xenomorph/X = owner - to_chat(X, span_notice("We gather enough strength to tail sweep again.")) + var/mob/living/carbon/xenomorph/xeno_owner = owner + to_chat(xeno_owner, span_notice("We gather enough strength to tail sweep again.")) owner.playsound_local(owner, 'sound/effects/alien/newlarva.ogg', 25, 0, 1) return ..() @@ -179,67 +179,67 @@ /datum/action/ability/xeno_action/toggle_crest_defense/give_action() . = ..() - var/mob/living/carbon/xenomorph/defender/X = owner - last_crest_bonus = X.xeno_caste.crest_defense_armor + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner + last_crest_bonus = xeno_owner.xeno_caste.crest_defense_armor /datum/action/ability/xeno_action/toggle_crest_defense/on_xeno_upgrade() - var/mob/living/carbon/xenomorph/X = owner - if(X.crest_defense) - X.soft_armor = X.soft_armor.modifyAllRatings(-last_crest_bonus) - last_crest_bonus = X.xeno_caste.crest_defense_armor - X.soft_armor = X.soft_armor.modifyAllRatings(last_crest_bonus) - X.add_movespeed_modifier(MOVESPEED_ID_CRESTDEFENSE, TRUE, 0, NONE, TRUE, X.xeno_caste.crest_defense_slowdown) + var/mob/living/carbon/xenomorph/xeno_owner = owner + if(xeno_owner.crest_defense) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyAllRatings(-last_crest_bonus) + last_crest_bonus = xeno_owner.xeno_caste.crest_defense_armor + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyAllRatings(last_crest_bonus) + xeno_owner.add_movespeed_modifier(MOVESPEED_ID_CRESTDEFENSE, TRUE, 0, NONE, TRUE, xeno_owner.xeno_caste.crest_defense_slowdown) else - last_crest_bonus = X.xeno_caste.crest_defense_armor + last_crest_bonus = xeno_owner.xeno_caste.crest_defense_armor /datum/action/ability/xeno_action/toggle_crest_defense/on_cooldown_finish() - var/mob/living/carbon/xenomorph/defender/X = owner - to_chat(X, span_notice("We can [X.crest_defense ? "raise" : "lower"] our crest.")) + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner + to_chat(xeno_owner, span_notice("We can [xeno_owner.crest_defense ? "raise" : "lower"] our crest.")) return ..() /datum/action/ability/xeno_action/toggle_crest_defense/action_activate() - var/mob/living/carbon/xenomorph/defender/X = owner + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner - if(X.crest_defense) + if(xeno_owner.crest_defense) set_crest_defense(FALSE) add_cooldown() return succeed_activate() - var/was_fortified = X.fortify - if(X.fortify) - var/datum/action/ability/xeno_action/fortify/FT = X.actions_by_path[/datum/action/ability/xeno_action/fortify] + var/was_fortified = xeno_owner.fortify + if(xeno_owner.fortify) + var/datum/action/ability/xeno_action/fortify/FT = xeno_owner.actions_by_path[/datum/action/ability/xeno_action/fortify] if(FT.cooldown_timer) - to_chat(X, span_xenowarning("We cannot yet untuck ourselves!")) + to_chat(xeno_owner, span_xenowarning("We cannot yet untuck ourselves!")) return fail_activate() FT.set_fortify(FALSE, TRUE) FT.add_cooldown() - to_chat(X, span_xenowarning("We carefully untuck, keeping our crest lowered.")) + to_chat(xeno_owner, span_xenowarning("We carefully untuck, keeping our crest lowered.")) set_crest_defense(TRUE, was_fortified) add_cooldown() return succeed_activate() /datum/action/ability/xeno_action/toggle_crest_defense/proc/set_crest_defense(on, silent = FALSE) - var/mob/living/carbon/xenomorph/defender/X = owner + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner if(on) if(!silent) - to_chat(X, span_xenowarning("We tuck ourselves into a defensive stance.")) + to_chat(xeno_owner, span_xenowarning("We tuck ourselves into a defensive stance.")) GLOB.round_statistics.defender_crest_lowerings++ SSblackbox.record_feedback(FEEDBACK_TALLY, "round_statistics", 1, "defender_crest_lowerings") - ADD_TRAIT(X, TRAIT_STAGGERIMMUNE, CREST_DEFENSE_TRAIT) //Can now endure impacts/damages that would make lesser xenos flinch - X.soft_armor = X.soft_armor.modifyAllRatings(last_crest_bonus) - X.add_movespeed_modifier(MOVESPEED_ID_CRESTDEFENSE, TRUE, 0, NONE, TRUE, X.xeno_caste.crest_defense_slowdown) + ADD_TRAIT(xeno_owner, TRAIT_STAGGERIMMUNE, CREST_DEFENSE_TRAIT) //Can now endure impacts/damages that would make lesser xenos flinch + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyAllRatings(last_crest_bonus) + xeno_owner.add_movespeed_modifier(MOVESPEED_ID_CRESTDEFENSE, TRUE, 0, NONE, TRUE, xeno_owner.xeno_caste.crest_defense_slowdown) else if(!silent) - to_chat(X, span_xenowarning("We raise our crest.")) + to_chat(xeno_owner, span_xenowarning("We raise our crest.")) GLOB.round_statistics.defender_crest_raises++ SSblackbox.record_feedback(FEEDBACK_TALLY, "round_statistics", 1, "defender_crest_raises") - REMOVE_TRAIT(X, TRAIT_STAGGERIMMUNE, CREST_DEFENSE_TRAIT) - X.soft_armor = X.soft_armor.modifyAllRatings(-last_crest_bonus) - X.remove_movespeed_modifier(MOVESPEED_ID_CRESTDEFENSE) + REMOVE_TRAIT(xeno_owner, TRAIT_STAGGERIMMUNE, CREST_DEFENSE_TRAIT) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyAllRatings(-last_crest_bonus) + xeno_owner.remove_movespeed_modifier(MOVESPEED_ID_CRESTDEFENSE) - X.crest_defense = on - X.update_icons() + xeno_owner.crest_defense = on + xeno_owner.update_icons() // *************************************** // *********** Fortify @@ -254,79 +254,86 @@ KEYBINDING_NORMAL = COMSIG_XENOABILITY_FORTIFY, ) var/last_fortify_bonus = 0 + var/move_on_fortifed = FALSE /datum/action/ability/xeno_action/fortify/give_action() . = ..() - var/mob/living/carbon/xenomorph/defender/X = owner - last_fortify_bonus = X.xeno_caste.fortify_armor + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner + last_fortify_bonus = xeno_owner.xeno_caste.fortify_armor /datum/action/ability/xeno_action/fortify/on_xeno_upgrade() - var/mob/living/carbon/xenomorph/X = owner - if(X.fortify) - X.soft_armor = X.soft_armor.modifyAllRatings(-last_fortify_bonus) - X.soft_armor = X.soft_armor.modifyRating(BOMB = -last_fortify_bonus) + var/mob/living/carbon/xenomorph/xeno_owner = owner + if(xeno_owner.fortify) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyAllRatings(-last_fortify_bonus) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyRating(BOMB = -last_fortify_bonus) - last_fortify_bonus = X.xeno_caste.fortify_armor + last_fortify_bonus = xeno_owner.xeno_caste.fortify_armor - X.soft_armor = X.soft_armor.modifyAllRatings(last_fortify_bonus) - X.soft_armor = X.soft_armor.modifyRating(BOMB = last_fortify_bonus) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyAllRatings(last_fortify_bonus) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyRating(BOMB = last_fortify_bonus) else - last_fortify_bonus = X.xeno_caste.fortify_armor + last_fortify_bonus = xeno_owner.xeno_caste.fortify_armor /datum/action/ability/xeno_action/fortify/on_cooldown_finish() - var/mob/living/carbon/xenomorph/X = owner - to_chat(X, span_notice("We can [X.fortify ? "stand up" : "fortify"] again.")) + var/mob/living/carbon/xenomorph/xeno_owner = owner + to_chat(xeno_owner, span_notice("We can [xeno_owner.fortify ? "stand up" : "fortify"] again.")) return ..() /datum/action/ability/xeno_action/fortify/action_activate() - var/mob/living/carbon/xenomorph/defender/X = owner + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner - if(X.fortify) + if(xeno_owner.fortify) set_fortify(FALSE) add_cooldown() return succeed_activate() - var/was_crested = X.crest_defense - if(X.crest_defense) - var/datum/action/ability/xeno_action/toggle_crest_defense/CD = X.actions_by_path[/datum/action/ability/xeno_action/toggle_crest_defense] + var/was_crested = xeno_owner.crest_defense + if(xeno_owner.crest_defense) + var/datum/action/ability/xeno_action/toggle_crest_defense/CD = xeno_owner.actions_by_path[/datum/action/ability/xeno_action/toggle_crest_defense] if(CD.cooldown_timer) - to_chat(X, span_xenowarning("We cannot yet transition to a defensive stance!")) + to_chat(xeno_owner, span_xenowarning("We cannot yet transition to a defensive stance!")) return fail_activate() CD.set_crest_defense(FALSE, TRUE) CD.add_cooldown() - to_chat(X, span_xenowarning("We tuck our lowered crest into ourselves.")) + to_chat(xeno_owner, span_xenowarning("We tuck our lowered crest into ourselves.")) - var/datum/action/ability/activable/xeno/charge/forward_charge/combo_cooldown = X.actions_by_path[/datum/action/ability/activable/xeno/charge/forward_charge] - combo_cooldown.add_cooldown(cooldown_duration) + var/datum/action/ability/activable/xeno/charge/forward_charge/combo_cooldown = xeno_owner.actions_by_path[/datum/action/ability/activable/xeno/charge/forward_charge] + combo_cooldown?.add_cooldown(cooldown_duration) set_fortify(TRUE, was_crested) add_cooldown() return succeed_activate() /datum/action/ability/xeno_action/fortify/proc/set_fortify(on, silent = FALSE) - var/mob/living/carbon/xenomorph/defender/X = owner + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner GLOB.round_statistics.defender_fortifiy_toggles++ SSblackbox.record_feedback(FEEDBACK_TALLY, "round_statistics", 1, "defender_fortifiy_toggles") if(on) - ADD_TRAIT(X, TRAIT_IMMOBILE, FORTIFY_TRAIT) - ADD_TRAIT(X, TRAIT_STOPS_TANK_COLLISION, FORTIFY_TRAIT) + if(move_on_fortifed) + xeno_owner.add_movespeed_modifier(MOVESPEED_ID_FORTIFY, TRUE, 0, NONE, TRUE, 5) + else + ADD_TRAIT(xeno_owner, TRAIT_IMMOBILE, FORTIFY_TRAIT) + ADD_TRAIT(xeno_owner, TRAIT_STOPS_TANK_COLLISION, FORTIFY_TRAIT) if(!silent) - to_chat(X, span_xenowarning("We tuck ourselves into a defensive stance.")) - X.soft_armor = X.soft_armor.modifyAllRatings(last_fortify_bonus) - X.soft_armor = X.soft_armor.modifyRating(BOMB = last_fortify_bonus) //double bomb bonus for explosion immunity + to_chat(xeno_owner, span_xenowarning("We tuck ourselves into a defensive stance.")) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyAllRatings(last_fortify_bonus) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyRating(BOMB = last_fortify_bonus) //double bomb bonus for explosion immunity owner.drop_all_held_items() // drop items (hugger/jelly) else if(!silent) - to_chat(X, span_xenowarning("We resume our normal stance.")) - X.soft_armor = X.soft_armor.modifyAllRatings(-last_fortify_bonus) - X.soft_armor = X.soft_armor.modifyRating(BOMB = -last_fortify_bonus) - REMOVE_TRAIT(X, TRAIT_IMMOBILE, FORTIFY_TRAIT) - REMOVE_TRAIT(X, TRAIT_STOPS_TANK_COLLISION, FORTIFY_TRAIT) - - X.fortify = on - X.anchored = on - playsound(X.loc, 'sound/effects/stonedoor_openclose.ogg', 30, TRUE) - X.update_icons() + to_chat(xeno_owner, span_xenowarning("We resume our normal stance.")) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyAllRatings(-last_fortify_bonus) + xeno_owner.soft_armor = xeno_owner.soft_armor.modifyRating(BOMB = -last_fortify_bonus) + if(move_on_fortifed) + xeno_owner.remove_movespeed_modifier(MOVESPEED_ID_FORTIFY) + else + REMOVE_TRAIT(xeno_owner, TRAIT_IMMOBILE, FORTIFY_TRAIT) + REMOVE_TRAIT(xeno_owner, TRAIT_STOPS_TANK_COLLISION, FORTIFY_TRAIT) + + xeno_owner.fortify = on + xeno_owner.anchored = on + playsound(xeno_owner.loc, 'sound/effects/stonedoor_openclose.ogg', 30, TRUE) + xeno_owner.update_icons() // *************************************** // *********** Regenerate Skin @@ -344,27 +351,27 @@ ) /datum/action/ability/xeno_action/regenerate_skin/on_cooldown_finish() - var/mob/living/carbon/xenomorph/X = owner - to_chat(X, span_notice("We feel we are ready to shred our skin and grow another.")) + var/mob/living/carbon/xenomorph/xeno_owner = owner + to_chat(xeno_owner, span_notice("We feel we are ready to shred our skin and grow another.")) return ..() /datum/action/ability/xeno_action/regenerate_skin/action_activate() - var/mob/living/carbon/xenomorph/defender/X = owner + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner if(!can_use_action(TRUE)) return fail_activate() - if(X.on_fire) - to_chat(X, span_xenowarning("We can't use that while on fire.")) + if(xeno_owner.on_fire) + to_chat(xeno_owner, span_xenowarning("We can't use that while on fire.")) return fail_activate() - X.emote("roar") - X.visible_message(span_warning("The skin on \the [X] shreds and a new layer can be seen in it's place!"), + xeno_owner.emote("roar") + xeno_owner.visible_message(span_warning("The skin on \the [xeno_owner] shreds and a new layer can be seen in it's place!"), span_notice("We shed our skin, showing the fresh new layer underneath!")) - X.do_jitter_animation(1000) - X.set_sunder(0) - X.heal_overall_damage(50, 50, updating_health = TRUE) //RUTGMC EDIT + xeno_owner.do_jitter_animation(1000) + xeno_owner.set_sunder(0) + xeno_owner.heal_overall_damage(50, 50, updating_health = TRUE) add_cooldown() return succeed_activate() @@ -392,9 +399,9 @@ if(spin_loop_timer) return TRUE . = ..() - var/mob/living/carbon/xenomorph/X = owner - if(X.crest_defense && X.plasma_stored < (ability_cost * 2)) - to_chat(X, span_xenowarning("We don't have enough plasma, we need [(ability_cost * 2) - X.plasma_stored] more plasma!")) + var/mob/living/carbon/xenomorph/xeno_owner = owner + if(xeno_owner.crest_defense && xeno_owner.plasma_stored < (ability_cost * 2)) + to_chat(xeno_owner, span_xenowarning("We don't have enough plasma, we need [(ability_cost * 2) - xeno_owner.plasma_stored] more plasma!")) return FALSE /datum/action/ability/xeno_action/centrifugal_force/action_activate() @@ -416,43 +423,43 @@ /// runs a spin, then starts the timer for a new spin if needed /datum/action/ability/xeno_action/centrifugal_force/proc/do_spin() spin_loop_timer = null - var/mob/living/carbon/xenomorph/X = owner - X.spin(4, 1) - X.enable_throw_parry(0.6 SECONDS) - playsound(X, pick('sound/effects/alien/tail_swipe1.ogg','sound/effects/alien/tail_swipe2.ogg','sound/effects/alien/tail_swipe3.ogg'), 25, 1) //Sound effects + var/mob/living/carbon/xenomorph/xeno_owner = owner + xeno_owner.spin(4, 1) + xeno_owner.enable_throw_parry(0.6 SECONDS) + playsound(xeno_owner, pick('sound/effects/alien/tail_swipe1.ogg','sound/effects/alien/tail_swipe2.ogg','sound/effects/alien/tail_swipe3.ogg'), 25, 1) //Sound effects - for(var/obj/item/explosive/grenade/G in orange (1, X)) - G.knockback(X, 6, 2) + for(var/obj/item/explosive/grenade/G in orange (1, xeno_owner)) + G.knockback(xeno_owner, 6, 2) - for(var/obj/machinery/deployable/mounted/sentry/sentry in orange (1, X)) - var/damage = X.xeno_caste.melee_damage + for(var/obj/machinery/deployable/mounted/sentry/sentry in orange (1, xeno_owner)) + var/damage = xeno_owner.xeno_caste.melee_damage sentry.take_damage(damage, BRUTE, MELEE) sentry.knock_down() - for(var/mob/living/carbon/human/slapped in orange(1, X)) + for(var/mob/living/carbon/human/slapped in orange(1, xeno_owner)) if(slapped.stat == DEAD) continue slapped.add_filter("defender_tail_sweep", 2, gauss_blur_filter(1)) //Add cool SFX; motion blur addtimer(CALLBACK(slapped, TYPE_PROC_REF(/atom, remove_filter), "defender_tail_sweep"), 0.5 SECONDS) //Remove cool SFX - var/damage = X.xeno_caste.melee_damage * 0.5 + var/damage = xeno_owner.xeno_caste.melee_damage * 0.5 var/affecting = slapped.get_limb(ran_zone(null, 0)) if(!affecting) affecting = slapped.get_limb("chest") - slapped.knockback(X, 1, 4) + slapped.knockback(xeno_owner, 1, 4) slapped.apply_damage(damage, BRUTE, affecting, MELEE) slapped.apply_damage(damage, STAMINA, updating_health = TRUE) slapped.Paralyze(0.3 SECONDS) shake_camera(slapped, 2, 1) - to_chat(slapped, span_xenowarning("We are struck by \the [X]'s flying tail!")) + to_chat(slapped, span_xenowarning("We are struck by \the [xeno_owner]'s flying tail!")) playsound(slapped, 'sound/weapons/alien_claw_block.ogg', 50, 1) - succeed_activate(X.crest_defense ? ability_cost * 2 : ability_cost) + succeed_activate(xeno_owner.crest_defense ? ability_cost * 2 : ability_cost) if(step_tick) - step(X, pick(GLOB.alldirs)) + step(xeno_owner, pick(GLOB.alldirs)) step_tick = !step_tick - if(can_use_action(X, ABILITY_IGNORE_COOLDOWN)) + if(can_use_action(xeno_owner, ABILITY_IGNORE_COOLDOWN)) spin_loop_timer = addtimer(CALLBACK(src, PROC_REF(do_spin)), 5, TIMER_STOPPABLE) return stop_spin() @@ -464,3 +471,152 @@ deltimer(spin_loop_timer) spin_loop_timer = null UnregisterSignal(owner, list(SIGNAL_ADDTRAIT(TRAIT_FLOORED), SIGNAL_ADDTRAIT(TRAIT_INCAPACITATED), SIGNAL_ADDTRAIT(TRAIT_IMMOBILE))) + +// *************************************** +// *********** Headbutt +// *************************************** + +/datum/action/ability/activable/xeno/headbutt + name = "Headbutt" + action_icon_state = "headbutt" + desc = "Headbutts into the designated target" + cooldown_duration = 10 SECONDS + ability_cost = 35 + use_state_flags = ABILITY_USE_FORTIFIED|ABILITY_USE_CRESTED // yea + keybinding_signals = list( + KEYBINDING_NORMAL = COMSIG_XENOABILITY_STEELCREST_HEADBUTT, + ) + target_flags = ABILITY_MOB_TARGET + var/base_damage = 30 + +/datum/action/ability/activable/xeno/headbutt/on_cooldown_finish() + to_chat(owner, span_notice("We gather enough strength to headbutt again.")) + return ..() + +/datum/action/ability/activable/xeno/headbutt/can_use_ability(atom/target, silent = FALSE, override_flags) + . = ..() + if(!.) + return FALSE + if(QDELETED(target)) + return FALSE + if(!ishuman(target)) + return FALSE + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner + var/max_dist = 2 - (xeno_owner.crest_defense) + if(!line_of_sight(owner, target, max_dist)) + if(!silent) + to_chat(owner, span_warning("We must get closer to headbutt")) + return FALSE + if(ishuman(target)) + var/mob/living/carbon/human/victim = target + if(isnestedhost(victim)) + return FALSE + if(!CHECK_BITFIELD(use_state_flags|override_flags, ABILITY_IGNORE_DEAD_TARGET) && victim.stat == DEAD) + return FALSE + +/datum/action/ability/activable/xeno/headbutt/use_ability(atom/target) + var/mob/living/carbon/xenomorph/defender/xeno_owner = owner + var/mob/living/victim = target + + SSblackbox.record_feedback(FEEDBACK_TALLY, "round_statistics", 1, "headbutts") + + var/headbutt_distance = 1 + (xeno_owner.crest_defense * 2) + (xeno_owner.fortify * 2) + var/headbutt_damage = base_damage - (xeno_owner.crest_defense * 10) + + if(!xeno_owner.crest_defense) + add_cooldown() + xeno_owner.throw_at(get_step_towards(victim, xeno_owner), 4, 3, owner) + if(!xeno_owner.Adjacent(victim)) + succeed_activate() + return + + owner.visible_message(span_xenowarning("[owner] rams [victim] with its armored crest!"), \ + span_xenowarning("We ram [victim] with our armored crest!")) + + victim.apply_damage(headbutt_damage, BRUTE, BODY_ZONE_CHEST, MELEE) + + xeno_owner.do_attack_animation(victim) + + var/facing = get_dir(xeno_owner, victim) + var/turf/T = victim.loc + var/turf/temp + for(var/x in 1 to headbutt_distance) + temp = get_step(T, facing) + if(!temp) + break + T = temp + victim.throw_at(T, headbutt_distance, 1, owner, TRUE) + + playsound(victim,'sound/weapons/alien_claw_block.ogg', 75, 1) + + succeed_activate() + add_cooldown() + +/datum/action/ability/xeno_action/soak + name = "soak" + action_icon_state = "soak" + desc = "When activated tracks damaged taken for 6 seconds, once the amount of damage reaches 140, the Defender is healed by 75 and the Tail Slam cooldown is reset. If the damage threshold is not reached, nothing happens." + cooldown_duration = 17 SECONDS + ability_cost = 35 + use_state_flags = ABILITY_USE_FORTIFIED|ABILITY_USE_CRESTED // yea + keybinding_signals = list( + KEYBINDING_NORMAL = COMSIG_XENOABILITY_STEELCREST_SOAK, + ) + /// Requires 140 damage taken within 6 seconds to activate the ability + var/damage_threshold = 140 + /// Heal + var/heal_amount = 80 + /// Sunder heal + var/heal_sunder_amount = 25 + /// Initially zero, gets damage added when the ability is activated + var/damage_accumulated = 0 + +/datum/action/ability/xeno_action/soak/action_activate(atom/target) + var/mob/living/carbon/xenomorph/xeno_owner = owner + + RegisterSignal(xeno_owner, COMSIG_XENOMORPH_TAKING_DAMAGE, PROC_REF(damage_accumulate)) + addtimer(CALLBACK(src, PROC_REF(stop_accumulating)), 6 SECONDS) + + xeno_owner.balloon_alert(xeno_owner, "begins to tank incoming damage!") + + to_chat(xeno_owner, span_xenonotice("We begin to tank incoming damage!")) + + xeno_owner.add_filter("steelcrest_enraging", 1, list("type" = "outline", "color" = "#421313", "size" = 1)) + + succeed_activate() + add_cooldown() + +/datum/action/ability/xeno_action/soak/proc/damage_accumulate(datum/source, damage) + SIGNAL_HANDLER + + damage_accumulated += damage + + if(damage_accumulated >= damage_threshold) + addtimer(CALLBACK(src, PROC_REF(enraged), owner), 0.1 SECONDS) //CM use timer, so i do + UnregisterSignal(owner, COMSIG_XENOMORPH_TAKING_DAMAGE) // Two Unregistersignal because if the enrage proc doesnt happen, then it needs to stop counting + +/datum/action/ability/xeno_action/soak/proc/stop_accumulating() + UnregisterSignal(owner, COMSIG_XENOMORPH_TAKING_DAMAGE) + + damage_accumulated = 0 + to_chat(owner, span_xenonotice("We stop taking incoming damage.")) + owner.remove_filter("steelcrest_enraging") + +/datum/action/ability/xeno_action/soak/proc/enraged() + owner.remove_filter("steelcrest_enraging") + owner.add_filter("steelcrest_enraged", 1, list("type" = "outline", "color" = "#ad1313", "size" = 1)) + + owner.visible_message(span_xenowarning("[owner] gets enraged after being damaged enough!"), \ + span_xenowarning("We feel enraged after taking in oncoming damage! Our tail slam's cooldown is reset and we heal!")) + + var/mob/living/carbon/xenomorph/enraged_mob = owner + HEAL_XENO_DAMAGE(enraged_mob, heal_amount, FALSE) + enraged_mob.adjust_sunder(-heal_sunder_amount) + + addtimer(CALLBACK(src, PROC_REF(remove_enrage), owner), 3 SECONDS) + +/datum/action/ability/xeno_action/soak/proc/remove_enrage() + owner.remove_filter("steelcrest_enraged") + +/datum/action/ability/xeno_action/fortify/steel_crest + move_on_fortifed = TRUE diff --git a/code/modules/mob/living/carbon/xenomorph/castes/defender/castedatum_defender.dm b/code/modules/mob/living/carbon/xenomorph/castes/defender/castedatum_defender.dm index 167214217df..d03e76c13cf 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/defender/castedatum_defender.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/defender/castedatum_defender.dm @@ -53,7 +53,10 @@ /datum/action/ability/xeno_action/tail_sweep, ) -/datum/xeno_caste/defender/ancient +/datum/xeno_caste/defender/normal + upgrade = XENO_UPGRADE_NORMAL + +/datum/xeno_caste/defender/steel_crest/normal upgrade = XENO_UPGRADE_NORMAL /datum/xeno_caste/defender/primordial @@ -72,3 +75,35 @@ /datum/action/ability/xeno_action/tail_sweep, /datum/action/ability/xeno_action/centrifugal_force, ) + +/datum/xeno_caste/defender/steel_crest + caste_type_path = /mob/living/carbon/xenomorph/defender/steel_crest + base_caste_type_path = /mob/living/carbon/xenomorph/defender + upgrade_name = "" + caste_name = "Defender" + display_name = "Steel crest" + upgrade = XENO_UPGRADE_BASETYPE + caste_desc = "An alien with an armored crest. It looks very tough." + + // *** Speed *** // + speed = -0.4 + + // *** Defender Abilities *** // + crest_defense_armor = 30 + crest_defense_slowdown = 0.8 + fortify_armor = 40 + + actions = list( + /datum/action/ability/xeno_action/xeno_resting, + /datum/action/ability/xeno_action/watch_xeno, + /datum/action/ability/activable/xeno/psydrain, + /datum/action/ability/xeno_action/fortify/steel_crest, + /datum/action/ability/xeno_action/toggle_crest_defense, + /datum/action/ability/activable/xeno/headbutt, + /datum/action/ability/xeno_action/soak, + ) + +/datum/xeno_caste/defender/steel_crest/primordial + upgrade_name = "Primordial" + upgrade = XENO_UPGRADE_PRIMO + caste_desc = "Alien with an incredibly tough and armored head crest able to endure even the strongest hits." diff --git a/code/modules/mob/living/carbon/xenomorph/castes/defender/defender.dm b/code/modules/mob/living/carbon/xenomorph/castes/defender/defender.dm index fbd230aff73..bba27badc16 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/defender/defender.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/defender/defender.dm @@ -43,9 +43,13 @@ if(isnull(.)) return if(. == CONSCIOUS && fortify) //No longer conscious. - var/datum/action/ability/xeno_action/fortify/FT = actions_by_path[/datum/action/ability/xeno_action/fortify] - FT.set_fortify(FALSE) //Fortify prevents dragging due to the anchor component. - + //Fortify prevents dragging due to the anchor component. // TODO: Unshitcode me + if(actions_by_path[/datum/action/ability/xeno_action/fortify]) + var/datum/action/ability/xeno_action/fortify/FT = actions_by_path[/datum/action/ability/xeno_action/fortify] + FT.set_fortify(FALSE) + else if(actions_by_path[/datum/action/ability/xeno_action/fortify/steel_crest]) + var/datum/action/ability/xeno_action/fortify/FT = actions_by_path[/datum/action/ability/xeno_action/fortify/steel_crest] + FT.set_fortify(FALSE) // *************************************** // *********** Mob overrides @@ -54,3 +58,24 @@ /mob/living/carbon/xenomorph/defender/Initialize(mapload) . = ..() AddComponent(/datum/component/throw_parry) + +// *************************************** +// *********** Steel crest +// *************************************** + +/mob/living/carbon/xenomorph/defender/steel_crest + icon = 'icons/Xeno/castes/defender/steel_crest.dmi' + caste_base_type = /datum/xeno_caste/defender/steel_crest + +// *************************************** +// *********** Front Armor +// *************************************** + +/mob/living/carbon/xenomorph/defender/steel_crest/projectile_hit(obj/projectile/proj, cardinal_move, uncrossing) + if(SEND_SIGNAL(src, COMSIG_XENO_PROJECTILE_HIT, proj, cardinal_move, uncrossing) & COMPONENT_PROJECTILE_DODGE) + return FALSE + if(proj.ammo.flags_ammo_behavior & AMMO_SKIPS_ALIENS) + return FALSE + if((cardinal_move & REVERSE_DIR(dir))) + proj.damage -= proj.damage * (0.2 * get_sunder()) + return ..() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/hivemind/hivemind.dm b/code/modules/mob/living/carbon/xenomorph/castes/hivemind/hivemind.dm index 9f214ea4008..f58770375fe 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/hivemind/hivemind.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/hivemind/hivemind.dm @@ -29,6 +29,7 @@ sight = SEE_MOBS|SEE_TURFS|SEE_OBJS see_in_dark = 8 move_on_shuttle = TRUE + initial_language_holder = /datum/language_holder/hivemind hud_type = /datum/hud/hivemind hud_possible = list(PLASMA_HUD, HEALTH_HUD_XENO, PHEROMONE_HUD, XENO_RANK_HUD, QUEEN_OVERWATCH_HUD, XENO_BLESSING_HUD, XENO_EVASION_HUD) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/hunter/abilities_hunter.dm b/code/modules/mob/living/carbon/xenomorph/castes/hunter/abilities_hunter.dm index 00efedefec0..be8f5635701 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/hunter/abilities_hunter.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/hunter/abilities_hunter.dm @@ -632,6 +632,7 @@ ability_cost = 0 cooldown_duration = 0 keybind_flags = ABILITY_USE_STAGGERED | ABILITY_IGNORE_SELECTED_ABILITY + hidden = TRUE /datum/action/ability/xeno_action/hunter_army/give_action(mob/living/L) . = ..() @@ -653,9 +654,6 @@ if(prob(ILUSSION_CHANCE)) new /mob/illusion/xeno(target_turf, owner, owner, ILLUSION_LIFETIME) -/datum/action/ability/xeno_action/hunter_army/should_show() - return FALSE - // *************************************** // *********** Crippling strike // *************************************** diff --git a/code/modules/mob/living/carbon/xenomorph/castes/king/king.dm b/code/modules/mob/living/carbon/xenomorph/castes/king/king.dm index 86f059663af..9e17e5e28ea 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/king/king.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/king/king.dm @@ -44,7 +44,7 @@ if(4201 to 9000) name = prefix + "Ancient Emperor ([nicknumber])" if(9001 to INFINITY) - name = prefix + "Prime Emperor ([nicknumber])" + name = prefix + "Primal Emperor ([nicknumber])" else name = prefix + "Young King ([nicknumber])" diff --git a/code/modules/mob/living/carbon/xenomorph/castes/queen/abilities_queen.dm b/code/modules/mob/living/carbon/xenomorph/castes/queen/abilities_queen.dm index 33f365838ab..7c6f8fc5f37 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/queen/abilities_queen.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/queen/abilities_queen.dm @@ -16,7 +16,7 @@ var/mob/living/carbon/xenomorph/queen/Q = owner //Preferring the use of multiline input as the message box is larger and easier to quickly proofread before sending to hive. - var/input = stripped_multiline_input(Q, "Maximum message length: [MAX_BROADCAST_LEN]", "Hive Message", "", MAX_BROADCAST_LEN, TRUE) + var/input = stripped_multiline_input(Q, "Максимальная длина: [MAX_BROADCAST_LEN]", "Приказ Улью", "", MAX_BROADCAST_LEN, TRUE) //Newlines are of course stripped and replaced with a space. input = capitalize(trim(replacetext(input, "\n", " "))) if(!input) @@ -34,14 +34,14 @@ log_game("[key_name(Q)] has messaged the hive with: \"[input]\"") deadchat_broadcast(" has messaged the hive: \"[input]\"", Q, Q) - var/queens_word = "HIVE MESSAGE:
" + input + var/queens_word = "ПРИКАЗ УЛЬЮ:
" + input var/sound/queen_sound = sound(get_sfx("queen"), channel = CHANNEL_ANNOUNCEMENTS) var/sound/king_sound = sound('sound/voice/alien/xenos_roaring.ogg', channel = CHANNEL_ANNOUNCEMENTS) for(var/mob/living/carbon/xenomorph/X AS in Q.hive.get_all_xenos()) to_chat(X, assemble_alert( - title = "Hive Announcement", - subtitle = "From [Q.name]", + title = "Приказ Улью", + subtitle = "Приказ [Q.name]", message = input, color_override = "purple" )) @@ -224,6 +224,7 @@ desc = "See from the target Xenomorphs vision. Click again the ability to stop observing" ability_cost = 0 use_state_flags = ABILITY_USE_LYING + hidden = TRUE var/overwatch_active = FALSE /datum/action/ability/xeno_action/watch_xeno/give_action(mob/living/L) @@ -237,9 +238,6 @@ UnregisterSignal(L, list(COMSIG_MOB_DEATH, COMSIG_XENOMORPH_WATCHXENO)) return ..() -/datum/action/ability/xeno_action/watch_xeno/should_show() - return FALSE // Overwatching now done through hive status UI! - /datum/action/ability/xeno_action/watch_xeno/proc/start_overwatch(mob/living/carbon/xenomorph/target) if(!can_use_action()) // Check for action now done here as action_activate pipeline has been bypassed with signal activation. return @@ -359,9 +357,7 @@ desc = "Make a target Xenomorph a leader." ability_cost = 200 use_state_flags = ABILITY_USE_LYING - -/datum/action/ability/xeno_action/set_xeno_lead/should_show() - return FALSE // Leadership now set through hive status UI! + hidden = TRUE /datum/action/ability/xeno_action/set_xeno_lead/give_action(mob/living/L) . = ..() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/queen/queen.dm b/code/modules/mob/living/carbon/xenomorph/castes/queen/queen.dm index 72b590df603..df98d46d3ee 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/queen/queen.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/queen/queen.dm @@ -87,7 +87,7 @@ if(4201 to 9000) name = prefix + "Ancient Empress ([nicknumber])" if(9001 to INFINITY) - name = prefix + "Prime Empress ([nicknumber])" + name = prefix + "Primal Empress ([nicknumber])" else name = prefix + "Young Queen ([nicknumber])" diff --git a/code/modules/mob/living/carbon/xenomorph/castes/warrior/abilities_warrior.dm b/code/modules/mob/living/carbon/xenomorph/castes/warrior/abilities_warrior.dm index 26dbc36d1e4..282fadf01ae 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/warrior/abilities_warrior.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/warrior/abilities_warrior.dm @@ -18,9 +18,7 @@ /datum/action/ability/activable/xeno/warrior/punch/jab, /datum/action/ability/activable/xeno/warrior/punch/flurry, ) - -/datum/action/ability/xeno_action/empower/should_show() - return FALSE + hidden = TRUE /// Checks if Empower is capped and gives bonuses if so, otherwise increases combo count. /datum/action/ability/xeno_action/empower/proc/check_empower(atom/target) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/widow/abilities_widow.dm b/code/modules/mob/living/carbon/xenomorph/castes/widow/abilities_widow.dm index 53e96c87446..54b00ff12b7 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/widow/abilities_widow.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/widow/abilities_widow.dm @@ -164,6 +164,9 @@ if(owner.do_actions) return fail_activate() + if(current_charges <= 0) + return fail_activate() + var/mob/living/carbon/xenomorph/X = owner if(length(spiderlings) >= X.xeno_caste.max_spiderlings) X.balloon_alert(X, "Max Spiderlings") @@ -411,6 +414,7 @@ ability_cost = 0 cooldown_duration = 0 keybind_flags = ABILITY_USE_STAGGERED | ABILITY_IGNORE_SELECTED_ABILITY + hidden = TRUE /datum/action/ability/xeno_action/spider_venom/give_action(mob/living/L) . = ..() @@ -428,6 +432,3 @@ return target.apply_status_effect(STATUS_EFFECT_SPIDER_VENOM) - -/datum/action/ability/xeno_action/spider_venom/should_show() - return FALSE diff --git a/code/modules/mob/living/carbon/xenomorph/charge_crush.dm b/code/modules/mob/living/carbon/xenomorph/charge_crush.dm index d1dc7ae9f10..64846e2c795 100644 --- a/code/modules/mob/living/carbon/xenomorph/charge_crush.dm +++ b/code/modules/mob/living/carbon/xenomorph/charge_crush.dm @@ -279,7 +279,7 @@ if(isobj(crushed)) var/obj/crushed_obj = crushed - if(istype(crushed_obj, /obj/structure/xeno/silo) || istype(crushed_obj, /obj/structure/xeno/xeno_turret)) + if(istype(crushed_obj, /obj/structure/xeno/silo) || istype(crushed_obj, /obj/structure/xeno/turret)) return precrush2signal(crushed_obj.post_crush_act(charger, src)) playsound(crushed_obj.loc, "punch", 25, 1) var/crushed_behavior = crushed_obj.crushed_special_behavior() diff --git a/code/modules/mob/living/carbon/xenomorph/egg.dm b/code/modules/mob/living/carbon/xenomorph/egg.dm index a3a9e365c66..3dee9bacf95 100644 --- a/code/modules/mob/living/carbon/xenomorph/egg.dm +++ b/code/modules/mob/living/carbon/xenomorph/egg.dm @@ -100,13 +100,13 @@ //Observers can become playable facehuggers by clicking on the egg /obj/alien/egg/hugger/attack_ghost(mob/dead/observer/user) . = ..() - var/datum/hive_status/hive = GLOB.hive_datums[hivenumber] if(maturity_stage != stage_ready_to_burst) return FALSE if(!hugger_type) return FALSE + var/datum/hive_status/hive = GLOB.hive_datums[hivenumber] if(!hive.can_spawn_as_hugger(user)) return FALSE @@ -137,7 +137,7 @@ F.balloon_alert(F, span_xenowarning("We can't use this egg")) return - F.visible_message(span_xenowarning("[F] slides back into [src]."),span_xenonotice("You slides back into [src].")) + F.visible_message(span_xenowarning("[F] slides back into [src]."),span_xenonotice("You slide back into [src].")) F.ghostize() F.death(deathmessage = "get inside the egg", silent = TRUE) qdel(F) diff --git a/code/modules/mob/living/carbon/xenomorph/embryo.dm b/code/modules/mob/living/carbon/xenomorph/embryo.dm index ca3a6e056df..01ceed82799 100644 --- a/code/modules/mob/living/carbon/xenomorph/embryo.dm +++ b/code/modules/mob/living/carbon/xenomorph/embryo.dm @@ -147,7 +147,7 @@ if(isyautja(affected_mob)) new_xeno = new /mob/living/carbon/xenomorph/larva/predalien(affected_mob) - yautja_announcement(span_yautjaboldbig("WARNING!\n\nAn abomination has been detected at [get_area_name(new_xeno)]. It is a stain upon our purity and is unfit for life. Exterminate it immediately.\n\nHeavy Armory unlocked.")) + yautja_announcement(span_yautjaboldbig("ТРЕВОГА!\n\nЗамечено Отродье в [get_area_name(new_xeno)]. Это слишком низко для нашей чести. Ошибка природы. Уничтожьте его немедленно.\n\nОткрыт доступ к Тяжелому Вооружению.")) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_YAUTJA_ARMORY_OPENED) else new_xeno = new(affected_mob) diff --git a/code/modules/mob/living/carbon/xenomorph/evolution.dm b/code/modules/mob/living/carbon/xenomorph/evolution.dm index a3928a480b9..0af4df8ae57 100644 --- a/code/modules/mob/living/carbon/xenomorph/evolution.dm +++ b/code/modules/mob/living/carbon/xenomorph/evolution.dm @@ -133,7 +133,7 @@ ///Actually changes the xenomorph to another caste /mob/living/carbon/xenomorph/proc/finish_evolve(new_mob_type) - var/mob/living/carbon/xenomorph/new_xeno = new new_mob_type(get_turf(src)) + var/mob/living/carbon/xenomorph/new_xeno = new new_mob_type(get_turf(src), TRUE) if(!istype(new_xeno)) //Something went horribly wrong! @@ -148,7 +148,6 @@ return SEND_SIGNAL(src, COMSIG_XENOMORPH_EVOLVED, new_xeno) - for(var/obj/item/W in contents) //Drop stuff dropItemToGround(W) @@ -168,6 +167,11 @@ qdel(new_xeno.hunter_data) new_xeno.hunter_data = hunter_data hunter_data = null + new_xeno.upgrades_holder = upgrades_holder + for(var/datum/status_effect/S AS in new_xeno.upgrades_holder) + new_xeno.apply_status_effect(S) + new_xeno.generate_name() // This is specifically for numbered xenos who want to keep their previous number instead of a random new one. + new_xeno.hive?.update_ruler() // Since ruler wasn't set during initialization, update ruler now. transfer_observers_to(new_xeno) if(new_xeno.health - getBruteLoss(src) - getFireLoss(src) > 0) //Cmon, don't kill the new one! Shouldnt be possible though @@ -221,7 +225,6 @@ selector?.set_selected_zone(zone_selected, new_xeno) qdel(src) INVOKE_ASYNC(new_xeno, TYPE_PROC_REF(/atom, do_jitter_animation), 1000) - new_xeno.overlay_fullscreen_timer(2 SECONDS, 20, "roundstart2", /atom/movable/screen/fullscreen/spawning_in) ///Check if the xeno is currently able to evolve /mob/living/carbon/xenomorph/proc/generic_evolution_checks() diff --git a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm index 602f7759cbe..598a4e647a2 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm @@ -122,7 +122,7 @@ for(var/obj/structure/xeno/silo/resin_silo AS in GLOB.xeno_resin_silos_by_hive[hivenumber]) .["hive_structures"] += list(get_structure_packet(resin_silo)) // Acid, sticky, and hugger turrets. - for(var/obj/structure/xeno/xeno_turret/turret AS in GLOB.xeno_resin_turrets_by_hive[hivenumber]) + for(var/obj/structure/xeno/turret/turret AS in GLOB.xeno_resin_turrets_by_hive[hivenumber]) .["hive_structures"] += list(get_structure_packet(turret)) // Psychic relays for(var/obj/structure/xeno/psychictower/tower AS in GLOB.hive_datums[hivenumber].psychictowers) @@ -403,6 +403,9 @@ // *********** Adding xenos // *************************************** /datum/hive_status/proc/add_xeno(mob/living/carbon/xenomorph/X) // should only be called by add_to_hive below + if(isnull(X)) // don't add nulls please + return FALSE + if(X.stat == DEAD) dead_xenos += X else @@ -429,7 +432,7 @@ return TRUE -/mob/living/carbon/xenomorph/proc/add_to_hive(datum/hive_status/HS, force=FALSE) +/mob/living/carbon/xenomorph/proc/add_to_hive(datum/hive_status/HS, force=FALSE, prevent_ruler=FALSE) if(!force && hivenumber != XENO_HIVE_NONE) CRASH("trying to do a dirty add_to_hive") @@ -446,24 +449,30 @@ SSdirection.start_tracking(HS.hivenumber, src) hive.update_tier_limits() //Update our tier limits. -/mob/living/carbon/xenomorph/queen/add_to_hive(datum/hive_status/HS, force=FALSE) // override to ensure proper queen/hive behaviour +/mob/living/carbon/xenomorph/queen/add_to_hive(datum/hive_status/HS, force=FALSE, prevent_ruler=FALSE) // override to ensure proper queen/hive behaviour . = ..() if(HS.living_xeno_queen) // theres already a queen return HS.living_xeno_queen = src + if(prevent_ruler) + return + HS.update_ruler() -/mob/living/carbon/xenomorph/shrike/add_to_hive(datum/hive_status/HS, force = FALSE) // override to ensure proper queen/hive behaviour +/mob/living/carbon/xenomorph/shrike/add_to_hive(datum/hive_status/HS, force = FALSE, prevent_ruler=FALSE) // override to ensure proper queen/hive behaviour . = ..() if(HS.living_xeno_ruler) return + if(prevent_ruler) + return + HS.update_ruler() -/mob/living/carbon/xenomorph/hivemind/add_to_hive(datum/hive_status/HS, force = FALSE) +/mob/living/carbon/xenomorph/hivemind/add_to_hive(datum/hive_status/HS, force = FALSE, prevent_ruler=FALSE) . = ..() if(!GLOB.xeno_structures_by_hive[HS.hivenumber]) GLOB.xeno_structures_by_hive[HS.hivenumber] = list() @@ -484,23 +493,26 @@ hive_core.name = "[HS.hivenumber == XENO_HIVE_NORMAL ? "" : "[HS.name] "]hivemind core" hive_core.color = HS.color -/mob/living/carbon/xenomorph/king/add_to_hive(datum/hive_status/HS, force = FALSE) +/mob/living/carbon/xenomorph/king/add_to_hive(datum/hive_status/HS, force = FALSE, prevent_ruler=FALSE) . = ..() if(HS.living_xeno_ruler) return + if(prevent_ruler) + return + HS.update_ruler() -/mob/living/carbon/xenomorph/proc/add_to_hive_by_hivenumber(hivenumber, force=FALSE) // helper function to add by given hivenumber +/mob/living/carbon/xenomorph/proc/add_to_hive_by_hivenumber(hivenumber, force=FALSE, prevent_ruler=FALSE) // helper function to add by given hivenumber if(!GLOB.hive_datums[hivenumber]) CRASH("add_to_hive_by_hivenumber called with invalid hivenumber") var/datum/hive_status/HS = GLOB.hive_datums[hivenumber] - add_to_hive(HS, force) + add_to_hive(HS, force, prevent_ruler) hive.update_tier_limits() //Update our tier limits. // This is a special proc called only when a xeno is first created to set their hive and name properly -/mob/living/carbon/xenomorph/proc/set_initial_hivenumber() - add_to_hive_by_hivenumber(hivenumber, force=TRUE) +/mob/living/carbon/xenomorph/proc/set_initial_hivenumber(prevent_ruler=FALSE) + add_to_hive_by_hivenumber(hivenumber, force=TRUE, prevent_ruler=prevent_ruler) // *************************************** // *********** Removing xenos @@ -829,20 +841,23 @@ // *************************************** // *********** Xeno death // *************************************** -/datum/hive_status/proc/on_xeno_death(mob/living/carbon/xenomorph/X) - remove_from_lists(X) - dead_xenos += X - SEND_SIGNAL(X, COMSIG_HIVE_XENO_DEATH) +///Handles any effects when a xeno dies +/datum/hive_status/proc/on_xeno_death(mob/living/carbon/xenomorph/dead_xeno) + remove_from_lists(dead_xeno) + dead_xenos += dead_xeno + + SEND_SIGNAL(dead_xeno, COMSIG_HIVE_XENO_DEATH) - if(X == living_xeno_ruler) - on_ruler_death(X) - var/datum/xeno_caste/caste = X?.xeno_caste - if(caste.death_evolution_delay <= 0) + if(dead_xeno == living_xeno_ruler) + on_ruler_death(dead_xeno) + var/datum/xeno_caste/base_caste = GLOB.xeno_caste_datums[dead_xeno.caste_base_type][XENO_UPGRADE_BASETYPE] + if(base_caste.death_evolution_delay <= 0) return - if(!caste_death_timers[caste]) - caste_death_timers[caste] = addtimer(CALLBACK(src, PROC_REF(end_caste_death_timer), caste), caste.death_evolution_delay , TIMER_STOPPABLE) + if(!caste_death_timers[base_caste]) + caste_death_timers[base_caste] = addtimer(CALLBACK(src, PROC_REF(end_caste_death_timer), base_caste), base_caste.death_evolution_delay , TIMER_STOPPABLE) +///Handles effects if a xeno is revived /datum/hive_status/proc/on_xeno_revive(mob/living/carbon/xenomorph/X) dead_xenos -= X add_to_lists(X) @@ -1016,7 +1031,7 @@ to_chat will check for valid clients itself already so no need to double check f /datum/hive_status/proc/set_all_xeno_trackers(atom/target) for(var/mob/living/carbon/xenomorph/X AS in get_all_xenos()) X.set_tracked(target) - to_chat(X, span_notice(" Now tracking [target.name]")) + to_chat(X, span_notice("Now tracking [target.name]")) // *************************************** // *********** Normal Xenos diff --git a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm index 562bb3cdb04..d912be2f905 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm @@ -250,6 +250,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( /datum/hive_upgrade/building/upgrade_chamber flags_upgrade = ABILITY_NUCLEARWAR + building_loc = 0 var/max_chambers = 3 /datum/hive_upgrade/building/upgrade_chamber/shell @@ -303,7 +304,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( ///How long to build one turret var/build_time = 10 SECONDS ///What type of turret is built - var/turret_type = /obj/structure/xeno/xeno_turret + var/turret_type = /obj/structure/xeno/turret /datum/hive_upgrade/defence/turret/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) . = ..() @@ -324,10 +325,10 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( to_chat(buyer, span_xenowarning("No weeds here!")) return FALSE - if(!T.check_alien_construction(buyer, silent, /obj/structure/xeno/xeno_turret) || !T.check_disallow_alien_fortification(buyer)) + if(!T.check_alien_construction(buyer, silent, /obj/structure/xeno/turret) || !T.check_disallow_alien_fortification(buyer)) return FALSE - for(var/obj/structure/xeno/xeno_turret/turret AS in GLOB.xeno_resin_turrets_by_hive[blocker.hivenumber]) + for(var/obj/structure/xeno/turret/turret AS in GLOB.xeno_resin_turrets_by_hive[blocker.hivenumber]) if(get_dist(turret, buyer) < 6) if(!silent) to_chat(buyer, span_xenowarning("Another turret is too close!")) @@ -355,7 +356,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( desc = "Places a sticky spit spitting resin turret under you. Must be at least 6 tiles away from other turrets, not near fog and on a weeded area." icon = "resinturret" psypoint_cost = 50 - turret_type = /obj/structure/xeno/xeno_turret/sticky + turret_type = /obj/structure/xeno/turret/sticky /datum/hive_upgrade/xenos category = "Xenos" diff --git a/code/modules/mob/living/carbon/xenomorph/update_icons.dm b/code/modules/mob/living/carbon/xenomorph/update_icons.dm index 19f50b8ae84..55fc77ac05b 100644 --- a/code/modules/mob/living/carbon/xenomorph/update_icons.dm +++ b/code/modules/mob/living/carbon/xenomorph/update_icons.dm @@ -201,3 +201,21 @@ else set_light_range_power_color(intensity, 0.5, LIGHT_COLOR_FIRE) set_light_on(TRUE) + +/mob/living/carbon/xenomorph/hud_set_hunter() + var/image/holder = hud_list[HUNTER_HUD] + if(!holder) + return + holder.icon_state = "" + holder.overlays.Cut() + holder.pixel_x = -17 + holder.pixel_y = 20 + if(hunter_data.hunted) + holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_hunted") + + if(hunter_data.dishonored) + holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_dishonored") + else if(hunter_data.honored) + holder.overlays += image('icons/mob/screen/yautja.dmi', src, "hunter_honored") + + hud_list[HUNTER_HUD] = holder diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index c8dd5e558df..eb0b5f97959 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -350,6 +350,8 @@ GLOBAL_LIST_INIT(strain_list, init_glob_strain_list()) var/regen_power = 0 ///Stored biomass var/biomass = 0 + ///Stored upgrade effects, so we reapply them on evolve + var/list/upgrades_holder = list() var/is_zoomed = FALSE var/zoom_turf = null diff --git a/code/modules/mob/living/carbon/xenomorph/xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/xenomorph.dm index 67c6a446a59..49a331ab367 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenomorph.dm @@ -4,7 +4,7 @@ //Just about ALL the procs are tied to the parent, not to the children //This is so they can be easily transferred between them without copypasta -/mob/living/carbon/xenomorph/Initialize(mapload) +/mob/living/carbon/xenomorph/Initialize(mapload, do_not_set_as_ruler) if(mob_size == MOB_SIZE_BIG) move_resist = MOVE_FORCE_EXTREMELY_STRONG move_force = MOVE_FORCE_EXTREMELY_STRONG @@ -28,7 +28,7 @@ if(is_centcom_level(z) && hivenumber == XENO_HIVE_NORMAL) hivenumber = XENO_HIVE_ADMEME //so admins can safely spawn xenos in Thunderdome for tests. - set_initial_hivenumber() + set_initial_hivenumber(prevent_ruler=do_not_set_as_ruler) switch(stat) if(CONSCIOUS) @@ -167,7 +167,7 @@ if(4201 to 9000) rank_name = "Ancient" if(9001 to INFINITY) - rank_name = "Prime" + rank_name = "Primal" else rank_name = "Young" var/prefix = (hive.prefix || xeno_caste.upgrade_name) ? "[hive.prefix][xeno_caste.upgrade_name] " : "" diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index 075d4614579..90e971d031b 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -441,9 +441,7 @@ if(locate(/turf/closed/wall/resin) in loc) to_chat(src, span_warning("We decide not to drop [F] after all.")) return - - . = ..() - + return ..() //When the Queen's pheromones are updated, or we add/remove a leader, update leader pheromones /mob/living/carbon/xenomorph/proc/handle_xeno_leader_pheromones(mob/living/carbon/xenomorph/queen/Q) @@ -659,16 +657,6 @@ get_upgrades(src) /mob/living/carbon/xenomorph/proc/get_upgrades(mob/living/carbon/xenomorph/user) - var/upgrade_price - switch(xeno_caste.tier) - if(XENO_TIER_ONE) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T1 - if(XENO_TIER_TWO) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T2 - if(XENO_TIER_THREE) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T3 - else - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T4 var/dat = "
" dat += "
Active Upgrade Chambers:" @@ -682,17 +670,17 @@ var/spur_chambers_built = length(user?.hive?.spur_chambers) var/veil_chambers_built = length(user?.hive?.veil_chambers) dat += "
SURVIVAL
" - dat += "[shell_chambers_built ? "
Carapace " : "
Carapace "] | Cost: [upgrade_price] | Increase our armor." - dat += "[shell_chambers_built ? "
Regeneration " : "
Regeneration "] | Cost: [upgrade_price] | Increase our health regeneration." - dat += "[shell_chambers_built ? "
Vampirism " : "
Vampirism "] | Cost: [upgrade_price] | Leech from our attacks." + dat += "[shell_chambers_built ? "
Carapace " : "
Carapace "] | Cost: [XENO_UPGRADE_COST] | Increase our armor." + dat += "[shell_chambers_built ? "
Regeneration " : "
Regeneration "] | Cost: [XENO_UPGRADE_COST] | Increase our health regeneration." + dat += "[shell_chambers_built ? "
Vampirism " : "
Vampirism "] | Cost: [XENO_UPGRADE_COST] | Leech from our attacks." dat += "
ATTACK
" - dat += "[spur_chambers_built ? "
Celerity " : "
Celerity "] | Cost: [upgrade_price] | Increase our movement speed." - dat += "[spur_chambers_built ? "
Adrenalin " : "
Adrenalin "] | Cost: [upgrade_price] | Increase our plasma regeneration." - dat += "[spur_chambers_built ? "
Crush " : "
Crush "] | Cost: [upgrade_price] | Increase our damage to objects." + dat += "[spur_chambers_built ? "
Celerity " : "
Celerity "] | Cost: [XENO_UPGRADE_COST] | Increase our movement speed." + dat += "[spur_chambers_built ? "
Adrenalin " : "
Adrenalin "] | Cost: [XENO_UPGRADE_COST] | Increase our plasma regeneration." + dat += "[spur_chambers_built ? "
Crush " : "
Crush "] | Cost: [XENO_UPGRADE_COST] | Increase our damage to objects." dat += "
UTILITY
" - dat += "[veil_chambers_built ? "
Toxin " : "
Toxin "] | Cost: [upgrade_price] | Inject neurotoxin into the target." - dat += "[veil_chambers_built ? "
Pheromones " : "
Pheromones "] | Cost: [upgrade_price] | Ability to emit pheromones." - dat += "[veil_chambers_built ? "
Trail " : "
Trail "] | Cost: [upgrade_price] | Leave a trail behind." + dat += "[veil_chambers_built ? "
Toxin " : "
Toxin "] | Cost: [XENO_UPGRADE_COST] | Inject neurotoxin into the target." + dat += "[veil_chambers_built ? "
Pheromones " : "
Pheromones "] | Cost: [XENO_UPGRADE_COST] | Ability to emit pheromones." + dat += "[veil_chambers_built ? "
Trail " : "
Trail "] | Cost: [XENO_UPGRADE_COST] | Leave a trail behind." var/datum/browser/popup = new(user, "upgrademenu", "
Mutations Menu
", 600, 600) popup.set_content(dat) @@ -702,17 +690,7 @@ if(incapacitated(TRUE)) to_chat(usr, span_warning("Cant do that right now!")) return - var/upgrade_price - switch(xeno_caste.tier) - if(XENO_TIER_ONE) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T1 - if(XENO_TIER_TWO) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T2 - if(XENO_TIER_THREE) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T3 - else - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T4 - if(biomass < upgrade_price) + if(biomass < XENO_UPGRADE_COST) to_chat(usr, span_warning("You dont have enough biomass!")) return var/upgrade = locate(upgrade_to_apply) in status_effects @@ -720,12 +698,14 @@ to_chat(usr, span_xenonotice("Existing mutation chosen. No biomass spent.")) DIRECT_OUTPUT(usr, browse(null, "window=["upgrademenu"]")) return - biomass -= upgrade_price + biomass -= XENO_UPGRADE_COST to_chat(usr, span_xenonotice("Mutation gained.")) for(var/datum/status_effect/S AS in upgrades_to_remove) remove_status_effect(S) + upgrades_holder.Remove(S.type) do_jitter_animation(500) apply_status_effect(upgrade_to_apply) + upgrades_holder.Add(upgrade_to_apply.type) DIRECT_OUTPUT(usr, browse(null, "window=["upgrademenu"]")) //Special override case. May not call the parent. diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index fe0aebcd4cf..7fd5a5060d6 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -323,6 +323,8 @@ return FALSE if(buckled || now_pushing) return + if(anchored) + return if(isliving(A)) var/mob/living/L = A diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 88130e2750f..9bffe969dd4 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -527,7 +527,7 @@ if(!can_use_action()) return owner.playsound_local(owner, "sound/effects/CIC_order.ogg", 10, 1) - TIMER_COOLDOWN_START(owner, COOLDOWN_HUD_ORDER, ORDER_COOLDOWN) + TIMER_COOLDOWN_START(owner, COOLDOWN_HUD_ORDER, CIC_ORDER_COOLDOWN) log_game("[key_name(owner)] has broadcasted the hud message [text] at [AREACOORD(owner)]") deadchat_broadcast(" has sent the command order \"[text]\"", owner, owner) for(var/mob/living/carbon/human/human AS in GLOB.alive_human_list) diff --git a/code/modules/mob/living/silicon/ai/ai_verbs.dm b/code/modules/mob/living/silicon/ai/ai_verbs.dm index 35aa86eecb8..46ecbbb9662 100644 --- a/code/modules/mob/living/silicon/ai/ai_verbs.dm +++ b/code/modules/mob/living/silicon/ai/ai_verbs.dm @@ -153,7 +153,7 @@ return last_announcement = world.time - priority_announce(input, "[src] Announcement", sound = 'sound/AI/aireport.ogg') + priority_announce(input, "Оповещение от [src]", sound = 'sound/AI/aireport.ogg') /mob/living/silicon/ai/verb/ai_core_display() @@ -320,6 +320,6 @@ log_game("[key_name(src)] has ghosted at [AREACOORD(src)].") message_admins("[ADMIN_TPMONTY(src)] has ghosted.") - priority_announce("[src] has suffered an unexpected NTOS failure over its Logarithmic silicon backhaul functions and has been taken offline. An attempt to load a backup personality core will proceed shortly.", "AI NT-OS Critical Failure") + priority_announce("[src] был отключен. Ожидание загрузки новой личности...", "Сбой ИИ", sound = 'sound/AI/aileft.ogg') ghostize(FALSE) offer_mob() diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index a8815a0061a..661d2e08339 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -45,9 +45,6 @@ /mob/living/silicon/put_in_r_hand(obj/item/I) return -/mob/living/silicon/stripPanelUnequip(obj/item/I, mob/M, slot) - return - /mob/living/silicon/med_hud_set_health() return diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index e6086011dd9..1dc60661422 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -378,9 +378,9 @@ GLOBAL_LIST_INIT(organ_rel_size, list( A.target = source if(!alert_overlay) alert_overlay = new(source) - var/icon/I = icon(source.icon) - var/iheight = I.Height() - var/iwidth = I.Width() + var/list/icon_dimensions = get_icon_dimensions(source.icon) + var/iheight = icon_dimensions["width"] + var/iwidth = icon_dimensions["height"] var/higher_power = (iheight > iwidth) ? iheight : iwidth if(higher_power > 32) var/diff = 32 / higher_power diff --git a/code/modules/mob/update_icons.dm b/code/modules/mob/update_icons.dm index 58c7b6dd60c..f5be18d6bf1 100644 --- a/code/modules/mob/update_icons.dm +++ b/code/modules/mob/update_icons.dm @@ -63,3 +63,6 @@ /mob/proc/update_burst() return + +/mob/proc/hud_set_hunter() + return diff --git a/code/modules/orbits/spaceship.dm b/code/modules/orbits/spaceship.dm index d058fe16f2c..0852570b41c 100644 --- a/code/modules/orbits/spaceship.dm +++ b/code/modules/orbits/spaceship.dm @@ -160,8 +160,8 @@ GLOBAL_VAR_INIT(current_orbit,STANDARD_ORBIT) return message_admins("[ADMIN_TPMONTY(usr)] Has sent the ship [direction == "UP" ? "UPWARD" : "DOWNWARD"] in orbit") - var/message = "Prepare for orbital change in 10 seconds.\nMoving [direction] the gravity well.\nSecure all belongings and prepare for engine ignition." - minor_announce(message, title = "Orbit Change") + var/message = "Внимание. [direction == "UP" ? "Подъём" : "Снижение"] на другую орбиту через 10 секунд." + minor_announce(message, title = "Смена Орбиты") addtimer(CALLBACK(src, PROC_REF(do_change_orbit), current_orbit, direction), 10 SECONDS) /obj/machinery/computer/navigation/proc/can_change_orbit(current_orbit, direction, silent = FALSE) @@ -194,8 +194,8 @@ GLOBAL_VAR_INIT(current_orbit,STANDARD_ORBIT) changing_orbit = TRUE engine_shudder() - var/message = "Arriving at new orbital level. Prepare for engine ignition and stabilization." - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(minor_announce), message, "Orbit Change"), 290 SECONDS) + var/message = "Переход на новую орбиту. Приготовьтесь к запуску двигателей и стабилизации." + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(minor_announce), message, "Смена Орбиты"), 290 SECONDS) addtimer(CALLBACK(src, PROC_REF(orbit_gets_changed), current_orbit, direction), 3 MINUTES) /obj/machinery/computer/navigation/proc/orbit_gets_changed(current_orbit, direction) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 5bc55e70d38..dcfec555aa3 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -328,7 +328,7 @@ playsound_z(3, 'sound/effects/powerloss.ogg') if(announce) - priority_announce("Abnormal activity detected in the ship power system. As a precaution, power must be shut down for an indefinite duration.", "Critical Power Failure", sound = 'sound/AI/poweroff.ogg') + priority_announce("В системе питания судна обнаружена аномальная активность. В качестве меры предосторожности питание будет отключено на неопределенный срок.", "Критический Сбой Питания", sound = 'sound/AI/poweroff.ogg') /proc/power_restore(announce = TRUE) @@ -351,7 +351,7 @@ if(announce) - priority_announce("Power has been restored. Reason: Unknown.", "Power Systems Nominal", sound = 'sound/AI/poweron.ogg') + priority_announce("Питание восстановлено. Причина: Неизвестно.", "Восстановление Питания", sound = 'sound/AI/poweron.ogg') /proc/power_restore_quick(announce = TRUE) @@ -365,7 +365,7 @@ S.power_change() if(announce) - priority_announce("Power has been restored. Reason: Unknown.", "Power Systems Nominal", sound = 'sound/AI/poweron.ogg') + priority_announce("Питание восстановлено. Причина: Неизвестно.", "Восстановление Питания", sound = 'sound/AI/poweron.ogg') /proc/power_restore_everything(announce = TRUE) @@ -382,4 +382,4 @@ C.cell.charge = C.cell.maxcharge if(announce) - priority_announce("Power has been restored. Reason: Unknown.", "Power Systems Nominal", sound = 'sound/AI/poweron.ogg') + priority_announce("Питание восстановлено. Причина: Неизвестно.", "Восстановление Питания", sound = 'sound/AI/poweron.ogg') diff --git a/code/modules/projectiles/ammo_casing.dm b/code/modules/projectiles/ammo_casing.dm new file mode 100644 index 00000000000..2a28b5acd67 --- /dev/null +++ b/code/modules/projectiles/ammo_casing.dm @@ -0,0 +1,86 @@ +/* +Doesn't do anything or hold anything anymore. +Generated per the various mags, and then changed based on the number of +casings. .dir is the main thing that controls the icon. It modifies +the icon_state to look like more casings are hitting the ground. +There are 8 directions, 8 bullets are possible so after that it tries to grab the next +icon_state while reseting the direction. After 16 casings, it just ignores new +ones. At that point there are too many anyway. Shells and bullets leave different +items, so they do not intersect. This is far more efficient than using Blend() or +Turn() or Shift() as there is virtually no overhead. ~N +*/ +/obj/item/ammo_casing + name = "spent casing" + desc = "Empty and useless now." + icon = 'icons/obj/items/casings.dmi' + icon_state = "casing_" + throwforce = 1 + w_class = WEIGHT_CLASS_TINY + layer = LOWER_ITEM_LAYER //Below other objects + dir = 1 //Always north when it spawns. + flags_atom = CONDUCT|DIRLOCK + ///This is manipulated in the procs that use these. + var/current_casings = 1 + ///Maximum amount of casings 1 stack can have + var/max_casings = 16 + ///Current icon of the casings stack, increases by 1 with each casing in the stack + var/current_icon = 0 + ///How many variations of this item there are. + var/number_of_states = 10 + ///holder for icon_state so we can do random variations without effecting mapper visibility + var/initial_icon_state = "cartridge_" + +/obj/item/ammo_casing/Initialize(mapload) + . = ..() + pixel_x = rand(-2, 2) //Want to move them just a tad. + pixel_y = rand(-2, 2) + icon_state = initial_icon_state += "[rand(1, number_of_states)]" //Set the icon to it. + +//This does most of the heavy lifting. It updates the icon and name if needed + +/obj/item/ammo_casing/update_name(updates) + . = ..() + if(max_casings >= current_casings && current_casings == 2) + name += "s" //In case there is more than one. + +/obj/item/ammo_casing/update_icon_state() + . = ..() + if(max_casings < current_casings) + return + if(round((current_casings - 1) / 8) > current_icon) + current_icon++ + icon_state += "_[current_icon]" + + var/base_direction = current_casings - (current_icon * 8) + setDir(base_direction + round(base_direction) / 3) + switch(current_casings) + if(3 to 5) + w_class = WEIGHT_CLASS_SMALL //Slightly heavier. + if(9 to 10) + w_class = WEIGHT_CLASS_NORMAL //Can't put it in your pockets and stuff. + +///changes .dir to simulate new casings, also sets the new w_class +/obj/item/ammo_casing/proc/update_dir() + var/base_direction = current_casings - (current_icon * 8) + setDir(base_direction + round(base_direction) / 3) + switch(current_casings) + if(3 to 5) + w_class = WEIGHT_CLASS_SMALL //Slightly heavier. + if(9 to 10) + w_class = WEIGHT_CLASS_NORMAL //Can't put it in your pockets and stuff. + +/obj/item/ammo_casing/update_icon() + update_dir() + return ..() + +//Making child objects so that locate() and istype() doesn't screw up. +/obj/item/ammo_casing/bullet + +/obj/item/ammo_casing/cartridge + name = "spent cartridge" + icon_state = "cartridge" + +/obj/item/ammo_casing/shell + name = "spent shell" + initial_icon_state = "shell_" + icon_state = "shell" diff --git a/code/modules/projectiles/ammo_datums/bullet/machinegun.dm b/code/modules/projectiles/ammo_datums/bullet/machinegun.dm index c32d6fe7e68..63092ccbef9 100644 --- a/code/modules/projectiles/ammo_datums/bullet/machinegun.dm +++ b/code/modules/projectiles/ammo_datums/bullet/machinegun.dm @@ -90,17 +90,6 @@ penetration = 10 sundering = 1 -/datum/ammo/bullet/sg29 - name = "smartmachinegun bullet" - bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction - hud_state = "smartgun" - hud_state_empty = "smartgun_empty" - flags_ammo_behavior = AMMO_BALLISTIC - accurate_range = 8 - damage = 20 - penetration = 5 - additional_xeno_penetration = 20 - /datum/ammo/bullet/smart_minigun name = "smartminigun bullet" bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction @@ -108,6 +97,14 @@ hud_state_empty = "smartgun_empty" flags_ammo_behavior = AMMO_BALLISTIC accurate_range = 12 - damage = 25 - penetration = -15 + damage = 12 + penetration = 20 damage_falloff = 0.1 + var/shatter_duration = 3 SECONDS + +/datum/ammo/bullet/smart_minigun/on_hit_mob(mob/M, obj/projectile/proj) + if(!isliving(M)) + return + + var/mob/living/living_victim = M + living_victim.apply_status_effect(STATUS_EFFECT_SHATTER, shatter_duration) diff --git a/code/modules/projectiles/ammo_datums/xeno.dm b/code/modules/projectiles/ammo_datums/xeno.dm index 918f07805d8..e14b9aec91e 100644 --- a/code/modules/projectiles/ammo_datums/xeno.dm +++ b/code/modules/projectiles/ammo_datums/xeno.dm @@ -573,15 +573,15 @@ GLOBAL_LIST_INIT(no_sticky_resin, typecacheof(list(/obj/item/clothing/mask/faceh /datum/ammo/xeno/hugger/on_hit_mob(mob/M, obj/projectile/proj) var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(get_turf(M), hivenumber) - hugger.go_idle() + hugger.Attach(M) /datum/ammo/xeno/hugger/on_hit_obj(obj/O, obj/projectile/proj) var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(get_turf(O), hivenumber) - hugger.go_idle() + hugger.go_active() /datum/ammo/xeno/hugger/on_hit_turf(turf/T, obj/projectile/P) var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(T.density ? P.loc : T, hivenumber) - hugger.go_idle() + hugger.go_active() /datum/ammo/xeno/hugger/do_at_max_range(turf/T, obj/projectile/P) var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(T.density ? P.loc : T, hivenumber) diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index e43b4e4cb1f..06291ece24d 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -1,20 +1,19 @@ /obj/item/ammo_magazine name = "generic ammo" desc = "A box of ammo." - icon = 'icons/obj/items/ammo.dmi' - icon_state = null + icon = 'icons/obj/items/ammo/magazine.dmi' item_state = "ammo_mag" //PLACEHOLDER. This ensures the mag doesn't use the icon state instead. item_icons = list( slot_l_hand_str = 'icons/mob/inhands/weapons/ammo_left.dmi', slot_r_hand_str = 'icons/mob/inhands/weapons/ammo_right.dmi', - ) + ) flags_atom = CONDUCT flags_equip_slot = ITEM_SLOT_BELT throwforce = 2 w_class = WEIGHT_CLASS_TINY throw_speed = 2 throw_range = 6 - ///Icon state in ammo.dmi to an overlay to add to the gun, for extended mags, box mags, and so on + ///Icon state to an overlay to add to the gun, for extended mags, box mags, and so on var/bonus_overlay = null ///This is a typepath for the type of bullet the magazine holds, it is cast so that it can draw the variable handful_amount from default_ammo in create_handful() var/datum/ammo/bullet/default_ammo = /datum/ammo/bullet @@ -80,7 +79,6 @@ . = ..() . += "[src] has [current_rounds] rounds out of [max_rounds]." - /obj/item/ammo_magazine/attack_hand(mob/living/user) if(user.get_inactive_held_item() != src || !CHECK_BITFIELD(flags_magazine, MAGAZINE_REFILLABLE)) return ..() @@ -119,7 +117,6 @@ transfer_ammo(mag, user, amount_to_transfer) - /obj/item/ammo_magazine/attackby_alternate(obj/item/I, mob/user, params) . = ..() if(!isgun(I)) @@ -135,7 +132,6 @@ master_gun.aim_slowdown += aim_speed_mod master_gun.wield_delay += wield_delay_mod - /obj/item/ammo_magazine/proc/on_removed(obj/item/weapon/gun/master_gun) master_gun.scatter -= scatter_mod master_gun.scatter_unwielded -= scatter_unwielded_mod @@ -191,29 +187,6 @@ update_icon() -///This will attempt to place the ammo in the user's hand if possible. -/obj/item/ammo_magazine/proc/create_handful(mob/user, transfer_amount) - if(current_rounds <= 0) - return - var/obj/item/ammo_magazine/handful/new_handful = new /obj/item/ammo_magazine/handful() - var/rounds = transfer_amount ? min(current_rounds, transfer_amount) : min(current_rounds, initial(default_ammo.handful_amount)) - new_handful.generate_handful(default_ammo, caliber, rounds) - current_rounds -= rounds - - if(user) - user.put_in_hands(new_handful) - to_chat(user, span_notice("You grab [rounds] round\s from [src].")) - update_icon() //Update the other one. - if(current_rounds <= 0 && CHECK_BITFIELD(flags_magazine, MAGAZINE_HANDFUL)) - user.temporarilyRemoveItemFromInventory(src) - qdel(src) - return rounds //Give the number created. - else - update_icon() - if(current_rounds <= 0 && CHECK_BITFIELD(flags_magazine, MAGAZINE_HANDFUL)) - qdel(src) - return new_handful - ///Called on a /ammo_magazine that wishes to be a handful. It generates all the data required for the handful. /obj/item/ammo_magazine/proc/generate_handful(new_ammo, new_caliber, new_rounds, maximum_rounds) var/datum/ammo/ammo = ispath(new_ammo) ? GLOB.ammo_list[new_ammo] : new_ammo @@ -236,6 +209,28 @@ current_rounds = new_rounds update_icon() +///This will attempt to place the ammo in the user's hand if possible. +/obj/item/ammo_magazine/proc/create_handful(mob/user, transfer_amount) + if(current_rounds <= 0) + return + var/obj/item/ammo_magazine/handful/new_handful = new /obj/item/ammo_magazine/handful() + var/rounds = transfer_amount ? min(current_rounds, transfer_amount) : min(current_rounds, initial(default_ammo.handful_amount)) + new_handful.generate_handful(default_ammo, caliber, rounds) + current_rounds -= rounds + + if(user) + user.put_in_hands(new_handful) + to_chat(user, span_notice("You grab [rounds] round\s from [src].")) + update_icon() //Update the other one. + if(current_rounds <= 0 && CHECK_BITFIELD(flags_magazine, MAGAZINE_HANDFUL)) + user.temporarilyRemoveItemFromInventory(src) + qdel(src) + return rounds //Give the number created. + else + update_icon() + if(current_rounds <= 0 && CHECK_BITFIELD(flags_magazine, MAGAZINE_HANDFUL)) + qdel(src) + return new_handful //our magazine inherits ammo info from a source magazine /obj/item/ammo_magazine/proc/match_ammo(obj/item/ammo_magazine/source) @@ -258,417 +253,4 @@ //Helper proc, to allow us to see a percentage of how full the magazine is. /obj/item/ammo_magazine/proc/get_ammo_percent() // return % charge of cell - return 100.0*current_rounds/max_rounds - -/obj/item/ammo_magazine/handful - name = "generic handful of bullets or shells" - desc = "A handful of rounds to reload on the go." - flags_equip_slot = null // It only fits into pockets and such. - w_class = WEIGHT_CLASS_SMALL - current_rounds = 1 // So it doesn't get autofilled for no reason. - max_rounds = 5 // For shotguns, though this will be determined by the handful type when generated. - flags_atom = CONDUCT|DIRLOCK - flags_magazine = MAGAZINE_HANDFUL|MAGAZINE_REFILLABLE - attack_speed = 3 // should make reloading less painful - icon_state_mini = "bullets" - -/obj/item/ammo_magazine/handful/repeater - name = "handful of heavy impact rifle bullet (.45-70 Government)" - icon_state = "bullet" - current_rounds = 8 - max_rounds = 8 - default_ammo = /datum/ammo/bullet/rifle/repeater - caliber = CALIBER_4570 - -/obj/item/ammo_magazine/handful/slug - name = "handful of shotgun slug (12 gauge)" - icon_state = "shotgun slug" - current_rounds = 5 - default_ammo = /datum/ammo/bullet/shotgun/slug - caliber = CALIBER_12G - -/obj/item/ammo_magazine/handful/buckshot - name = "handful of shotgun buckshot shells (12g)" - icon_state = "shotgun buckshot shell" - current_rounds = 5 - default_ammo = /datum/ammo/bullet/shotgun/buckshot - caliber = CALIBER_12G - -/obj/item/ammo_magazine/handful/flechette - name = "handful of shotgun flechette shells (12g)" - icon_state = "shotgun flechette shell" - current_rounds = 5 - default_ammo = /datum/ammo/bullet/shotgun/flechette - caliber = CALIBER_12G - -/obj/item/ammo_magazine/handful/incendiary - name = "handful of shotgun incendiary shells (12g)" - icon_state = "incendiary slug" - current_rounds = 5 - default_ammo = /datum/ammo/bullet/shotgun/incendiary - caliber = CALIBER_12G - -/obj/item/ammo_magazine/handful/micro_grenade - name = "handful of airburst micro grenades (10g)" - icon_state = "micro_grenade_airburst" - icon_state_mini = "40mm_cyan" - current_rounds = 3 - max_rounds = 3 - default_ammo = /datum/ammo/bullet/micro_rail/airburst - caliber = CALIBER_10G_RAIL - -/obj/item/ammo_magazine/handful/micro_grenade/dragonbreath - name = "handful of dragon's breath micro grenades (10g)" - icon_state = "micro_grenade_incendiary" - icon_state_mini = "40mm_orange" - default_ammo = /datum/ammo/bullet/micro_rail/dragonbreath - -/obj/item/ammo_magazine/handful/micro_grenade/cluster - name = "handful of clustermunition micro grenades (10g)" - icon_state = "micro_grenade_cluster" - icon_state_mini = "40mm_red" - default_ammo = /datum/ammo/bullet/micro_rail/cluster - -/obj/item/ammo_magazine/handful/micro_grenade/smoke_burst - name = "handful of smoke burst micro grenades (10g)" - icon_state = "micro_grenade_smoke" - icon_state_mini = "40mm_blue" - default_ammo = /datum/ammo/bullet/micro_rail/smoke_burst - -//----------------------------------------------------------------// - -/* -Doesn't do anything or hold anything anymore. -Generated per the various mags, and then changed based on the number of -casings. .dir is the main thing that controls the icon. It modifies -the icon_state to look like more casings are hitting the ground. -There are 8 directions, 8 bullets are possible so after that it tries to grab the next -icon_state while reseting the direction. After 16 casings, it just ignores new -ones. At that point there are too many anyway. Shells and bullets leave different -items, so they do not intersect. This is far more efficient than using Blend() or -Turn() or Shift() as there is virtually no overhead. ~N -*/ -/obj/item/ammo_casing - name = "spent casing" - desc = "Empty and useless now." - icon = 'icons/obj/items/casings.dmi' - icon_state = "casing_" - throwforce = 1 - w_class = WEIGHT_CLASS_TINY - layer = LOWER_ITEM_LAYER //Below other objects - dir = 1 //Always north when it spawns. - flags_atom = CONDUCT|DIRLOCK - var/current_casings = 1 //This is manipulated in the procs that use these. - var/max_casings = 16 - var/current_icon = 0 - var/number_of_states = 10 //How many variations of this item there are. - var/initial_icon_state = "cartridge_" //holder for icon_state so we can do random variations without effecting mapper visibility - -/obj/item/ammo_casing/Initialize(mapload) - . = ..() - pixel_x = rand(-2, 2) //Want to move them just a tad. - pixel_y = rand(-2, 2) - icon_state = initial_icon_state += "[rand(1, number_of_states)]" //Set the icon to it. - -//This does most of the heavy lifting. It updates the icon and name if needed - -/obj/item/ammo_casing/update_name(updates) - . = ..() - if(max_casings >= current_casings && current_casings == 2) - name += "s" //In case there is more than one. - -/obj/item/ammo_casing/update_icon_state() - . = ..() - if(max_casings >= current_casings) - if(round((current_casings-1)/8) > current_icon) - current_icon++ - icon_state += "_[current_icon]" - - var/base_direction = current_casings - (current_icon * 8) - setDir(base_direction + round(base_direction)/3) - switch(current_casings) - if(3 to 5) - w_class = WEIGHT_CLASS_SMALL //Slightly heavier. - if(9 to 10) - w_class = WEIGHT_CLASS_NORMAL //Can't put it in your pockets and stuff. - -///changes .dir to simulate new casings, also sets the new w_class -/obj/item/ammo_casing/proc/update_dir() - var/base_direction = current_casings - (current_icon * 8) - setDir(base_direction + round(base_direction)/3) - switch(current_casings) - if(3 to 5) - w_class = WEIGHT_CLASS_SMALL //Slightly heavier. - if(9 to 10) - w_class = WEIGHT_CLASS_NORMAL //Can't put it in your pockets and stuff. - -/obj/item/ammo_casing/update_icon() - update_dir() - return ..() - -//Making child objects so that locate() and istype() doesn't screw up. -/obj/item/ammo_casing/bullet - -/obj/item/ammo_casing/cartridge - name = "spent cartridge" - icon_state = "cartridge" - -/obj/item/ammo_casing/shell - name = "spent shell" - initial_icon_state = "shell_" - icon_state = "shell" - - - - -//Big ammo boxes - -/obj/item/big_ammo_box - name = "big ammo box (10x24mm)" - desc = "A large ammo box. It comes with a leather strap." - w_class = WEIGHT_CLASS_HUGE - icon = 'icons/obj/items/ammo.dmi' - icon_state = "big_ammo_box" - item_state = "big_ammo_box" - flags_equip_slot = ITEM_SLOT_BACK - base_icon_state = "big_ammo_box" - var/default_ammo = /datum/ammo/bullet/rifle - var/bullet_amount = 2400 - var/max_bullet_amount = 2400 - var/caliber = CALIBER_10X24_CASELESS - -/obj/item/big_ammo_box/update_icon_state() - . = ..() - if(bullet_amount) - icon_state = base_icon_state - return - icon_state = "[base_icon_state]_e" - -/obj/item/big_ammo_box/examine(mob/user) - . = ..() - if(bullet_amount) - . += "It contains [bullet_amount] round\s." - else - . += "It's empty." - -/obj/item/big_ammo_box/attackby(obj/item/I, mob/user, params) - . = ..() - - if(istype(I, /obj/item/ammo_magazine)) - var/obj/item/ammo_magazine/AM = I - if(!isturf(loc)) - to_chat(user, span_warning("[src] must be on the ground to be used.")) - return - if(AM.flags_magazine & MAGAZINE_REFILLABLE) - if(default_ammo != AM.default_ammo) - to_chat(user, span_warning("Those aren't the same rounds. Better not mix them up.")) - return - if(caliber != AM.caliber) - to_chat(user, span_warning("The rounds don't match up. Better not mix them up.")) - return - if(AM.current_rounds == AM.max_rounds) - to_chat(user, span_warning("[AM] is already full.")) - return - - if(!do_after(user, 15, NONE, src, BUSY_ICON_GENERIC)) - return - - playsound(loc, 'sound/weapons/guns/interact/revolver_load.ogg', 25, 1) - var/S = min(bullet_amount, AM.max_rounds - AM.current_rounds) - AM.current_rounds += S - bullet_amount -= S - AM.update_icon() - update_icon() - if(AM.current_rounds == AM.max_rounds) - to_chat(user, span_notice("You refill [AM].")) - else - to_chat(user, span_notice("You put [S] rounds in [AM].")) - else if(AM.flags_magazine & MAGAZINE_HANDFUL) - if(caliber != AM.caliber) - to_chat(user, span_warning("The rounds don't match up. Better not mix them up.")) - return - if(bullet_amount == max_bullet_amount) - to_chat(user, span_warning("[src] is full!")) - return - playsound(loc, 'sound/weapons/guns/interact/revolver_load.ogg', 25, 1) - var/S = min(AM.current_rounds, max_bullet_amount - bullet_amount) - AM.current_rounds -= S - bullet_amount += S - AM.update_icon() - to_chat(user, span_notice("You put [S] rounds in [src].")) - if(AM.current_rounds <= 0) - user.temporarilyRemoveItemFromInventory(AM) - qdel(AM) - -//explosion when using flamer procs. -/obj/item/big_ammo_box/fire_act(burn_level, flame_color) - if(QDELETED(src)) - return - if(!bullet_amount) - return - var/turf/explosion_loc = loc // we keep it so we don't runtime on src deletion - var/power = 5 - for(var/obj/item/big_ammo_box/box in explosion_loc) - if(!box.bullet_amount) - continue - power++ - qdel(box) - cell_explosion(explosion_loc, power, power) - -//Deployable shotgun ammo box -/obj/item/shotgunbox - name = "Slug Ammo Box" - desc = "A large, deployable ammo box." - icon = 'icons/obj/items/ammo.dmi' - icon_state = "ammoboxslug" - item_state = "ammoboxslug" - base_icon_state = "ammoboxslug" - w_class = WEIGHT_CLASS_HUGE - flags_equip_slot = ITEM_SLOT_BACK - ///Current stored rounds - var/current_rounds = 200 - ///Maximum stored rounds - var/max_rounds = 200 - ///Ammunition type - var/datum/ammo/ammo_type = /datum/ammo/bullet/shotgun/slug - ///Whether the box is deployed or not. - var/deployed = FALSE - ///Caliber of the rounds stored. - var/caliber = CALIBER_12G - - -/obj/item/shotgunbox/update_icon_state() - . = ..() - if(!deployed) - icon_state = "[initial(icon_state)]" - else if(current_rounds > 0) - icon_state = "[initial(icon_state)]_deployed" - else - icon_state = "[initial(icon_state)]_empty" - - -/obj/item/shotgunbox/attack_self(mob/user) - deployed = TRUE - update_icon() - user.dropItemToGround(src) - - -/obj/item/shotgunbox/MouseDrop(atom/over_object) - if(!deployed) - return - - if(!ishuman(over_object)) - return - - var/mob/living/carbon/human/H = over_object - if(H == usr && !H.incapacitated() && Adjacent(H) && H.put_in_hands(src)) - deployed = FALSE - update_icon() - - -/obj/item/shotgunbox/examine(mob/user) - . = ..() - . += "It contains [current_rounds] out of [max_rounds] shotgun shells." - - -/obj/item/shotgunbox/attack_hand(mob/living/user) - if(loc == user) - return ..() - - if(!deployed) - user.put_in_hands(src) - return - - if(current_rounds < 1) - to_chat(user, ("The [src] is empty.")) - return - - var/obj/item/ammo_magazine/handful/H = new - var/rounds = min(current_rounds, 5) - - H.generate_handful(ammo_type, caliber, rounds, initial(ammo_type.handful_amount)) - current_rounds -= rounds - - user.put_in_hands(H) - to_chat(user, span_notice("You grab [rounds] round\s from [src].")) - update_icon() - - -/obj/item/shotgunbox/attackby(obj/item/I, mob/user, params) - . = ..() - - if(!istype(I, /obj/item/ammo_magazine/handful)) - return - - var/obj/item/ammo_magazine/handful/H = I - - if(!deployed) - to_chat(user, span_warning("[src] must be deployed on the ground to be refilled.")) - return - - if(H.default_ammo != ammo_type) - to_chat(user, span_warning("That's not the right kind of ammo.")) - return - - if(current_rounds == max_rounds) - to_chat(user, span_warning("The [src] is already full.")) - return - - current_rounds = min(current_rounds + H.current_rounds, max_rounds) - qdel(H) - update_icon() - - -/obj/item/big_ammo_box/ap - name = "big ammo box (10x24mm AP)" - icon_state = "big_ammo_box_ap" - base_icon_state = "big_ammo_box_ap" - default_ammo = /datum/ammo/bullet/rifle/ap - bullet_amount = 400 //AP is OP - max_bullet_amount = 400 - -/obj/item/big_ammo_box/smg - name = "big ammo box (10x20mm)" - caliber = CALIBER_10X20 - icon_state = "big_ammo_box_m25" - base_icon_state = "big_ammo_box_m25" - default_ammo = /datum/ammo/bullet/smg - bullet_amount = 4500 - max_bullet_amount = 4500 - caliber = CALIBER_10X20_CASELESS - -/obj/item/shotgunbox/buckshot - name = "Buckshot Ammo Box" - icon_state = "ammoboxbuckshot" - item_state = "ammoboxbuckshot" - base_icon_state = "ammoboxbuckshot" - ammo_type = /datum/ammo/bullet/shotgun/buckshot - -/obj/item/shotgunbox/flechette - name = "Flechette Ammo Box" - icon_state = "ammoboxflechette" - item_state = "ammoboxflechette" - base_icon_state = "ammoboxflechette" - ammo_type = /datum/ammo/bullet/shotgun/flechette - -/obj/item/shotgunbox/clf_heavyrifle - name = "big ammo box (14.5mm API)" - caliber = CALIBER_14X5 - icon_state = "ammobox_145" - item_state = "ammobox_145" - base_icon_state = "ammobox_145" - ammo_type = /datum/ammo/bullet/sniper/clf_heavyrifle - -/obj/item/shotgunbox/tracker - name = "Tracking Ammo Box" - icon_state = "ammoboxtracking" - item_state = "ammoboxtracking" - base_icon_state = "ammoboxtracking" - ammo_type = /datum/ammo/bullet/shotgun/tracker - -/obj/item/big_ammo_box/mg - name = "big ammo box (10x26mm)" - default_ammo = /datum/ammo/bullet/rifle/machinegun - caliber = CALIBER_10x26_CASELESS - bullet_amount = 3200 //a backpack holds 8 MG-60 box mags, which is 1600 rounds - max_bullet_amount = 3200 + return 100.0 * current_rounds / max_rounds diff --git a/code/modules/projectiles/attachables/foldable.dm b/code/modules/projectiles/attachables/foldable.dm index 7cd6cdc94aa..8e76cc5cb07 100644 --- a/code/modules/projectiles/attachables/foldable.dm +++ b/code/modules/projectiles/attachables/foldable.dm @@ -61,9 +61,6 @@ if(master_gun) apply_modifiers(master_gun, user, !folded) - for(var/X in master_gun.actions) - var/datum/action/A = X - A.update_button_icon() return TRUE diff --git a/code/modules/projectiles/attachables/rail.dm b/code/modules/projectiles/attachables/rail.dm index e8083e12ad6..98507e5e8f8 100644 --- a/code/modules/projectiles/attachables/rail.dm +++ b/code/modules/projectiles/attachables/rail.dm @@ -76,10 +76,6 @@ else return - for(var/X in master_gun.actions) - var/datum/action/A = X - A.update_button_icon() - update_icon() /obj/item/attachable/flashlight/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/projectiles/attachables/underbarrel.dm b/code/modules/projectiles/attachables/underbarrel.dm index 6a346ae1b4d..c4879773cbf 100644 --- a/code/modules/projectiles/attachables/underbarrel.dm +++ b/code/modules/projectiles/attachables/underbarrel.dm @@ -59,13 +59,6 @@ flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION attachment_action_type = /datum/action/item_action/toggle -/obj/item/attachable/lace/t500 - name = "R-500 lace" - icon = 'icons/Marine/attachments_64.dmi' - slot = ATTACHMENT_SLOT_STOCK - pixel_shift_x = 0 - pixel_shift_y = 0 - /obj/item/attachable/lace/activate(mob/living/user, turn_off) if(lace_deployed) REMOVE_TRAIT(master_gun, TRAIT_NODROP, PISTOL_LACE_TRAIT) @@ -87,13 +80,16 @@ lace_deployed = !lace_deployed - for(var/i in master_gun.actions) - var/datum/action/action_to_update = i - action_to_update.update_button_icon() - update_icon() return TRUE +/obj/item/attachable/lace/t500 + name = "R-500 lace" + icon = 'icons/Marine/attachments_64.dmi' + slot = ATTACHMENT_SLOT_STOCK + pixel_shift_x = 0 + pixel_shift_y = 0 + /obj/item/attachable/burstfire_assembly name = "burst fire assembly" desc = "A mechanism re-assembly kit that allows for automatic fire, or more shots per burst if the weapon already has the ability." diff --git a/code/modules/projectiles/big_ammo_box.dm b/code/modules/projectiles/big_ammo_box.dm new file mode 100644 index 00000000000..898b2609859 --- /dev/null +++ b/code/modules/projectiles/big_ammo_box.dm @@ -0,0 +1,246 @@ +/obj/item/big_ammo_box + name = "big ammo box (10x24mm)" + desc = "A large ammo box. It comes with a leather strap." + w_class = WEIGHT_CLASS_HUGE + icon = 'icons/obj/items/ammo/box.dmi' + icon_state = "big_ammo_box" + item_state = "big_ammo_box" + flags_equip_slot = ITEM_SLOT_BACK + base_icon_state = "big_ammo_box" + ///Ammunition type + var/default_ammo = /datum/ammo/bullet/rifle + ///Current stored rounds + var/bullet_amount = 2400 + ///Maximum stored rounds + var/max_bullet_amount = 2400 + ///Caliber of the rounds stored. + var/caliber = CALIBER_10X24_CASELESS + +/obj/item/big_ammo_box/update_icon_state() + . = ..() + if(bullet_amount) + icon_state = base_icon_state + return + icon_state = "[base_icon_state]_e" + +/obj/item/big_ammo_box/examine(mob/user) + . = ..() + if(bullet_amount) + . += "It contains [bullet_amount] round\s." + else + . += "It's empty." + +/obj/item/big_ammo_box/attackby(obj/item/I, mob/user, params) + . = ..() + + if(istype(I, /obj/item/ammo_magazine)) + var/obj/item/ammo_magazine/AM = I + if(!isturf(loc)) + to_chat(user, span_warning("[src] must be on the ground to be used.")) + return + if(AM.flags_magazine & MAGAZINE_REFILLABLE) + if(default_ammo != AM.default_ammo) + to_chat(user, span_warning("Those aren't the same rounds. Better not mix them up.")) + return + if(caliber != AM.caliber) + to_chat(user, span_warning("The rounds don't match up. Better not mix them up.")) + return + if(AM.current_rounds == AM.max_rounds) + to_chat(user, span_warning("[AM] is already full.")) + return + + if(!do_after(user, 15, NONE, src, BUSY_ICON_GENERIC)) + return + + playsound(loc, 'sound/weapons/guns/interact/revolver_load.ogg', 25, 1) + var/S = min(bullet_amount, AM.max_rounds - AM.current_rounds) + AM.current_rounds += S + bullet_amount -= S + AM.update_icon() + update_icon() + if(AM.current_rounds == AM.max_rounds) + to_chat(user, span_notice("You refill [AM].")) + else + to_chat(user, span_notice("You put [S] rounds in [AM].")) + else if(AM.flags_magazine & MAGAZINE_HANDFUL) + if(caliber != AM.caliber) + to_chat(user, span_warning("The rounds don't match up. Better not mix them up.")) + return + if(bullet_amount == max_bullet_amount) + to_chat(user, span_warning("[src] is full!")) + return + playsound(loc, 'sound/weapons/guns/interact/revolver_load.ogg', 25, 1) + var/S = min(AM.current_rounds, max_bullet_amount - bullet_amount) + AM.current_rounds -= S + bullet_amount += S + AM.update_icon() + to_chat(user, span_notice("You put [S] rounds in [src].")) + if(AM.current_rounds <= 0) + user.temporarilyRemoveItemFromInventory(AM) + qdel(AM) + +//explosion when using flamer procs. +/obj/item/big_ammo_box/fire_act(burn_level, flame_color) + if(QDELETED(src)) + return + if(!bullet_amount) + return + var/turf/explosion_loc = loc // we keep it so we don't runtime on src deletion + var/power = 5 + for(var/obj/item/big_ammo_box/box in explosion_loc) + if(!box.bullet_amount) + continue + power++ + qdel(box) + cell_explosion(explosion_loc, power, power) + +/obj/item/big_ammo_box/ap + name = "big ammo box (10x24mm AP)" + icon_state = "big_ammo_box_ap" + base_icon_state = "big_ammo_box_ap" + default_ammo = /datum/ammo/bullet/rifle/ap + bullet_amount = 400 //AP is OP + max_bullet_amount = 400 + +/obj/item/big_ammo_box/smg + name = "big ammo box (10x20mm)" + caliber = CALIBER_10X20 + icon_state = "big_ammo_box_m25" + base_icon_state = "big_ammo_box_m25" + default_ammo = /datum/ammo/bullet/smg + bullet_amount = 4500 + max_bullet_amount = 4500 + caliber = CALIBER_10X20_CASELESS + +/obj/item/big_ammo_box/mg + name = "big ammo box (10x26mm)" + default_ammo = /datum/ammo/bullet/rifle/machinegun + caliber = CALIBER_10X26_CASELESS + bullet_amount = 3200 //a backpack holds 8 MG-60 box mags, which is 1600 rounds + max_bullet_amount = 3200 + +//Deployable shotgun ammo box +/obj/item/shotgunbox + name = "Slug Ammo Box" + desc = "A large, deployable ammo box." + icon = 'icons/obj/items/ammo/box.dmi' + icon_state = "ammoboxslug" + item_state = "ammoboxslug" + base_icon_state = "ammoboxslug" + w_class = WEIGHT_CLASS_HUGE + flags_equip_slot = ITEM_SLOT_BACK + ///Current stored rounds + var/current_rounds = 200 + ///Maximum stored rounds + var/max_rounds = 200 + ///Ammunition type + var/datum/ammo/ammo_type = /datum/ammo/bullet/shotgun/slug + ///Whether the box is deployed or not. + var/deployed = FALSE + ///Caliber of the rounds stored. + var/caliber = CALIBER_12G + +/obj/item/shotgunbox/update_icon_state() + . = ..() + if(!deployed) + icon_state = "[initial(icon_state)]" + else if(current_rounds > 0) + icon_state = "[initial(icon_state)]_deployed" + else + icon_state = "[initial(icon_state)]_empty" + +/obj/item/shotgunbox/attack_self(mob/user) + deployed = TRUE + update_icon() + user.dropItemToGround(src) + +/obj/item/shotgunbox/MouseDrop(atom/over_object) + if(!deployed) + return + + if(!ishuman(over_object)) + return + + var/mob/living/carbon/human/H = over_object + if(H == usr && !H.incapacitated() && Adjacent(H) && H.put_in_hands(src)) + deployed = FALSE + update_icon() + +/obj/item/shotgunbox/examine(mob/user) + . = ..() + . += "It contains [current_rounds] out of [max_rounds] shotgun shells." + +/obj/item/shotgunbox/attack_hand(mob/living/user) + if(loc == user) + return ..() + + if(!deployed) + user.put_in_hands(src) + return + + if(current_rounds < 1) + to_chat(user, ("The [src] is empty.")) + return + + var/obj/item/ammo_magazine/handful/H = new + var/rounds = min(current_rounds, 5) + + H.generate_handful(ammo_type, caliber, rounds, initial(ammo_type.handful_amount)) + current_rounds -= rounds + + user.put_in_hands(H) + to_chat(user, span_notice("You grab [rounds] round\s from [src].")) + update_icon() + +/obj/item/shotgunbox/attackby(obj/item/I, mob/user, params) + . = ..() + + if(!istype(I, /obj/item/ammo_magazine/handful)) + return + + var/obj/item/ammo_magazine/handful/H = I + + if(!deployed) + to_chat(user, span_warning("[src] must be deployed on the ground to be refilled.")) + return + + if(H.default_ammo != ammo_type) + to_chat(user, span_warning("That's not the right kind of ammo.")) + return + + if(current_rounds == max_rounds) + to_chat(user, span_warning("The [src] is already full.")) + return + + current_rounds = min(current_rounds + H.current_rounds, max_rounds) + qdel(H) + update_icon() + +/obj/item/shotgunbox/buckshot + name = "Buckshot Ammo Box" + icon_state = "ammoboxbuckshot" + item_state = "ammoboxbuckshot" + base_icon_state = "ammoboxbuckshot" + ammo_type = /datum/ammo/bullet/shotgun/buckshot + +/obj/item/shotgunbox/flechette + name = "Flechette Ammo Box" + icon_state = "ammoboxflechette" + item_state = "ammoboxflechette" + base_icon_state = "ammoboxflechette" + ammo_type = /datum/ammo/bullet/shotgun/flechette + +/obj/item/shotgunbox/clf_heavyrifle + name = "big ammo box (14.5mm API)" + caliber = CALIBER_14X5 + icon_state = "ammobox_145" + item_state = "ammobox_145" + base_icon_state = "ammobox_145" + ammo_type = /datum/ammo/bullet/sniper/clf_heavyrifle + +/obj/item/shotgunbox/tracker + name = "Tracking Ammo Box" + icon_state = "ammoboxtracking" + item_state = "ammoboxtracking" + base_icon_state = "ammoboxtracking" + ammo_type = /datum/ammo/bullet/shotgun/tracker diff --git a/code/modules/projectiles/gun_system.dm b/code/modules/projectiles/gun_system.dm index 79935f3b1b3..722749767d0 100644 --- a/code/modules/projectiles/gun_system.dm +++ b/code/modules/projectiles/gun_system.dm @@ -504,16 +504,8 @@ SIGNAL_HANDLER set_gun_user(null) -/obj/item/weapon/gun/update_icon() +/obj/item/weapon/gun/update_icon(updates=ALL) . = ..() - - for(var/datum/action/action AS in actions) - action.update_button_icon() - - if(master_gun) - for(var/datum/action/action AS in master_gun.actions) - action.update_button_icon() - update_item_state() /obj/item/weapon/gun/update_icon_state() diff --git a/code/modules/projectiles/guns/mounted.dm b/code/modules/projectiles/guns/mounted.dm index 47f2855b267..1b13d0d5659 100644 --- a/code/modules/projectiles/guns/mounted.dm +++ b/code/modules/projectiles/guns/mounted.dm @@ -402,7 +402,7 @@ icon = 'icons/Marine/marine-mmg.dmi' icon_state = "t27" item_state = "t27" - caliber = CALIBER_10x27_CASELESS // codex + caliber = CALIBER_10X27_CASELESS // codex max_shells = 150 //codex force = 40 aim_slowdown = 1.2 diff --git a/code/modules/projectiles/guns/revolvers.dm b/code/modules/projectiles/guns/revolvers.dm index dca92f6c726..8fdc32db8d4 100644 --- a/code/modules/projectiles/guns/revolvers.dm +++ b/code/modules/projectiles/guns/revolvers.dm @@ -334,7 +334,7 @@ icon_state = "t76" item_state = "t76" fire_animation = "t76_fire" - caliber = CALIBER_12x7 //codex + caliber = CALIBER_12X7 //codex max_chamber_items = 5 //codex default_ammo_type = /obj/item/ammo_magazine/revolver/standard_magnum allowed_ammo_types = list(/obj/item/ammo_magazine/revolver/standard_magnum) diff --git a/code/modules/projectiles/guns/rifles.dm b/code/modules/projectiles/guns/rifles.dm index 0f4d5b30f73..dd73350c577 100644 --- a/code/modules/projectiles/guns/rifles.dm +++ b/code/modules/projectiles/guns/rifles.dm @@ -238,7 +238,7 @@ cocked_sound = 'sound/weapons/guns/dmr/DMR-37/DMR37_boltpull.ogg' silenced_sound = 'sound/weapons/guns/dmr/DMR-37/DMR37_SIL.ogg' wield_sound = 'sound/weapons/guns/dmr/Deploy_Wave_DMR.ogg' - caliber = CALIBER_10x27_CASELESS //codex + caliber = CALIBER_10X27_CASELESS //codex aim_slowdown = 0.75 wield_delay = 0.8 SECONDS force = 20 @@ -321,7 +321,7 @@ cocked_sound = 'sound/weapons/guns/dmr/BR-64/BR64_boltpull.ogg' silenced_sound = 'sound/weapons/guns/dmr/BR-64/BR64_SIL.ogg' wield_sound = 'sound/weapons/guns/dmr/Deploy_Wave_DMR.ogg' - caliber = CALIBER_10x265_CASELESS //codex + caliber = CALIBER_10X265_CASELESS //codex aim_slowdown = 0.55 wield_delay = 0.7 SECONDS force = 20 @@ -993,7 +993,7 @@ inhand_x_dimension = 64 inhand_y_dimension = 32 - caliber = CALIBER_10x26_CASELESS //codex + caliber = CALIBER_10X26_CASELESS //codex max_shells = 200 //codex force = 35 aim_slowdown = 1.2 @@ -1319,7 +1319,7 @@ desc = "The Raummetall-KT SG-29 is the TGMC's current standard IFF-capable medium machine gun. It's known for its ability to lay down heavy fire support very well. It is generally used when someone wants to hold a position or provide fire support. Requires special training and it cannot turn off IFF. It uses 10x26mm ammunition." icon_state = "sg29" item_state = "sg29" - caliber = CALIBER_10x26_CASELESS //codex + caliber = CALIBER_10X26_CASELESS //codex max_shells = 300 //codex force = 30 aim_slowdown = 0.95 @@ -1355,7 +1355,8 @@ starting_attachment_types = list(/obj/item/attachable/stock/sgstock, /obj/item/attachable/sgbarrel) gun_skill_category = SKILL_SMARTGUN //Uses SG skill for the penalties. attachable_offset = list("muzzle_x" = 42, "muzzle_y" = 17,"rail_x" = 15, "rail_y" = 21, "under_x" = 24, "under_y" = 14, "stock_x" = 12, "stock_y" = 13) - fire_delay = 0.2 SECONDS + + fire_delay = 0.15 SECONDS burst_amount = 0 accuracy_mult_unwielded = 0.5 accuracy_mult = 1.1 @@ -1383,7 +1384,7 @@ icon = 'icons/Marine/gun64.dmi' icon_state = "sg62" item_state = "sg62" - caliber = CALIBER_10x27_CASELESS //codex + caliber = CALIBER_10X27_CASELESS //codex max_shells = 40 //codex aim_slowdown = 0.55 wield_delay = 0.65 SECONDS @@ -1431,7 +1432,7 @@ icon_state = "sg153" icon = 'icons/Marine/gun64.dmi' fire_sound = 'sound/weapons/guns/fire/spottingrifle.ogg' - caliber = CALIBER_12x7 + caliber = CALIBER_12X7 slot = ATTACHMENT_SLOT_UNDER max_shells = 5 default_ammo_type =/obj/item/ammo_magazine/rifle/sg153 @@ -2289,7 +2290,7 @@ inhand_x_dimension = 64 inhand_y_dimension = 32 - caliber = CALIBER_10x26_CASELESS + caliber = CALIBER_10X26_CASELESS max_shells = 200 force = 35 wield_delay = 1.5 SECONDS @@ -2361,7 +2362,7 @@ dry_fire_sound = 'sound/weapons/guns/fire/m41a_empty.ogg' unload_sound = 'sound/weapons/guns/interact/fal_unload.ogg' reload_sound = 'sound/weapons/guns/interact/fal_reload.ogg' - caliber = CALIBER_10x27_CASELESS //codex + caliber = CALIBER_10X27_CASELESS //codex aim_slowdown = 0.8 wield_delay = 0.85 SECONDS force = 20 @@ -2673,7 +2674,7 @@ slot_s_store_str = 'icons/mob/suit_slot.dmi', slot_back_str = 'icons/mob/clothing/back.dmi', ) - caliber = CALIBER_10x26_CASELESS //codex + caliber = CALIBER_10X26_CASELESS //codex max_shells = 80 //codex force = 20 aim_slowdown = 0.5 diff --git a/code/modules/projectiles/guns/specialist.dm b/code/modules/projectiles/guns/specialist.dm index 18131866893..309ddcf5252 100644 --- a/code/modules/projectiles/guns/specialist.dm +++ b/code/modules/projectiles/guns/specialist.dm @@ -427,7 +427,7 @@ Note that this means that snipers will have a slowdown of 3, due to the scope item_state = "minigun_sg" fire_animation = "minigun_sg_fire" max_shells = 2000 //codex - caliber = CALIBER_10x26_CASELESS //codex + caliber = CALIBER_10X26_CASELESS //codex allowed_ammo_types = list(/obj/item/ammo_magazine/minigun_powerpack/smartgun) wield_delay = 1.5 SECONDS flags_gun_features = GUN_AMMO_COUNTER|GUN_WIELDED_FIRING_ONLY|GUN_IFF|GUN_SMOKE_PARTICLES diff --git a/code/modules/projectiles/handful.dm b/code/modules/projectiles/handful.dm new file mode 100644 index 00000000000..0698a2be023 --- /dev/null +++ b/code/modules/projectiles/handful.dm @@ -0,0 +1,75 @@ +/obj/item/ammo_magazine/handful + name = "generic handful of bullets or shells" + desc = "A handful of rounds to reload on the go." + flags_equip_slot = null // It only fits into pockets and such. + w_class = WEIGHT_CLASS_SMALL + current_rounds = 1 // So it doesn't get autofilled for no reason. + max_rounds = 5 // For shotguns, though this will be determined by the handful type when generated. + flags_atom = CONDUCT|DIRLOCK + flags_magazine = MAGAZINE_HANDFUL|MAGAZINE_REFILLABLE + attack_speed = 3 // should make reloading less painful + icon = 'icons/obj/items/ammo/handful.dmi' + icon_state_mini = "bullets" + +/obj/item/ammo_magazine/handful/repeater + name = "handful of heavy impact rifle bullet (.45-70 Government)" + icon_state = "bullet" + current_rounds = 8 + max_rounds = 8 + default_ammo = /datum/ammo/bullet/rifle/repeater + caliber = CALIBER_4570 + +/obj/item/ammo_magazine/handful/slug + name = "handful of shotgun slug (12 gauge)" + icon_state = "shotgun slug" + current_rounds = 5 + default_ammo = /datum/ammo/bullet/shotgun/slug + caliber = CALIBER_12G + +/obj/item/ammo_magazine/handful/buckshot + name = "handful of shotgun buckshot shells (12g)" + icon_state = "shotgun buckshot shell" + current_rounds = 5 + default_ammo = /datum/ammo/bullet/shotgun/buckshot + caliber = CALIBER_12G + +/obj/item/ammo_magazine/handful/flechette + name = "handful of shotgun flechette shells (12g)" + icon_state = "shotgun flechette shell" + current_rounds = 5 + default_ammo = /datum/ammo/bullet/shotgun/flechette + caliber = CALIBER_12G + +/obj/item/ammo_magazine/handful/incendiary + name = "handful of shotgun incendiary shells (12g)" + icon_state = "incendiary slug" + current_rounds = 5 + default_ammo = /datum/ammo/bullet/shotgun/incendiary + caliber = CALIBER_12G + +/obj/item/ammo_magazine/handful/micro_grenade + name = "handful of airburst micro grenades (10g)" + icon_state = "micro_grenade_airburst" + icon_state_mini = "40mm_cyan" + current_rounds = 3 + max_rounds = 3 + default_ammo = /datum/ammo/bullet/micro_rail/airburst + caliber = CALIBER_10G_RAIL + +/obj/item/ammo_magazine/handful/micro_grenade/dragonbreath + name = "handful of dragon's breath micro grenades (10g)" + icon_state = "micro_grenade_incendiary" + icon_state_mini = "40mm_orange" + default_ammo = /datum/ammo/bullet/micro_rail/dragonbreath + +/obj/item/ammo_magazine/handful/micro_grenade/cluster + name = "handful of clustermunition micro grenades (10g)" + icon_state = "micro_grenade_cluster" + icon_state_mini = "40mm_red" + default_ammo = /datum/ammo/bullet/micro_rail/cluster + +/obj/item/ammo_magazine/handful/micro_grenade/smoke_burst + name = "handful of smoke burst micro grenades (10g)" + icon_state = "micro_grenade_smoke" + icon_state_mini = "40mm_blue" + default_ammo = /datum/ammo/bullet/micro_rail/smoke_burst diff --git a/code/modules/projectiles/magazines/energy.dm b/code/modules/projectiles/magazines/energy.dm index 50009190cb8..260e4d93642 100644 --- a/code/modules/projectiles/magazines/energy.dm +++ b/code/modules/projectiles/magazines/energy.dm @@ -3,7 +3,7 @@ /obj/item/cell/lasgun name = "\improper lasgun Battery" desc = "A specialized high density battery used to power lasguns." - icon = 'icons/obj/items/ammo.dmi' + icon = 'icons/obj/items/ammo/energy.dmi' item_icons = list( slot_l_hand_str = 'icons/mob/inhands/weapons/ammo_left.dmi', slot_r_hand_str = 'icons/mob/inhands/weapons/ammo_right.dmi', @@ -75,7 +75,6 @@ /obj/item/cell/lasgun/volkite name = "\improper volkite energy cell" desc = "A specialized high density battery used to power volkite weaponry." - icon = 'icons/obj/items/ammo.dmi' icon_state = "volkite" maxcharge = 1440 w_class = WEIGHT_CLASS_NORMAL @@ -86,7 +85,6 @@ /obj/item/cell/lasgun/volkite/small name = "\improper compact volkite energy cell" desc = "A specialized compact battery used to power the smallest volkite weaponry." - icon = 'icons/obj/items/ammo.dmi' icon_state = "volkite_small" maxcharge = 540 w_class = WEIGHT_CLASS_SMALL @@ -95,7 +93,6 @@ /obj/item/cell/lasgun/volkite/turret name = "\improper volkite nuclear energy cell" desc = "A nuclear powered battery designed for certain heavy SOM machinery like sentries. Slowly charges over time." - icon = 'icons/obj/items/ammo.dmi' icon_state = "volkite_turret" maxcharge = 1800 w_class = WEIGHT_CLASS_NORMAL diff --git a/code/modules/projectiles/magazines/flamer.dm b/code/modules/projectiles/magazines/flamer.dm index 83d2334e811..88871609779 100644 --- a/code/modules/projectiles/magazines/flamer.dm +++ b/code/modules/projectiles/magazines/flamer.dm @@ -1,11 +1,9 @@ - - //Flame thrower. - /obj/item/ammo_magazine/flamer_tank name = "incinerator tank" desc = "A fuel tank of usually ultra thick napthal, a sticky combustable liquid chemical, for use in the FL-240 incinerator unit. Handle with care." icon_state = "flametank" + icon = 'icons/obj/items/ammo/flamer.dmi' max_rounds = 50 //Per turf. current_rounds = 50 reload_delay = 2 SECONDS diff --git a/code/modules/projectiles/magazines/misc.dm b/code/modules/projectiles/magazines/misc.dm index 35c9218884d..401f2426094 100644 --- a/code/modules/projectiles/magazines/misc.dm +++ b/code/modules/projectiles/magazines/misc.dm @@ -3,6 +3,7 @@ /obj/item/ammo_magazine/packet name = "box of some kind of ammo" desc = "A packet containing some kind of ammo." + icon = 'icons/obj/items/ammo/packet.dmi' icon_state_mini = "ammo_packet" w_class = WEIGHT_CLASS_NORMAL @@ -62,7 +63,7 @@ /obj/item/ammo_magazine/packet/p10x265mm name = "box of 10x26.5mm" desc = "A box containing 100 rounds of 10x26.5mm caseless." - caliber = CALIBER_10x265_CASELESS + caliber = CALIBER_10X265_CASELESS icon_state = "box_10x265mm" default_ammo = /datum/ammo/bullet/rifle/br64 current_rounds = 100 @@ -71,7 +72,7 @@ /obj/item/ammo_magazine/packet/p10x27mm name = "box of 10x27mm" desc = "A box containing 100 rounds of 10x27mm caseless." - caliber = CALIBER_10x27_CASELESS + caliber = CALIBER_10X27_CASELESS icon_state = "box_10x27mm" default_ammo = /datum/ammo/bullet/rifle/dmr37 current_rounds = 100 @@ -110,7 +111,7 @@ desc = "A hefty container stuffed to the absolute brim with 500 rounds for the SG-85 powerpack." icon_state = "box_smartminigun" default_ammo = /datum/ammo/bullet/smart_minigun - caliber = CALIBER_10x26_CASELESS + caliber = CALIBER_10X26_CASELESS current_rounds = 500 max_rounds = 500 w_class = WEIGHT_CLASS_NORMAL @@ -249,7 +250,7 @@ name = "packet of 10x26mm" desc = "A packet containing 100 rounds of 10x26mm caseless." icon_state = "box_10x26mm" - caliber = CALIBER_10x26_CASELESS + caliber = CALIBER_10X26_CASELESS default_ammo = /datum/ammo/bullet/rifle/machinegun w_class = WEIGHT_CLASS_SMALL current_rounds = 100 @@ -289,7 +290,6 @@ /obj/item/ammo_magazine/packet/long_special name = "box of .44 Long Special" desc = "A packet containing 40 rounds of .44 Long Special." - icon = 'icons/obj/items/ammo.dmi' icon_state = "44LSbox" default_ammo = /datum/ammo/bullet/revolver/rifle caliber = CALIBER_44LS @@ -300,10 +300,9 @@ /obj/item/ammo_magazine/packet/t25 name = "box of 10x26mm high-pressure" desc = "A box containing 300 rounds of 10x26mm 'HP' caseless tuned for a smartgun." - icon = 'icons/obj/items/ammo.dmi' icon_state = "box_t25" default_ammo = /datum/ammo/bullet/rifle/t25 - caliber = CALIBER_10x26_CASELESS + caliber = CALIBER_10X26_CASELESS current_rounds = 300 max_rounds = 300 @@ -319,7 +318,6 @@ /obj/item/ammo_magazine/packet/t500 name = "packet of .500 Nigro Express" - icon = 'icons/obj/items/ammo.dmi' icon_state = "boxt500" default_ammo = /datum/ammo/bullet/revolver/t500 caliber = CALIBER_500 @@ -340,10 +338,9 @@ /obj/item/ammo_magazine/packet/standard_magnum name = "packet of .12x7mm" - icon = 'icons/obj/items/ammo.dmi' icon_state = "box_t76" default_ammo = /datum/ammo/bullet/revolver/t76 - caliber = CALIBER_12x7 + caliber = CALIBER_12X7 w_class = WEIGHT_CLASS_SMALL current_rounds = 50 max_rounds = 50 @@ -387,22 +384,19 @@ /obj/item/ammo_magazine/packet/p10x265mm/ap desc = "A box containing 100 armor piercing rounds of 10x26.5mm caseless." - icon = 'icons/obj/items/ammo.dmi' icon_state = "box_10x265mm_ap" default_ammo = /datum/ammo/bullet/rifle/br64/ap /obj/item/ammo_magazine/packet/p10x20mm/ap desc = "A packet containing 125 rounds of 10x20mm caseless." - icon = 'icons/obj/items/ammo.dmi' icon_state = "box_10x20mm_ap" default_ammo = /datum/ammo/bullet/smg/ap /obj/item/ammo_magazine/packet/sg62 name = "box of 10x27mm" desc = "A box containing 200 rounds of 10x27mm caseless." - icon = 'icons/obj/items/ammo.dmi' icon_state = "box_sg62" default_ammo = /datum/ammo/bullet/sg62 - caliber = CALIBER_10x27_CASELESS + caliber = CALIBER_10X27_CASELESS current_rounds = 200 max_rounds = 200 diff --git a/code/modules/projectiles/magazines/mounted.dm b/code/modules/projectiles/magazines/mounted.dm index 8b169740b72..c01517bb952 100644 --- a/code/modules/projectiles/magazines/mounted.dm +++ b/code/modules/projectiles/magazines/mounted.dm @@ -48,7 +48,7 @@ icon_state = "mag" icon_state_mini = "mag_drum_big_armygreen" flags_magazine = NONE - caliber = CALIBER_10x27_CASELESS + caliber = CALIBER_10X27_CASELESS max_rounds = 150 default_ammo = /datum/ammo/bullet/rifle/heavy reload_delay = 1 SECONDS @@ -95,7 +95,6 @@ icon_state = "ags_mag_pgas" default_ammo = /datum/ammo/grenade_container/agls37/tanglefoot - /obj/item/ammo_magazine/at36 name = "AT-36 AP-HE shell (37mm Shell)" desc = "A 37mm shell for light anti tank guns. Will penetrate walls and fortifications, before hitting a target and exploding, has less payload and punch than usual rounds." @@ -141,7 +140,7 @@ name = "MG-2005 box magazine (7.62x51mm)" desc = "A box of 1000 rounds for the MG-2005 mounted minigun." w_class = WEIGHT_CLASS_BULKY - icon = 'icons/obj/items/ammo.dmi' + icon = 'icons/obj/items/ammo/stationary.dmi' icon_state = "minigun" flags_magazine = NONE caliber = CALIBER_762X51 diff --git a/code/modules/projectiles/magazines/pistols.dm b/code/modules/projectiles/magazines/pistols.dm index a12a25591ad..416e6545abf 100644 --- a/code/modules/projectiles/magazines/pistols.dm +++ b/code/modules/projectiles/magazines/pistols.dm @@ -32,35 +32,37 @@ name = "\improper RT-3 magazine (9mm)" desc = "A pistol magazine." caliber = CALIBER_9X19 + icon = 'icons/obj/items/ammo/pistol.dmi' icon_state = "m4a3" max_rounds = 14 w_class = WEIGHT_CLASS_SMALL default_ammo = /datum/ammo/bullet/pistol icon_state_mini = "mag_pistol_orange" + ammo_band_icon = "m4a3_band" /obj/item/ammo_magazine/pistol/hp name = "\improper M4A3 hollowpoint magazine (9mm)" - icon_state = "m4a3_hp" default_ammo = /datum/ammo/bullet/pistol/hollow icon_state_mini = "mag_pistol_blue" + ammo_band_color = AMMO_BAND_COLOR_HOLLOWPOINT /obj/item/ammo_magazine/pistol/ap name = "\improper M4A3 AP magazine (9mm)" - icon_state = "m4a3_ap" default_ammo = /datum/ammo/bullet/pistol/ap icon_state_mini = "mag_pistol_green" + ammo_band_color = AMMO_BAND_COLOR_AP /obj/item/ammo_magazine/pistol/incendiary name = "\improper M4A3 incendiary magazine (9mm)" - icon_state = "m4a3_incendiary" default_ammo = /datum/ammo/bullet/pistol/incendiary icon_state_mini = "mag_pistol_red" + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY /obj/item/ammo_magazine/pistol/extended name = "\improper M4A3 extended magazine (9mm)" max_rounds = 24 - icon_state = "m4a3_ext" icon_state_mini = "mag_pistol_yellow" + ammo_band_color = AMMO_BAND_COLOR_EXTENDED //------------------------------------------------------- //P-1911 @@ -218,18 +220,20 @@ icon_state = "v11" icon_state_mini = "mag_pistol_normal" max_rounds = 18 + ammo_band_icon = "v11_band" /obj/item/ammo_magazine/pistol/som/incendiary name = "\improper V-11 incendiary magazine (9mm)" - icon_state = "v11_incend" default_ammo = /datum/ammo/bullet/pistol/incendiary icon_state_mini = "mag_pistol_red" + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY /obj/item/ammo_magazine/pistol/som/extended name = "\improper V-11 extended magazine (9mm)" max_rounds = 30 icon_state = "v11_extended" icon_state_mini = "mag_pistol_yellow" + ammo_band_color = AMMO_BAND_COLOR_EXTENDED //------------------------------------------------------- //PL-5 diff --git a/code/modules/projectiles/magazines/revolvers.dm b/code/modules/projectiles/magazines/revolvers.dm index 75de1d988cd..b790b4617c3 100644 --- a/code/modules/projectiles/magazines/revolvers.dm +++ b/code/modules/projectiles/magazines/revolvers.dm @@ -4,6 +4,7 @@ default_ammo = /datum/ammo/bullet/revolver flags_equip_slot = NONE caliber = CALIBER_44 + icon = 'icons/obj/items/ammo/revolver.dmi' icon_state = "m44" icon_state_mini = "mag_revolver_bronze" w_class = WEIGHT_CLASS_SMALL @@ -12,7 +13,6 @@ /obj/item/ammo_magazine/revolver/rifle name = "\improper M1855 speed loader (.44LS)" desc = "A speed loader for the M1855, with special design to make it possible to speedload a rifle. Longer version of .44 Magnum, with uranium-neodimium core." - icon = 'icons/obj/items/ammo.dmi' icon_state = "44LS" default_ammo = /datum/ammo/bullet/revolver/rifle caliber = CALIBER_44LS @@ -20,13 +20,10 @@ /obj/item/ammo_magazine/revolver/t500 name = "\improper R-500 speed loader (.500)" - icon = 'icons/obj/items/ammo.dmi' icon_state = "t500" desc = "A R-500 BF revolver speed loader." default_ammo = /datum/ammo/bullet/revolver/t500 - flags_equip_slot = NONE caliber = CALIBER_500 - w_class = WEIGHT_CLASS_SMALL max_rounds = 5 /obj/item/ammo_magazine/revolver/t500/slavs @@ -114,6 +111,6 @@ desc = "A revolver speed loader for the R-76 Magnum, mind your shoulder, will stun most moderately sized targets on impact." default_ammo = /datum/ammo/bullet/revolver/t76 max_rounds = 5 - caliber = CALIBER_12x7 + caliber = CALIBER_12X7 icon_state = "t76" icon_state_mini = "mag_revolver_red" diff --git a/code/modules/projectiles/magazines/rifles.dm b/code/modules/projectiles/magazines/rifles.dm index 08defd211f7..6bbc909a885 100644 --- a/code/modules/projectiles/magazines/rifles.dm +++ b/code/modules/projectiles/magazines/rifles.dm @@ -1,10 +1,7 @@ - - - //------------------------------------------------------- //M41A PULSE RIFLE AMMUNITION -/obj/item/ammo_magazine/rifle/ +/obj/item/ammo_magazine/rifle name = "\improper PR-412 magazine (10x24mm)" desc = "A 10mm assault rifle magazine." caliber = CALIBER_10X24_CASELESS @@ -13,30 +10,31 @@ w_class = WEIGHT_CLASS_NORMAL default_ammo = /datum/ammo/bullet/rifle max_rounds = 40 + ammo_band_icon = "m412_band" /obj/item/ammo_magazine/rifle/extended name = "\improper PR-412 extended magazine (10x24mm)" desc = "A 10mm assault extended rifle magazine." - icon_state = "m412_ext" icon_state_mini = "mag_rifle_big_yellow" max_rounds = 60 bonus_overlay = "m412_ex" + ammo_band_color = AMMO_BAND_COLOR_EXTENDED /obj/item/ammo_magazine/rifle/incendiary name = "\improper PR-412 incendiary magazine (10x24mm)" desc = "A 10mm assault rifle magazine." - icon_state = "m412_incendiary" icon_state_mini = "mag_rifle_big_red" default_ammo = /datum/ammo/bullet/rifle/incendiary bonus_overlay = "m412_incend" + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY /obj/item/ammo_magazine/rifle/ap name = "\improper PR-412 AP magazine (10x24mm)" desc = "A 10mm armor piercing magazine." - icon_state = "m412_ap" icon_state_mini = "mag_rifle_big_green" default_ammo = /datum/ammo/bullet/rifle/ap bonus_overlay = "m412_ap" + ammo_band_color = AMMO_BAND_COLOR_AP //------------------------------------------------------- //ar18 Carbine @@ -52,6 +50,24 @@ default_ammo = /datum/ammo/bullet/rifle max_rounds = 36 +/obj/item/ammo_magazine/rifle/ar18/ap + name = "\improper AR-18 AP magazine (10x24mm)" + desc = "A 10mm armor piercing carbine magazine." + ammo_band_color = AMMO_BAND_COLOR_AP + default_ammo = /datum/ammo/bullet/rifle/ap + +/obj/item/ammo_magazine/rifle/ar18/incendiary + name = "\improper AR-18 incendiary magazine (10x24mm)" + desc = "A 10mm incendiary carbine magazine." + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY + default_ammo = /datum/ammo/bullet/rifle/incendiary + +/obj/item/ammo_magazine/rifle/ar18/hp + name = "\improper AR-18 HP magazine (10x24mm)" + desc = "A 10mm hollow-point carbine magazine." + ammo_band_color = AMMO_BAND_COLOR_HOLLOWPOINT + default_ammo = /datum/ammo/bullet/rifle/hp + //------------------------------------------------------- //AR12 Assault Rifle @@ -66,13 +82,31 @@ default_ammo = /datum/ammo/bullet/rifle max_rounds = 50 +/obj/item/ammo_magazine/rifle/ar12/ap + name = "\improper AR-12 AP magazine (10x24mm)" + desc = "A 10mm armor piercing assault rifle magazine." + ammo_band_color = AMMO_BAND_COLOR_AP + default_ammo = /datum/ammo/bullet/rifle/ap + +/obj/item/ammo_magazine/rifle/ar12/incendiary + name = "\improper AR-12 incendiary magazine (10x24mm)" + desc = "A 10mm incendiary assault rifle magazine." + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY + default_ammo = /datum/ammo/bullet/rifle/incendiary + +/obj/item/ammo_magazine/rifle/ar12/hp + name = "\improper AR-12 HP magazine (10x24mm)" + desc = "A 10mm hollow-point assault rifle magazine." + ammo_band_color = AMMO_BAND_COLOR_HOLLOWPOINT + default_ammo = /datum/ammo/bullet/rifle/hp + //------------------------------------------------------- //DMR37 /obj/item/ammo_magazine/rifle/dmr37 name = "\improper DMR-37 magazine (10x27mm)" desc = "A 10mm DMR magazine." - caliber = CALIBER_10x27_CASELESS + caliber = CALIBER_10X27_CASELESS icon_state = "t37" icon_state_mini = "mag_rifle_big" w_class = WEIGHT_CLASS_NORMAL @@ -85,12 +119,19 @@ /obj/item/ammo_magazine/rifle/br64 name = "\improper BR-64 magazine (10x26.5mm)" desc = "A 10mm battle rifle magazine." - caliber = CALIBER_10x265_CASELESS + caliber = CALIBER_10X265_CASELESS icon_state = "t64" icon_state_mini = "mag_rifle_big" w_class = WEIGHT_CLASS_NORMAL default_ammo = /datum/ammo/bullet/rifle/br64 max_rounds = 36 + ammo_band_icon = "t64_band" + +/obj/item/ammo_magazine/rifle/br64/ap + name = "\improper BR-64 AP magazine (10x26.5mm)" + desc = "A 10mm armor piercing battle rifle magazine." + default_ammo = /datum/ammo/bullet/rifle/br64/ap + ammo_band_color = AMMO_BAND_COLOR_AP //------------------------------------------------------- //M41A TRUE AND ORIGINAL @@ -233,7 +274,7 @@ desc = "A belt box for the MG-60 general purpose machinegun." icon_state = "t60" icon_state_mini = "mag_gpmg" - caliber = CALIBER_10x26_CASELESS + caliber = CALIBER_10X26_CASELESS default_ammo = /datum/ammo/bullet/rifle/machinegun w_class = WEIGHT_CLASS_NORMAL max_rounds = 200 @@ -305,11 +346,11 @@ /obj/item/ammo_magazine/sg29 name = "\improper SG-29 drum magazine" desc = "A wide drum magazine carefully filled to capacity with 10x26mm specialized smart rounds." - caliber = CALIBER_10x26_CASELESS + caliber = CALIBER_10X26_CASELESS icon_state = "sg29" icon_state_mini = "mag_sg29" w_class = WEIGHT_CLASS_NORMAL - default_ammo = /datum/ammo/bullet/sg29 + default_ammo = /datum/ammo/bullet/rifle/t25 max_rounds = 250 reload_delay = 1.3 SECONDS @@ -319,7 +360,7 @@ /obj/item/ammo_magazine/rifle/sg62 name = "\improper SG-62 magazine (10x27mm HV)" desc = "A magazine filled with 10x27mm specialized smart rounds." - caliber = CALIBER_10x27_CASELESS + caliber = CALIBER_10X27_CASELESS icon_state = "sg62" w_class = WEIGHT_CLASS_NORMAL default_ammo = /datum/ammo/bullet/sg62 @@ -332,7 +373,7 @@ /obj/item/ammo_magazine/rifle/sg153 name = "\improper SG-153 magazine (12x7mm)" desc = "A magazine filled with 12x7mm lethal smart rounds, these will do nothing other than pack a big punch." - caliber = CALIBER_12x7 + caliber = CALIBER_12X7 icon_state = "sg153" w_class = WEIGHT_CLASS_SMALL default_ammo = /datum/ammo/bullet/sg153 @@ -399,14 +440,15 @@ default_ammo = /datum/ammo/bullet/sniper/pfc max_rounds = 10 bonus_overlay = "tl127_mag" + ammo_band_icon = "tl127_band" /obj/item/ammo_magazine/rifle/sr127/flak name = "SR-127 bolt action rifle flak magazine" desc = "A box magazine filled with 8.6x70mm rifle flak rounds for the SR-127." - icon_state = "tl127_flak" icon_state_mini = "mag_sniper_blue" default_ammo = /datum/ammo/bullet/sniper/pfc/flak bonus_overlay = "tl127_flak" + ammo_band_color = AMMO_BAND_COLOR_IMPACT //------------------------------------------------------- //Marine magazine automatic sniper, or the SR-81. @@ -442,6 +484,33 @@ default_ammo = /datum/ammo/bullet/rifle/heavy max_rounds = 30 +/obj/item/ammo_magazine/rifle/ar21/extended + name = "\improper AR-21 extended skirmish rifle magazine" + desc = "A extended magazine filled with 10x25mm rifle rounds for the AR-21." + icon_state = "t21_ext" + max_rounds = 50 + icon_state_mini = "mag_rifle_big_yellow" + ammo_band_color = AMMO_BAND_COLOR_EXTENDED + bonus_overlay = "t21_ext" + +/obj/item/ammo_magazine/rifle/ar21/ap + name = "\improper AR-21 skirmish AP rifle magazine" + desc = "A magazine filled with 10x25mm armor piercing rifle rounds for the AR-21." + ammo_band_color = AMMO_BAND_COLOR_AP + default_ammo = /datum/ammo/bullet/rifle/heavy/ap + +/obj/item/ammo_magazine/rifle/ar21/incendiary + name = "\improper AR-21 skirmish incendiary rifle magazine" + desc = "A magazine filled with 10x25mm incendiary rifle rounds for the AR-21." + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY + default_ammo = /datum/ammo/bullet/rifle/heavy/incendiary + +/obj/item/ammo_magazine/rifle/ar21/hp + name = "\improper AR-21 skirmish HP rifle magazine" + desc = "A magazine filled with 10x25mm armor-piercing rifle rounds for the AR-21." + ammo_band_color = AMMO_BAND_COLOR_HOLLOWPOINT + default_ammo = /datum/ammo/bullet/rifle/heavy/hp + //ALF-51B /obj/item/ammo_magazine/rifle/alf_machinecarbine @@ -473,6 +542,7 @@ name = "\improper 20mm airburst grenade magazine" desc = "A 20mm magazine loaded with airburst grenades. For use with the GL-54 or AR-55." caliber = CALIBER_20MM + icon = 'icons/obj/items/ammo/misc.dmi' icon_state = "tx54_airburst" icon_state_mini = "mag_sniper_blue" w_class = WEIGHT_CLASS_NORMAL @@ -485,7 +555,6 @@ name = "\improper 20mm incendiary grenade magazine" desc = "A 20mm magazine loaded with incendiary grenades. For use with the GL-54 or AR-55." default_ammo = /datum/ammo/tx54/incendiary - icon_state = "tx54_airburst" icon_state_mini = "mag_sniper_orange" greyscale_colors = COLOR_AMMO_INCENDIARY @@ -493,7 +562,6 @@ name = "\improper 20mm tactical smoke grenade magazine" desc = "A 20mm magazine loaded with tactical smoke grenades. For use with the GL-54 or AR-55." default_ammo = /datum/ammo/tx54/smoke - icon_state = "tx54_airburst" icon_state_mini = "mag_sniper_green" greyscale_colors = COLOR_AMMO_TACTICAL_SMOKE @@ -501,7 +569,6 @@ name = "\improper 20mm smoke grenade magazine" desc = "A 20mm magazine loaded with smoke grenades. For use with the GL-54 or AR-55." default_ammo = /datum/ammo/tx54/smoke/dense - icon_state = "tx54_airburst" icon_state_mini = "mag_sniper_cyan" greyscale_colors = COLOR_AMMO_SMOKE @@ -509,7 +576,6 @@ name = "\improper 20mm tanglefoot grenade magazine" desc = "A 20mm magazine loaded with tanglefoot grenades. For use with the GL-54 or AR-55." default_ammo = /datum/ammo/tx54/smoke/tangle - icon_state = "tx54_airburst" icon_state_mini = "mag_sniper_purple" greyscale_colors = COLOR_AMMO_TANGLEFOOT @@ -517,7 +583,6 @@ name = "\improper 20mm razorburn grenade magazine" desc = "A 20mm magazine loaded with razorburn grenades. For use with the GL-54 or AR-55." default_ammo = /datum/ammo/tx54/razor - icon_state = "tx54_airburst" icon_state_mini = "mag_sniper_yellow" greyscale_colors = COLOR_AMMO_RAZORBURN @@ -545,23 +610,21 @@ w_class = WEIGHT_CLASS_NORMAL default_ammo = /datum/ammo/bullet/rifle max_rounds = 50 + ammo_band_icon = "v31_band" /obj/item/ammo_magazine/rifle/som/ap name = "\improper V-31 AP magazine (10x24mm)" desc = "A 10mm rifle magazine designed for the V-31, loaded with armor piercing rounds." - caliber = CALIBER_10X24_CASELESS - icon_state = "v31_ap" icon_state_mini = "mag_thin_green" - w_class = WEIGHT_CLASS_NORMAL default_ammo = /datum/ammo/bullet/rifle/hv - max_rounds = 50 + ammo_band_color = AMMO_BAND_COLOR_AP /obj/item/ammo_magazine/rifle/som/incendiary name = "\improper V-31 incendiary magazine (10x24mm)" desc = "A 10mm rifle magazine designed for the V-31, loaded with incendiary rounds." - icon_state = "v31_incend" icon_state_mini = "mag_thin_red" default_ammo = /datum/ammo/bullet/rifle/incendiary + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY //------------------------------------------------------- //V-41 Machine Gun @@ -571,7 +634,7 @@ desc = "A drum magazine for the V-41 machinegun." icon_state = "v41" icon_state_mini = "mag_drum_big_long" - caliber = CALIBER_10x26_CASELESS + caliber = CALIBER_10X26_CASELESS default_ammo = /datum/ammo/bullet/rifle/som_machinegun w_class = WEIGHT_CLASS_NORMAL max_rounds = 200 @@ -583,7 +646,7 @@ /obj/item/ammo_magazine/rifle/icc_sharpshooter name = "\improper L-11 sharpshooter rifle magazine (10x27mm)" desc = "A 10mm DMR magazine." - caliber = CALIBER_10x27_CASELESS + caliber = CALIBER_10X27_CASELESS icon_state = "l11" icon_state_mini = "mag_rifle" w_class = WEIGHT_CLASS_NORMAL @@ -652,23 +715,13 @@ /obj/item/ammo_magazine/rifle/t25 name = "\improper T-25 magazine (10x26mm)" desc = "A 10mm assault rifle magazine." - caliber = CALIBER_10x26_CASELESS - icon = 'icons/obj/items/ammo.dmi' + caliber = CALIBER_10X26_CASELESS icon_state = "t25" w_class = WEIGHT_CLASS_NORMAL default_ammo = /datum/ammo/bullet/rifle/t25 max_rounds = 80 icon_state_mini = "mag_rifle_big" -/obj/item/ammo_magazine/rifle/ar21/extended - name = "\improper AR-21 extended skirmish rifle magazine" - desc = "A extended magazine filled with 10x25mm rifle rounds for the AR-21." - icon = 'icons/obj/items/ammo.dmi' - icon_state = "t21_ext" - max_rounds = 50 - icon_state_mini = "mag_rifle_big_yellow" - bonus_overlay = "t21_ext" - /obj/item/ammo_magazine/rifle/t25/extended name = "\improper T-25 extended magazine (10x26mm)" desc = "A 10mm extended assault rifle magazine." @@ -676,76 +729,3 @@ max_rounds = 120 icon_state_mini = "mag_rifle_big_yellow" bonus_overlay = "t25_ext" - -/obj/item/ammo_magazine/rifle/ar18/ap - name = "\improper AR-18 AP magazine (10x24mm)" - desc = "A 10mm armor piercing carbine magazine." - ammo_band_color = AMMO_BAND_COLOR_AP - default_ammo = /datum/ammo/bullet/rifle/ap - -/obj/item/ammo_magazine/rifle/ar18/incendiary - name = "\improper AR-18 incendiary magazine (10x24mm)" - desc = "A 10mm incendiary carbine magazine." - ammo_band_color = AMMO_BAND_COLOR_INCENDIARY - default_ammo = /datum/ammo/bullet/rifle/incendiary - -/obj/item/ammo_magazine/rifle/ar18/hp - name = "\improper AR-18 HP magazine (10x24mm)" - desc = "A 10mm hollow-point carbine magazine." - ammo_band_color = AMMO_BAND_COLOR_HOLLOWPOINT - default_ammo = /datum/ammo/bullet/rifle/hp - -/obj/item/ammo_magazine/rifle/ar12/ap - name = "\improper AR-12 AP magazine (10x24mm)" - desc = "A 10mm armor piercing assault rifle magazine." - ammo_band_color = AMMO_BAND_COLOR_AP - default_ammo = /datum/ammo/bullet/rifle/ap - -/obj/item/ammo_magazine/rifle/ar12/incendiary - name = "\improper AR-12 incendiary magazine (10x24mm)" - desc = "A 10mm incendiary assault rifle magazine." - ammo_band_color = AMMO_BAND_COLOR_INCENDIARY - default_ammo = /datum/ammo/bullet/rifle/incendiary - -/obj/item/ammo_magazine/rifle/ar12/hp - name = "\improper AR-12 HP magazine (10x24mm)" - desc = "A 10mm hollow-point assault rifle magazine." - ammo_band_color = AMMO_BAND_COLOR_HOLLOWPOINT - default_ammo = /datum/ammo/bullet/rifle/hp - -/obj/item/ammo_magazine/rifle/br64/ap - name = "\improper BR-64 AP magazine (10x26.5mm)" - desc = "A 10mm armor piercing battle rifle magazine." - caliber = CALIBER_10x265_CASELESS - icon = 'icons/obj/items/ammo.dmi' - icon_state = "t64_ap" - default_ammo = /datum/ammo/bullet/rifle/br64/ap - icon_state_mini = "mag_rifle_big" - -/obj/item/ammo_magazine/rifle/ar21/ap - name = "\improper AR-21 skirmish AP rifle magazine" - desc = "A magazine filled with 10x25mm armor piercing rifle rounds for the AR-21." - ammo_band_color = AMMO_BAND_COLOR_AP - default_ammo = /datum/ammo/bullet/rifle/heavy/ap - -/obj/item/ammo_magazine/rifle/ar21/incendiary - name = "\improper AR-21 skirmish incendiary rifle magazine" - desc = "A magazine filled with 10x25mm incendiary rifle rounds for the AR-21." - ammo_band_color = AMMO_BAND_COLOR_INCENDIARY - default_ammo = /datum/ammo/bullet/rifle/heavy/incendiary - -/obj/item/ammo_magazine/rifle/ar21/hp - name = "\improper AR-21 skirmish HP rifle magazine" - desc = "A magazine filled with 10x25mm armor-piercing rifle rounds for the AR-21." - ammo_band_color = AMMO_BAND_COLOR_HOLLOWPOINT - default_ammo = /datum/ammo/bullet/rifle/heavy/hp - -/obj/item/ammo_magazine/rifle/som/ap - name = "\improper V-31 AP magazine (10x24mm)" - desc = "A 10mm rifle magazine designed for the V-31, loaded with armor piercing rounds." - caliber = CALIBER_10X24_CASELESS - icon_state = "v31_ap" - w_class = WEIGHT_CLASS_NORMAL - default_ammo = /datum/ammo/bullet/rifle/hv - max_rounds = 50 - icon_state_mini = "mag_rifle_big_green" diff --git a/code/modules/projectiles/magazines/sentries.dm b/code/modules/projectiles/magazines/sentries.dm index f27d0ae7c79..0dd6d5b033e 100644 --- a/code/modules/projectiles/magazines/sentries.dm +++ b/code/modules/projectiles/magazines/sentries.dm @@ -2,7 +2,8 @@ name = "\improper Магазин TUR-B (10x28мм)" desc = "Коробчатый магазин на 200 безгильзовых патронов 10х28 мм для турели \"Базис\". Вставьте в порт турели в случае отстутсвия боеприпасов." w_class = WEIGHT_CLASS_NORMAL - icon_state = "sentry_mag" + icon = 'icons/obj/items/ammo/stationary.dmi' + icon_state = "sentry" flags_magazine = NONE //can't be refilled or emptied by hand caliber = CALIBER_10X28 max_rounds = 200 @@ -12,7 +13,8 @@ name = "\improper Магазин TUR-M (10x20мм)" desc = "Коробчатый магазин на 300 безгильзовых патронов 10х20 мм для турели \"Гном\". Вставьте в порт турели в случае отстутсвия боеприпасов." w_class = WEIGHT_CLASS_NORMAL - icon_state = "minisentry_mag" + icon = 'icons/obj/items/ammo/stationary.dmi' + icon_state = "minisentry" flags_magazine = NONE //can't be refilled or emptied by hand caliber = CALIBER_10X20 max_rounds = 300 @@ -35,7 +37,7 @@ /obj/item/ammo_magazine/sentry/sniper name = "\improper Магазин TUR-SN (9x39мм)" desc = "Коробчатый магазин на 50 безгильзовых патронов 9х39 мм для турели \"Оса\". Вставьте в порт турели в случае отстутсвия боеприпасов." - icon_state = "sentry_sniper_mag" + icon_state = "sentry_sniper" max_rounds = 50 default_ammo = /datum/ammo/bullet/turret/sniper @@ -43,7 +45,7 @@ name = "\improper Магазин TUR-SH (12G)" desc = "Коробчатый магазин на 75 специализированных патронов 12 калибра для турели \"Бык\". Вставьте в порт турели в случае отстутсвия боеприпасов." caliber = CALIBER_12G - icon_state = "sentry_shotgun_mag" + icon_state = "sentry_shotgun" max_rounds = 75 default_ammo = /datum/ammo/bullet/turret/buckshot @@ -52,7 +54,7 @@ /obj/item/ammo_magazine/flamer_tank/large/sentry name = "\improper Малый бак TUR-F (Горючее)" desc = "Малый бак на 5 литров горючего для турели \"Феникс\". Вставьте в порт турели в случае отстутсвия горючего." - icon_state = "sentry_flamer_mag" + icon_state = "sentry_flamer" w_class = WEIGHT_CLASS_NORMAL max_rounds = 75 current_rounds = 75 diff --git a/code/modules/projectiles/magazines/shotguns.dm b/code/modules/projectiles/magazines/shotguns.dm index ca99c0ffb21..6eddfa28088 100644 --- a/code/modules/projectiles/magazines/shotguns.dm +++ b/code/modules/projectiles/magazines/shotguns.dm @@ -10,6 +10,7 @@ one type of shotgun ammo, but I think it helps in referencing it. ~N /obj/item/ammo_magazine/shotgun name = "box of 12 gauge shotgun slugs" desc = "A box filled with heavy shotgun shells. A timeless classic. 12 Gauge." + icon = 'icons/obj/items/ammo/packet.dmi' icon_state = "slugs" default_ammo = /datum/ammo/bullet/shotgun/slug caliber = CALIBER_12G //All shotgun rounds are 12g right now. @@ -55,6 +56,7 @@ one type of shotgun ammo, but I think it helps in referencing it. ~N /obj/item/ammo_magazine/rifle/bolt name = "box of 7.62x54mmR rifle rounds" desc = "A box filled with rifle bullets." + icon = 'icons/obj/items/ammo/packet.dmi' icon_state = "7.62" //Thank you Alterist default_ammo = /datum/ammo/bullet/sniper/svd caliber = CALIBER_762X54 //Cyka Blyat @@ -75,6 +77,7 @@ one type of shotgun ammo, but I think it helps in referencing it. ~N /obj/item/ammo_magazine/rifle/martini name = "box of .557/440 rifle rounds" desc = "A box filled with rifle bullets." + icon = 'icons/obj/items/ammo/packet.dmi' icon_state = ".557" default_ammo = /datum/ammo/bullet/sniper/martini caliber = CALIBER_557 @@ -90,6 +93,7 @@ one type of shotgun ammo, but I think it helps in referencing it. ~N /obj/item/ammo_magazine/pistol/derringer name = "box of .40 rimfire pistol rounds" desc = "A box filled with pistol bullets." + icon = 'icons/obj/items/ammo/packet.dmi' icon_state = "derringer_box" default_ammo = /datum/ammo/bullet/pistol/superheavy/derringer caliber = CALIBER_41RIM diff --git a/code/modules/projectiles/magazines/smgs.dm b/code/modules/projectiles/magazines/smgs.dm index 176bedb0d0f..0a2924cc21e 100644 --- a/code/modules/projectiles/magazines/smgs.dm +++ b/code/modules/projectiles/magazines/smgs.dm @@ -3,6 +3,7 @@ desc = "A submachinegun magazine." default_ammo = /datum/ammo/bullet/smg max_rounds = 30 + icon = 'icons/obj/items/ammo/smg.dmi' icon_state_mini = "mag_smg" //------------------------------------------------------- @@ -15,20 +16,21 @@ icon_state = "m25" max_rounds = 60 w_class = WEIGHT_CLASS_SMALL + ammo_band_icon = "m25_band" /obj/item/ammo_magazine/smg/m25/ap name = "\improper SMG-25 AP magazine (10x20mm)" - icon_state = "m25_ap" default_ammo = /datum/ammo/bullet/smg/ap icon_state_mini = "mag_smg_green" bonus_overlay = "m25_ap" + ammo_band_color = AMMO_BAND_COLOR_AP /obj/item/ammo_magazine/smg/m25/extended name = "\improper SMG-25 extended magazine (10x20mm)" - icon_state = "m25_ext" max_rounds = 90 icon_state_mini = "mag_smg_yellow" bonus_overlay = "m25_ex" + ammo_band_color = AMMO_BAND_COLOR_EXTENDED //------------------------------------------------------- //MP-19 Machinepistol ammo @@ -132,20 +134,21 @@ icon_state_mini = "mag_smg" max_rounds = 50 w_class = WEIGHT_CLASS_SMALL + ammo_band_icon = "v21_band" /obj/item/ammo_magazine/smg/som/ap name = "\improper V-21 AP submachinegun magazine (10x20mm)" desc = "A 10x20mm caseless submachinegun magazine, loaded in armor piercing rounds." - icon_state = "v21_ap" default_ammo = /datum/ammo/bullet/smg/ap icon_state_mini = "mag_smg_green" + ammo_band_color = AMMO_BAND_COLOR_AP /obj/item/ammo_magazine/smg/som/incendiary name = "\improper V-21 incendiary submachinegun magazine (10x20mm)" desc = "A 10x20mm caseless submachinegun magazine, loaded in incendiary rounds." - icon_state = "v21_incend" default_ammo = /datum/ammo/bullet/smg/incendiary icon_state_mini = "mag_smg_red" + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY /obj/item/ammo_magazine/smg/som/extended name = "\improper V-21 extended submachinegun magazine (10x20mm)" @@ -155,6 +158,7 @@ icon_state_mini = "mag_smg_yellow" w_class = WEIGHT_CLASS_NORMAL aim_speed_mod = 0.1 + ammo_band_color = AMMO_BAND_COLOR_EXTENDED /obj/item/ammo_magazine/smg/som/rad name = "\improper V-21 radioactive submachinegun magazine (10x20mm)" @@ -175,16 +179,14 @@ default_ammo = /datum/ammo/bullet/smg/ap max_rounds = 32 w_class = WEIGHT_CLASS_SMALL + ammo_band_icon = "pl38_band" /obj/item/ammo_magazine/smg/icc_machinepistol/hp name = "\improper PL-38 HP machinepistol magazine (10x20mm)" desc = "A 10x20mm caseless hollow point machine pistol magazine." - caliber = CALIBER_10X20_CASELESS - icon_state = "pl38_hp" icon_state_mini = "mag_smg_dark_blue" default_ammo = /datum/ammo/bullet/smg/hollow - max_rounds = 32 - w_class = WEIGHT_CLASS_SMALL + ammo_band_color = AMMO_BAND_COLOR_HOLLOWPOINT //------------------------------------------------------- //L-40, ICC PDW diff --git a/code/modules/projectiles/magazines/specialist.dm b/code/modules/projectiles/magazines/specialist.dm index 042f81290cf..b927614f300 100644 --- a/code/modules/projectiles/magazines/specialist.dm +++ b/code/modules/projectiles/magazines/specialist.dm @@ -12,21 +12,21 @@ default_ammo = /datum/ammo/bullet/sniper reload_delay = 3 icon_state_mini = "mag_sniper" - + ammo_band_icon = "t26_band" /obj/item/ammo_magazine/sniper/incendiary name = "\improper SR-26 incendiary magazine (10x28mm)" default_ammo = /datum/ammo/bullet/sniper/incendiary - icon_state = "t26_inc" icon_state_mini = "mag_sniper_red" bonus_overlay = "t26_incend" + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY /obj/item/ammo_magazine/sniper/flak name = "\improper SR-26 flak magazine (10x28mm)" default_ammo = /datum/ammo/bullet/sniper/flak - icon_state = "t26_flak" icon_state_mini = "mag_sniper_blue" bonus_overlay = "t26_flak" + ammo_band_color = AMMO_BAND_COLOR_IMPACT //SR-42 magazine @@ -62,24 +62,24 @@ default_ammo = /datum/ammo/bullet/rifle/tx8 max_rounds = 25 icon_state_mini = "mag_rifle_big" + ammo_band_icon = "tx8_band" /obj/item/ammo_magazine/rifle/tx8/incendiary name = "\improper high velocity incendiary magazine (10x28mm)" desc = "A magazine of overpressuered high velocity incendiary rounds for use in the BR-8 battle rifle. The BR-8 battle rifle is the only gun that can chamber these rounds." caliber = CALIBER_10X28_CASELESS - icon_state = "tx8_incend" default_ammo = /datum/ammo/bullet/rifle/tx8/incendiary icon_state_mini = "mag_rifle_big_red" bonus_overlay = "tx8_incend" + ammo_band_color = AMMO_BAND_COLOR_INCENDIARY /obj/item/ammo_magazine/rifle/tx8/impact name = "\improper high velocity impact magazine (10x28mm)" desc = "A magazine of overpressuered high velocity impact rounds for use in the BR-8 battle rifle. The BR-8 battle rifle is the only gun that can chamber these rounds." - icon_state = "tx8_impact" default_ammo = /datum/ammo/bullet/rifle/tx8/impact icon_state_mini = "mag_rifle_big_blue" bonus_overlay = "tx8_impact" - + ammo_band_color = AMMO_BAND_COLOR_IMPACT //------------------------------------------------------- //M5 RPG @@ -88,6 +88,7 @@ name = "\improper generic high-explosive rocket" desc = "A precursor to all kinds of rocket ammo unfit for normal use. How did you get this anyway?" caliber = CALIBER_84MM + icon = 'icons/obj/items/ammo/rocket.dmi' icon_state = "rocket" w_class = WEIGHT_CLASS_NORMAL flags_magazine = MAGAZINE_REFUND_IN_CHAMBER @@ -358,6 +359,7 @@ name = "railgun canister (Armor Piercing Discarding Sabot)" desc = "A canister holding a tungsten projectile to be used inside a railgun. APDS is written across the canister, this round will penetrate through most armor, but will not leave much of a hole." caliber = CALIBER_RAILGUN + icon = 'icons/obj/items/ammo/misc.dmi' icon_state = "railgun" default_ammo = /datum/ammo/bullet/railgun max_rounds = 3 @@ -385,6 +387,7 @@ name = "pepperball canister (SAN balls)" desc = "A canister holding a projectile to be used inside a pepperball gun." caliber = CALIBER_PEPPERBALL + icon = 'icons/obj/items/ammo/misc.dmi' icon_state = "pepperball" default_ammo = /datum/ammo/bullet/pepperball max_rounds = 100 @@ -431,9 +434,9 @@ icon_state = "powerpacksg" flags_magazine = MAGAZINE_WORN|MAGAZINE_REFILLABLE default_ammo = /datum/ammo/bullet/smart_minigun - current_rounds = 2000 - max_rounds = 2000 - caliber = CALIBER_10x26_CASELESS + current_rounds = 1000 + max_rounds = 1000 + caliber = CALIBER_10X26_CASELESS flags_item_map_variant = null diff --git a/code/modules/projectiles/magazines/unmanned_vehicle.dm b/code/modules/projectiles/magazines/unmanned_vehicle.dm index aa1a14595a1..45ba0ef21c5 100644 --- a/code/modules/projectiles/magazines/unmanned_vehicle.dm +++ b/code/modules/projectiles/magazines/unmanned_vehicle.dm @@ -2,6 +2,7 @@ name = "box of 12x40mm" desc = "A box containing 200 rounds of 12x40mm caseless." caliber = CALIBER_12X40 + icon = 'icons/obj/items/ammo/misc.dmi' icon_state = "ltbcannon_4" w_class = WEIGHT_CLASS_NORMAL default_ammo = /datum/ammo/bullet/machinegun @@ -13,6 +14,7 @@ name = "box of 11x35mm" desc = "A box containing 200 rounds of 11x35mm caseless." caliber = CALIBER_11X35 + icon = 'icons/obj/items/ammo/misc.dmi' icon_state = "ltbcannon_4" w_class = WEIGHT_CLASS_NORMAL default_ammo = /datum/ammo/bullet/smg diff --git a/code/modules/reagents/reagents/medical.dm b/code/modules/reagents/reagents/medical.dm index 82b46c0f1a1..12fce353b35 100644 --- a/code/modules/reagents/reagents/medical.dm +++ b/code/modules/reagents/reagents/medical.dm @@ -149,7 +149,6 @@ name = "Oxycodone" description = "An effective and very addictive painkiller." color = COLOR_REAGENT_OXYCODONE - custom_metabolism = REAGENTS_METABOLISM * 1.25 overdose_threshold = REAGENTS_OVERDOSE * 0.5 overdose_crit_threshold = REAGENTS_OVERDOSE_CRITICAL * 0.5 scannable = TRUE diff --git a/code/modules/reqs/_supply.dm b/code/modules/reqs/_supply.dm index 6eeb1a5cbee..8fac9089dcd 100644 --- a/code/modules/reqs/_supply.dm +++ b/code/modules/reqs/_supply.dm @@ -1,10 +1,3 @@ -GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( - /mob/living, - /obj/item/disk/nuclear, - /obj/item/radio/beacon, - /obj/vehicle, - ))) - /datum/supply_order var/id var/orderer @@ -16,174 +9,6 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( ///What faction ordered this var/faction = FACTION_TERRAGOV -/obj/item/paper/manifest - name = "Supply Manifest" - -/obj/docking_port/stationary/supply - id = "supply_home" - roundstart_template = /datum/map_template/shuttle/supply - width = 5 - dwidth = 2 - dheight = 2 - height = 5 - -/obj/docking_port/mobile/supply - name = "supply shuttle" - id = SHUTTLE_SUPPLY - callTime = 15 SECONDS - - dir = WEST - port_direction = EAST - width = 5 - dwidth = 2 - dheight = 2 - height = 5 - movement_force = list("KNOCKDOWN" = 0, "THROW" = 0) - use_ripples = FALSE - var/list/gears = list() - var/list/obj/machinery/door/poddoor/railing/railings = list() - ///The faction of this docking port (aka, on which ship it is located) - var/faction = FACTION_TERRAGOV - /// Id of the home docking port - var/home_id = "supply_home" - ///prefix for railings and gear todo should probbaly be defines instead? - var/railing_gear_name = "supply" - -/obj/docking_port/mobile/supply/Destroy(force) - for(var/i in railings) - var/obj/machinery/door/poddoor/railing/railing = i - railing.linked_pad = null - railings.Cut() - return ..() - - -/obj/docking_port/mobile/supply/afterShuttleMove() - . = ..() - if(getDockedId() == home_id) - for(var/j in railings) - var/obj/machinery/door/poddoor/railing/R = j - R.open() - -/obj/docking_port/mobile/supply/on_ignition() - if(getDockedId() == home_id) - for(var/j in railings) - var/obj/machinery/door/poddoor/railing/R = j - R.close() - for(var/i in gears) - var/obj/machinery/gear/G = i - G.start_moving(NORTH) - else - for(var/i in gears) - var/obj/machinery/gear/G = i - G.start_moving(SOUTH) - -/obj/docking_port/mobile/supply/register() - . = ..() - for(var/obj/machinery/gear/G in GLOB.machines) - if(G.id == (railing_gear_name+"_elevator_gear")) - gears += G - RegisterSignal(G, COMSIG_QDELETING, PROC_REF(clean_gear)) - for(var/obj/machinery/door/poddoor/railing/R in GLOB.machines) - if(R.id == (railing_gear_name+"_elevator_railing")) - railings += R - RegisterSignal(R, COMSIG_QDELETING, PROC_REF(clean_railing)) - R.linked_pad = src - R.open() - -///Signal handler when a gear is destroyed -/obj/docking_port/mobile/supply/proc/clean_gear(datum/source) - SIGNAL_HANDLER - gears -= source - -///Signal handler when a railing is destroyed -/obj/docking_port/mobile/supply/proc/clean_railing(datum/source) - SIGNAL_HANDLER - railings -= source - -/obj/docking_port/mobile/supply/canMove() - if(is_station_level(z)) - return check_blacklist(shuttle_areas) - return ..() - -/obj/docking_port/mobile/supply/proc/check_blacklist(areaInstances) - if(!areaInstances) - areaInstances = shuttle_areas - for(var/place in areaInstances) - var/area/shuttle/shuttle_area = place - for(var/trf in shuttle_area) - var/turf/T = trf - for(var/a in T.GetAllContents()) - if(isxeno(a)) - var/mob/living/L = a - if(L.stat == DEAD) - continue - if(ishuman(a)) - var/mob/living/carbon/human/human_to_sell = a - if(human_to_sell.stat == DEAD && can_sell_human_body(human_to_sell, faction)) - continue - if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types)) - return FALSE - return TRUE - -/obj/docking_port/mobile/supply/request(obj/docking_port/stationary/S) - if(mode != SHUTTLE_IDLE) - return 2 - return ..() - -/obj/docking_port/mobile/supply/proc/buy(mob/user, datum/supply_ui/supply_ui) - if(!length(SSpoints.shoppinglist[faction])) - return - log_game("Supply pack orders have been purchased by [key_name(user)]") - - var/list/empty_turfs = list() - for(var/place in shuttle_areas) - var/area/shuttle/shuttle_area = place - for(var/turf/open/floor/T in shuttle_area) - if(is_blocked_turf(T)) - continue - empty_turfs += T - - for(var/i in SSpoints.shoppinglist[faction]) - if(!length(empty_turfs)) - break - var/datum/supply_order/SO = LAZYACCESSASSOC(SSpoints.shoppinglist, faction, i) - - var/datum/supply_packs/firstpack = SO.pack[1] - - var/obj/structure/crate_type = firstpack.containertype || firstpack.contains[1] - - var/obj/structure/A = new crate_type(pick_n_take(empty_turfs)) - if(firstpack.containertype) - A.name = "Order #[SO.id] for [SO.orderer]" - - - var/list/contains = list() - //spawn the stuff, finish generating the manifest while you're at it - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - // yes i know - if(SP.access) - A.req_access = list() - A.req_access += text2num(SP.access) - - if(SP.randomised_num_contained) - if(length(SP.contains)) - for(var/j in 1 to SP.randomised_num_contained) - contains += pick(SP.contains) - else - contains += SP.contains - - for(var/typepath in contains) - if(!typepath) - continue - if(!firstpack.containertype) - break - new typepath(A) - - SSpoints.shoppinglist[faction] -= "[SO.id]" - SSpoints.shopping_history += SO - - /datum/export_report /// How many points from that export var/points @@ -196,833 +21,3 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( points = _points export_name = _export_name faction = _faction - -/obj/docking_port/mobile/supply/proc/sell() - for(var/place in shuttle_areas) - var/area/shuttle/shuttle_area = place - for(var/atom/movable/AM in shuttle_area) - if(AM.anchored) - continue - var/datum/export_report = AM.supply_export(faction) - if(export_report) - SSpoints.export_history += export_report - qdel(AM) - -/obj/item/supplytablet - name = "ASRS tablet" - desc = "A tablet for an Automated Storage and Retrieval System" - icon = 'icons/Marine/marine-navigation.dmi' - icon_state = "req_tablet_off" - req_access = list(ACCESS_MARINE_CARGO) - flags_equip_slot = ITEM_SLOT_POCKET - w_class = WEIGHT_CLASS_NORMAL - var/datum/supply_ui/SU - ///Id of the shuttle controlled - var/shuttle_id = SHUTTLE_SUPPLY - /// Id of the home docking port - var/home_id = "supply_home" - /// Faction of the tablet - var/faction = FACTION_TERRAGOV - -/obj/item/supplytablet/interact(mob/user) - . = ..() - if(.) - return - if(!allowed(user)) - return - if(!SU) - SU = new(src) - SU.shuttle_id = shuttle_id - SU.home_id = home_id - SU.faction = faction - return SU.interact(user) - -/obj/machinery/computer/supplycomp - name = "ASRS console" - desc = "A console for an Automated Storage and Retrieval System" - icon = 'icons/obj/machines/computer.dmi' - icon_state = "computer" - screen_overlay = "supply" - req_access = list(ACCESS_MARINE_CARGO) - circuit = /obj/item/circuitboard/computer/supplycomp - var/datum/supply_ui/SU - ///Id of the shuttle controlled - var/shuttle_id = SHUTTLE_SUPPLY - /// Id of the home docking port - var/home_id = "supply_home" - /// Faction of the computer - var/faction = FACTION_TERRAGOV - -/obj/machinery/computer/supplycomp/interact(mob/user) - . = ..() - if(.) - return - if(isliving(user) && !allowed(user)) - return - if(!SU) - SU = new(src) - SU.shuttle_id = shuttle_id - SU.home_id = home_id - SU.faction = faction - return SU.interact(user) - -/datum/supply_ui - interaction_flags = INTERACT_MACHINE_TGUI - var/atom/source_object - var/tgui_name = "Cargo" - ///Id of the shuttle controlled - var/shuttle_id = "" - ///Reference to the supply shuttle - var/obj/docking_port/mobile/supply/supply_shuttle - ///Faction of the supply console linked - var/faction = FACTION_TERRAGOV - ///Id of the home port - var/home_id = "" - -/datum/supply_ui/New(atom/source_object) - . = ..() - src.source_object = source_object - RegisterSignal(source_object, COMSIG_QDELETING, PROC_REF(clean_ui)) - -///Signal handler to delete the ui when the source object is deleting -/datum/supply_ui/proc/clean_ui() - SIGNAL_HANDLER - qdel(src) - -/datum/supply_ui/Destroy(force) - source_object = null - return ..() - -/datum/supply_ui/ui_host() - return source_object - -/datum/supply_ui/can_interact(mob/user) - . = ..() - if(!.) - return FALSE - if(!user.CanReach(source_object)) - return FALSE - return TRUE - -/datum/supply_ui/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - - if(!ui) - if(shuttle_id) - supply_shuttle = SSshuttle.getShuttle(shuttle_id) - supply_shuttle.home_id = home_id - supply_shuttle.faction = faction - ui = new(user, src, tgui_name, source_object.name) - ui.open() - -/datum/supply_ui/ui_static_data(mob/user) - . = list() - .["categories"] = GLOB.all_supply_groups - .["supplypacks"] = SSpoints.supply_packs_ui - .["supplypackscontents"] = SSpoints.supply_packs_contents - .["elevator_size"] = supply_shuttle?.return_number_of_turfs() - -/datum/supply_ui/ui_data(mob/living/user) - . = list() - .["currentpoints"] = round(SSpoints.supply_points[user.faction]) - .["personalpoints"] = round(SSpoints.personal_supply_points[user.ckey]) - .["requests"] = list() - for(var/key in SSpoints.requestlist) - var/datum/supply_order/SO = SSpoints.requestlist[key] - if(SO.faction != user.faction) - continue - var/list/packs = list() - var/cost = 0 - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - if(packs[SP.type]) - packs[SP.type] += 1 - else - packs[SP.type] = 1 - cost += SP.cost - .["requests"] += list(list("id" = SO.id, "orderer" = SO.orderer, "orderer_rank" = SO.orderer_rank, "reason" = SO.reason, "cost" = cost, "packs" = packs, "authed_by" = SO.authorised_by)) - .["deniedrequests"] = list() - for(var/i in length(SSpoints.deniedrequests) to 1 step -1) - var/datum/supply_order/SO = SSpoints.deniedrequests[SSpoints.deniedrequests[i]] - if(SO.faction != user.faction) - continue - var/list/packs = list() - var/cost = 0 - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - if(packs[SP.type]) - packs[SP.type] += 1 - else - packs[SP.type] = 1 - cost += SP.cost - .["deniedrequests"] += list(list("id" = SO.id, "orderer" = SO.orderer, "orderer_rank" = SO.orderer_rank, "reason" = SO.reason, "cost" = cost, "packs" = packs, "authed_by" = SO.authorised_by)) - .["approvedrequests"] = list() - for(var/i in length(SSpoints.approvedrequests) to 1 step -1) - var/datum/supply_order/SO = SSpoints.approvedrequests[SSpoints.approvedrequests[i]] - if(SO.faction != user.faction) - continue - var/list/packs = list() - var/cost = 0 - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - if(packs[SP.type]) - packs[SP.type] += 1 - else - packs[SP.type] = 1 - cost += SP.cost - .["approvedrequests"] += list(list("id" = SO.id, "orderer" = SO.orderer, "orderer_rank" = SO.orderer_rank, "reason" = SO.reason, "cost" = cost, "packs" = packs, "authed_by" = SO.authorised_by)) - .["awaiting_delivery"] = list() - .["awaiting_delivery_orders"] = 0 - for(var/key in SSpoints.shoppinglist[faction]) - var/datum/supply_order/SO = LAZYACCESSASSOC(SSpoints.shoppinglist, faction, key) - .["awaiting_delivery_orders"]++ - var/list/packs = list() - var/cost = 0 - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - if(packs[SP.type]) - packs[SP.type] += 1 - else - packs[SP.type] = 1 - cost += SP.cost - .["awaiting_delivery"] += list(list("id" = SO.id, "orderer" = SO.orderer, "orderer_rank" = SO.orderer_rank, "reason" = SO.reason, "cost" = cost, "packs" = packs, "authed_by" = SO.authorised_by)) - .["export_history"] = list() - var/id = 0 - var/lastexport = "" - for(var/datum/export_report/report AS in SSpoints.export_history) - if(report.faction != user.faction) - continue - if(report.points == 0) - continue - if(report.export_name == lastexport) - .["export_history"][id]["amount"] += 1 - .["export_history"][id]["total"] += report.points - else - .["export_history"] += list(list("id" = id, "name" = report.export_name, "points" = report.points, "amount" = 1, total = report.points)) - id++ - lastexport = report.export_name - .["shopping_history"] = list() - for(var/datum/supply_order/SO AS in SSpoints.shopping_history) - if(SO.faction != user.faction) - continue - var/list/packs = list() - var/cost = 0 - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - if(packs[SP.type]) - packs[SP.type] += 1 - else - packs[SP.type] = 1 - cost += SP.cost - .["shopping_history"] += list(list("id" = SO.id, "orderer" = SO.orderer, "orderer_rank" = SO.orderer_rank, "reason" = SO.reason, "cost" = cost, "packs" = packs, "authed_by" = SO.authorised_by)) - .["shopping_list_cost"] = 0 - .["shopping_list_items"] = 0 - .["shopping_list"] = list() - for(var/i in SSpoints.shopping_cart) - var/datum/supply_packs/SP = SSpoints.supply_packs[i] - .["shopping_list_items"] += SSpoints.shopping_cart[i] - .["shopping_list_cost"] += SP.cost * SSpoints.shopping_cart[SP.type] - .["shopping_list"][SP.type] = list("count" = SSpoints.shopping_cart[SP.type]) - if(supply_shuttle) - if(supply_shuttle?.mode == SHUTTLE_CALL) - if(is_mainship_level(supply_shuttle.destination.z)) - .["elevator"] = "Raising" - .["elevator_dir"] = "up" - else - .["elevator"] = "Lowering" - .["elevator_dir"] = "down" - else if(supply_shuttle?.mode == SHUTTLE_IDLE) - if(is_mainship_level(supply_shuttle.z)) - .["elevator"] = "Raised" - .["elevator_dir"] = "down" - else - .["elevator"] = "Lowered" - .["elevator_dir"] = "up" - else - if(is_mainship_level(supply_shuttle.z)) - .["elevator"] = "Lowering" - .["elevator_dir"] = "down" - else - .["elevator"] = "Raising" - .["elevator_dir"] = "up" - else - .["elevator"] = "MISSING!" - .["beacon"] = length(GLOB.supply_beacon) ? TRUE : FALSE - -/datum/supply_ui/proc/get_shopping_cart(mob/user) - return SSpoints.shopping_cart - -/datum/supply_ui/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - . = ..() - if(.) - return - switch(action) - if("cart") - var/datum/supply_packs/P = SSpoints.supply_packs[text2path(params["id"])] - if(!P) - return - var/shopping_cart = get_shopping_cart(ui.user) - switch(params["mode"]) - if("removeall") - shopping_cart -= P.type - if("removeone") - if(shopping_cart[P.type] > 1) - shopping_cart[P.type]-- - else - shopping_cart -= P.type - if("addone") - if(shopping_cart[P.type]) - shopping_cart[P.type]++ - else - shopping_cart[P.type] = 1 - if("addall") - var/mob/living/ui_user = ui.user - var/cart_cost = 0 - for(var/i in shopping_cart) - var/datum/supply_packs/SP = SSpoints.supply_packs[i] - cart_cost += SP.cost * shopping_cart[SP.type] - var/excess_points = SSpoints.supply_points[ui_user.faction] - cart_cost - var/number_to_buy = min(round(excess_points / P.cost), 20) //hard cap at 20 - if(shopping_cart[P.type]) - shopping_cart[P.type] += number_to_buy - else - shopping_cart[P.type] = number_to_buy - . = TRUE - if("send") - if(supply_shuttle.mode != SHUTTLE_IDLE) - return - if(is_mainship_level(supply_shuttle.z)) - if (!supply_shuttle.check_blacklist()) - to_chat(usr, "For safety reasons, the Automated Storage and Retrieval System cannot store live, friendlies, classified nuclear weaponry or homing beacons.") - playsound(supply_shuttle.return_center_turf(), 'sound/machines/buzz-two.ogg', 50, 0) - else - playsound(supply_shuttle.return_center_turf(), 'sound/machines/elevator_move.ogg', 50, 0) - SSshuttle.moveShuttleToTransit(shuttle_id, TRUE) - addtimer(CALLBACK(supply_shuttle, TYPE_PROC_REF(/obj/docking_port/mobile/supply, sell)), 15 SECONDS) - else - var/obj/docking_port/D = SSshuttle.getDock(home_id) - supply_shuttle.buy(usr, src) - playsound(D.return_center_turf(), 'sound/machines/elevator_move.ogg', 50, 0) - SSshuttle.moveShuttle(shuttle_id, home_id, TRUE) - . = TRUE - if("approve") - var/datum/supply_order/O = SSpoints.requestlist["[params["id"]]"] - if(!O) - O = SSpoints.deniedrequests["[params["id"]]"] - if(!O) - return - SSpoints.approve_request(O, ui.user) - . = TRUE - if("deny") - var/datum/supply_order/O = SSpoints.requestlist["[params["id"]]"] - if(!O) - return - SSpoints.deny_request(O) - . = TRUE - if("approveall") - for(var/i in SSpoints.requestlist) - var/datum/supply_order/O = SSpoints.requestlist[i] - SSpoints.approve_request(O, ui.user) - . = TRUE - if("denyall") - for(var/i in SSpoints.requestlist) - var/datum/supply_order/O = SSpoints.requestlist[i] - SSpoints.deny_request(O) - . = TRUE - if("buycart") - SSpoints.buy_cart(ui.user) - . = TRUE - if("clearcart") - var/list/shopping_cart = get_shopping_cart(ui.user) - shopping_cart.Cut() - . = TRUE - if("buypersonal") - SSpoints.buy_using_psp(ui.user) - . = TRUE - if("delivery") - var/datum/supply_order/O = SSpoints.shoppinglist[faction]["[params["id"]]"] - if(!O) - return - SSpoints.fast_delivery(O, ui.user) - . = TRUE - -/datum/supply_ui/requests - tgui_name = "CargoRequest" - -// yes these are copy pasted from above because SPEEEEEEEEEEEEED -/datum/supply_ui/requests/ui_static_data(mob/user) - . = list() - .["categories"] = GLOB.all_supply_groups - .["supplypacks"] = SSpoints.supply_packs_ui - .["supplypackscontents"] = SSpoints.supply_packs_contents - -/datum/supply_ui/requests/ui_data(mob/living/user) - . = list() - .["currentpoints"] = round(SSpoints.supply_points[user.faction]) - .["personalpoints"] = round(SSpoints.personal_supply_points[user.ckey]) - .["requests"] = list() - for(var/i in SSpoints.requestlist) - var/datum/supply_order/SO = SSpoints.requestlist[i] - if(SO.faction != user.faction) - continue - var/list/packs = list() - var/cost = 0 - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - if(packs[SP.type]) - packs[SP.type] += 1 - else - packs[SP.type] = 1 - cost += SP.cost - .["requests"] += list(list("id" = SO.id, "orderer" = SO.orderer, "orderer_rank" = SO.orderer_rank, "reason" = SO.reason, "cost" = cost, "packs" = packs, "authed_by" = SO.authorised_by)) - .["deniedrequests"] = list() - for(var/i in length(SSpoints.deniedrequests) to 1 step -1) - var/datum/supply_order/SO = SSpoints.deniedrequests[SSpoints.deniedrequests[i]] - if(SO.faction != user.faction) - continue - var/list/packs = list() - var/cost = 0 - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - if(packs[SP.type]) - packs[SP.type] += 1 - else - packs[SP.type] = 1 - cost += SP.cost - .["deniedrequests"] += list(list("id" = SO.id, "orderer" = SO.orderer, "orderer_rank" = SO.orderer_rank, "reason" = SO.reason, "cost" = cost, "packs" = packs, "authed_by" = SO.authorised_by)) - .["approvedrequests"] = list() - for(var/i in length(SSpoints.approvedrequests) to 1 step -1) - var/datum/supply_order/SO = SSpoints.approvedrequests[SSpoints.approvedrequests[i]] - if(SO.faction != user.faction) - continue - var/list/packs = list() - var/cost = 0 - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - if(packs[SP.type]) - packs[SP.type] += 1 - else - packs[SP.type] = 1 - cost += SP.cost - .["approvedrequests"] += list(list("id" = SO.id, "orderer" = SO.orderer, "orderer_rank" = SO.orderer_rank, "reason" = SO.reason, "cost" = cost, "packs" = packs, "authed_by" = SO.authorised_by)) - .["awaiting_delivery"] = list() - .["awaiting_delivery_orders"] = 0 - for(var/key in SSpoints.shoppinglist[faction]) - //only own orders - var/datum/supply_order/SO = LAZYACCESSASSOC(SSpoints.shoppinglist, faction, key) - if(user.real_name == SO.orderer) - .["awaiting_delivery_orders"]++ - var/list/packs = list() - var/cost = 0 - for(var/P in SO.pack) - var/datum/supply_packs/SP = P - if(packs[SP.type]) - packs[SP.type] += 1 - else - packs[SP.type] = 1 - cost += SP.cost - .["awaiting_delivery"] += list(list("id" = SO.id, "orderer" = SO.orderer, "orderer_rank" = SO.orderer_rank, "reason" = SO.reason, "cost" = cost, "packs" = packs, "authed_by" = SO.authorised_by)) - if(!SSpoints.request_shopping_cart[user.ckey]) - SSpoints.request_shopping_cart[user.ckey] = list() - .["shopping_list_cost"] = 0 - .["shopping_list_items"] = 0 - .["shopping_list"] = list() - for(var/i in SSpoints.request_shopping_cart[user.ckey]) - var/datum/supply_packs/SP = SSpoints.supply_packs[i] - .["shopping_list_items"] += SSpoints.request_shopping_cart[user.ckey][i] - .["shopping_list_cost"] += SP.cost * SSpoints.request_shopping_cart[user.ckey][SP.type] - .["shopping_list"][SP.type] = list("count" = SSpoints.request_shopping_cart[user.ckey][SP.type]) - .["beacon"] = length(GLOB.supply_beacon) ? TRUE : FALSE - -/datum/supply_ui/requests/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - . = ..() - if(.) - return TRUE - switch(action) - if("submitrequest") - SSpoints.submit_request(ui.user, params["reason"]) - . = TRUE - -/datum/supply_ui/requests/get_shopping_cart(mob/user) - return SSpoints.request_shopping_cart[user.ckey] - -/obj/machinery/computer/ordercomp - name = "Supply ordering console" - icon = 'icons/obj/machines/computer.dmi' - icon_state = "computer" - screen_overlay = "request" - broken_icon = "computer_orange_broken" - circuit = /obj/item/circuitboard/computer/ordercomp - var/datum/supply_ui/requests/SU - -/obj/machinery/computer/ordercomp/interact(mob/user) - . = ..() - if(.) - return - if(!allowed(user)) - return - if(!SU) - SU = new(src) - return SU.interact(user) - -/obj/item/storage/backpack/marine/radiopack - name = "\improper TGMC radio operator backpack" - desc = "A backpack that resembles the ones old-age radio operator marines would use. It has a supply ordering console installed on it, and a retractable antenna to receive supply drops." - icon_state = "radiopack" - item_state = "radiopack" - ///Var for the window pop-up - var/datum/supply_ui/requests/supply_interface - /// Reference to the datum used by the supply drop console - var/datum/supply_beacon/beacon_datum - -/obj/item/storage/backpack/marine/radiopack/Destroy() - if(beacon_datum) - UnregisterSignal(beacon_datum, COMSIG_QDELETING) - QDEL_NULL(beacon_datum) - return ..() - -/obj/item/storage/backpack/marine/radiopack/examine(mob/user) - . = ..() - . += span_notice("Right-Click with empty hand to open requisitions interface.") - . += span_notice("Activate in hand to create a supply beacon signal.") - -/obj/item/storage/backpack/marine/radiopack/attack_hand_alternate(mob/living/user) - if(!allowed(user)) - return ..() - if(!supply_interface) - supply_interface = new(src) - return supply_interface.interact(user) - -/obj/item/storage/backpack/marine/radiopack/attack_self(mob/living/user) - if(beacon_datum) - UnregisterSignal(beacon_datum, COMSIG_QDELETING) - QDEL_NULL(beacon_datum) - user.show_message(span_warning("The [src] beeps and states, \"Your last position is no longer accessible by the supply console"), EMOTE_AUDIBLE, span_notice("The [src] vibrates but you can not hear it!")) - return - if(!is_ground_level(user.z)) - to_chat(user, span_warning("You have to be on the planet to use this or it won't transmit.")) - return FALSE - var/turf/location = get_turf(src) - beacon_datum = new /datum/supply_beacon(user.name, user.loc, user.faction, 4 MINUTES) - RegisterSignal(beacon_datum, COMSIG_QDELETING, PROC_REF(clean_beacon_datum)) - user.show_message(span_notice("The [src] beeps and states, \"Your current coordinates were registered by the supply console. LONGITUDE [location.x]. LATITUDE [location.y]. Area ID: [get_area(src)]\""), EMOTE_AUDIBLE, span_notice("The [src] vibrates but you can not hear it!")) - addtimer(CALLBACK(src, PROC_REF(update_beacon_location)), 5 SECONDS) - -/obj/item/storage/backpack/marine/radiopack/proc/update_beacon_location() - if(beacon_datum) - beacon_datum.drop_location = get_turf(src) - addtimer(CALLBACK(src, PROC_REF(update_beacon_location), beacon_datum), 5 SECONDS) - -/// Signal handler to nullify beacon datum -/obj/item/storage/backpack/marine/radiopack/proc/clean_beacon_datum() - SIGNAL_HANDLER - beacon_datum = null - -/obj/docking_port/mobile/supply/vehicle - railing_gear_name = "vehicle" - id = SHUTTLE_VEHICLE_SUPPLY - home_id = "vehicle_home" - -/obj/docking_port/mobile/supply/vehicle/buy(mob/user, datum/supply_ui/supply_ui) - var/datum/supply_ui/vehicles/veh_ui = supply_ui - if(!veh_ui || !veh_ui.current_veh_type) - return - var/obj/vehicle/sealed/armored/tanktype = veh_ui.current_veh_type - var/is_assault = initial(tanktype.flags_armored) & ARMORED_PURCHASABLE_ASSAULT - if(GLOB.purchased_tanks[user.faction]?["[is_assault]"]) - to_chat(usr, span_danger("A vehicle of this type has already been purchased!")) - return - if(!GLOB.purchased_tanks[user.faction]) - GLOB.purchased_tanks[user.faction] = list() - GLOB.purchased_tanks[user.faction]["[is_assault]"] += 1 - var/obj/vehicle/sealed/armored/tank = new tanktype(loc) - if(veh_ui.current_primary) - var/obj/item/armored_weapon/gun = new veh_ui.current_primary(loc) - gun.attach(tank, TRUE) - if(veh_ui.current_secondary) - var/obj/item/armored_weapon/gun = new veh_ui.current_secondary(loc) - gun.attach(tank, FALSE) - if(veh_ui.current_driver_mod) - var/obj/item/tank_module/mod = new veh_ui.current_driver_mod(loc) - mod.on_equip(tank) - if(veh_ui.current_gunner_mod) - var/obj/item/tank_module/mod = new veh_ui.current_gunner_mod(loc) - mod.on_equip(tank) - if(length(veh_ui.primary_ammo)) - var/turf/dumploc = get_step(get_step(loc, NORTH), NORTH) // todo should autoload depending on tank prolly - for(var/ammo in veh_ui.primary_ammo) - for(var/i=1 to veh_ui.primary_ammo[ammo]) - new ammo(dumploc) - if(length(veh_ui.secondary_ammo)) - var/turf/dumploc = get_step(get_step(loc, NORTH), NORTH) // todo should autoload depending on tank prolly - for(var/ammo in veh_ui.secondary_ammo) - for(var/i=1 to veh_ui.secondary_ammo[ammo]) - new ammo(dumploc) - -/obj/docking_port/stationary/supply/vehicle - id = "vehicle_home" - roundstart_template = /datum/map_template/shuttle/supply/vehicle - - - -GLOBAL_LIST_EMPTY(armored_gunammo) -GLOBAL_LIST_EMPTY(armored_modtypes) -GLOBAL_LIST_INIT(armored_guntypes, armored_init_guntypes()) -GLOBAL_LIST_EMPTY(purchased_tanks) -#define DEFAULT_MAX_ARMORED_AMMO 20 - -///im a lazy bum who cant use initial on lists, so we just load everything into a list -/proc/armored_init_guntypes() - . = list() - for(var/obj/vehicle/sealed/armored/vehtype AS in typesof(/obj/vehicle/sealed/armored)) - vehtype = new vehtype - GLOB.armored_modtypes[vehtype.type] = vehtype.permitted_mods - .[vehtype.type] = vehtype.permitted_weapons - qdel(vehtype) - for(var/obj/item/armored_weapon/gun AS in typesof(/obj/item/armored_weapon)) - gun = new gun - GLOB.armored_gunammo[gun.type] = gun.accepted_ammo - qdel(gun) - -/datum/supply_ui/vehicles - tgui_name = "VehicleSupply" - shuttle_id = SHUTTLE_VEHICLE_SUPPLY - home_id = "vehicle_home" - /// current selected vehicles typepath - var/current_veh_type - /// current selected primary weapons typepath - var/current_primary - /// current selected secondaryies typepath - var/current_secondary - /// current driver mod typepath - var/current_driver_mod - /// current gunner mod typepath - var/current_gunner_mod - /// current primary ammo list, type = count - var/list/primary_ammo = list() - /// current secondary ammo list, type = count - var/list/secondary_ammo = list() - -/datum/supply_ui/vehicles/ui_static_data(mob/user) - var/list/data = list() - for(var/obj/vehicle/sealed/armored/vehtype AS in typesof(/obj/vehicle/sealed/armored)) - var/flags = vehtype::flags_armored - - if(flags & ARMORED_PURCHASABLE_TRANSPORT) - if(user.skills.getRating(SKILL_LARGE_VEHICLE) < SKILL_LARGE_VEHICLE_EXPERIENCED) - continue - else if(flags & ARMORED_PURCHASABLE_ASSAULT) - if(user.skills.getRating(SKILL_LARGE_VEHICLE) < SKILL_LARGE_VEHICLE_VETERAN) - continue - else - continue - - data["vehicles"] += list(list("name" = initial(vehtype.name), "desc" = initial(vehtype.desc), "type" = "[vehtype]", "isselected" = (vehtype == current_veh_type))) - if(vehtype != current_veh_type) - continue - for(var/obj/item/armored_weapon/gun AS in GLOB.armored_guntypes[vehtype]) - var/primary_selected = (current_primary == gun) - var/secondary_selected = (current_secondary == gun) - if(initial(gun.weapon_slot) & MODULE_PRIMARY) - data["primaryWeapons"] += list(list( - "name" = initial(gun.name), - "desc" = initial(gun.desc), - "type" = gun, - "isselected" = primary_selected, - )) - if(primary_selected) - for(var/obj/item/ammo_magazine/mag AS in primary_ammo) - data["primaryammotypes"] += list(list( - "name" = initial(mag.name), - "type" = mag, - "current" = primary_ammo[mag], - "max" = DEFAULT_MAX_ARMORED_AMMO, //TODO make vehicle ammo dynamic instead of fixed number - )) - - if(initial(gun.weapon_slot) & MODULE_SECONDARY) - data["secondaryWeapons"] += list(list( - "name" = initial(gun.name), - "desc" = initial(gun.desc), - "type" = gun, - "isselected" = secondary_selected, - )) - if(secondary_selected) - for(var/obj/item/ammo_magazine/mag AS in secondary_ammo) - data["secondarymmotypes"] += list(list( - "name" = initial(mag.name), - "type" = mag, - "current" = secondary_ammo[mag], - "max" = DEFAULT_MAX_ARMORED_AMMO, //TODO make vehicle ammo dynamic instead of fixed number - )) - - for(var/obj/item/tank_module/mod AS in GLOB.armored_modtypes[vehtype]) - if(initial(mod.is_driver_module)) - data["driverModules"] += list(list( - "name" = initial(mod.name), - "desc" = initial(mod.desc), - "type" = mod, - "isselected" = (current_driver_mod == mod), - )) - else - data["gunnerModules"] += list(list( - "name" = initial(mod.name), - "desc" = initial(mod.desc), - "type" = mod, - "isselected" = (current_gunner_mod == mod), - )) - return data - -/datum/supply_ui/vehicles/ui_data(mob/living/user) - var/list/data = list() - if(supply_shuttle) - if(supply_shuttle?.mode == SHUTTLE_CALL) - if(is_mainship_level(supply_shuttle.destination.z)) - data["elevator"] = "Raising" - data["elevator_dir"] = "up" - else - data["elevator"] = "Lowering" - data["elevator_dir"] = "down" - else if(supply_shuttle?.mode == SHUTTLE_IDLE) - if(is_mainship_level(supply_shuttle.z)) - data["elevator"] = "Raised" - data["elevator_dir"] = "down" - else if(current_veh_type) - data["elevator"] = "Purchase" - data["elevator_dir"] = "store" - else - data["elevator"] = "Lowered" - data["elevator_dir"] = "up" - else - if(is_mainship_level(supply_shuttle.z)) - data["elevator"] = "Lowering" - data["elevator_dir"] = "down" - else - data["elevator"] = "Raising" - data["elevator_dir"] = "up" - else - data["elevator"] = "MISSING!" - return data - -/datum/supply_ui/vehicles/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - . = ..() - if(.) - return - - switch(action) - if("setvehicle") - var/newtype = text2path(params["type"]) - if(!ispath(newtype, /obj/vehicle/sealed/armored)) - return - var/obj/vehicle/sealed/armored/tank_type = newtype - var/is_assault = initial(tank_type.flags_armored) & ARMORED_PURCHASABLE_ASSAULT - if(GLOB.purchased_tanks[usr.faction]?["[is_assault]"]) - to_chat(usr, span_danger("A vehicle of this type has already been purchased!")) - return - current_veh_type = newtype - current_primary = null // set everything to null, to avoid bugs - current_secondary = null - current_driver_mod = null - current_gunner_mod = null - primary_ammo = list() - secondary_ammo = list() - . = TRUE - - if("setprimary") - if(!current_veh_type) - return - var/newtype = text2path(params["type"]) - if(!(newtype in GLOB.armored_guntypes[current_veh_type])) - return - current_primary = newtype - var/list/assoc_cast = GLOB.armored_gunammo[newtype] - primary_ammo = assoc_cast.Copy() - for(var/ammo in primary_ammo) - primary_ammo[ammo] = 0 - . = TRUE - - if("setsecondary") - if(!current_veh_type) - return - var/newtype = text2path(params["type"]) - if(!(newtype in GLOB.armored_guntypes[current_veh_type])) - return - current_secondary = newtype - var/list/assoc_cast = GLOB.armored_gunammo[newtype] - secondary_ammo = assoc_cast.Copy() - for(var/ammo in secondary_ammo) - secondary_ammo[ammo] = 0 - . = TRUE - - if("set_ammo_primary") - if(!current_primary) - return - var/newtype = text2path(params["type"]) - if(!(newtype in primary_ammo)) - return - var/non_adjusted_total = 0 - for(var/ammo in primary_ammo) - if(ammo == newtype) - continue - non_adjusted_total += primary_ammo[ammo] - var/newvalue = clamp(params["new_value"], 0, DEFAULT_MAX_ARMORED_AMMO-non_adjusted_total) - primary_ammo[newtype] = newvalue - . = TRUE - - if("set_ammo_secondary") - if(!current_secondary) - return - var/newtype = text2path(params["type"]) - if(!(newtype in secondary_ammo)) - return - var/non_adjusted_total = 0 - for(var/ammo in secondary_ammo) - if(ammo == newtype) - continue - non_adjusted_total += secondary_ammo[ammo] - var/newvalue = clamp(params["new_value"], 0, DEFAULT_MAX_ARMORED_AMMO-non_adjusted_total) - secondary_ammo[newtype] = newvalue - . = TRUE - - if("set_driver_mod") - if(!current_veh_type) - return - var/newtype = text2path(params["type"]) - if(!ispath(newtype, /obj/item/tank_module)) - return - if(!(newtype in GLOB.armored_modtypes[current_veh_type])) - return - current_driver_mod = newtype - . = TRUE - - if("set_gunner_mod") - if(!current_veh_type) - return - var/newtype = text2path(params["type"]) - if(!ispath(newtype, /obj/item/tank_module)) - return - if(!(newtype in GLOB.armored_modtypes[current_veh_type])) - return - current_gunner_mod = newtype - . = TRUE - - if("deploy") - if(supply_shuttle.mode != SHUTTLE_IDLE) - to_chat(usr, span_danger("Elevator moving!")) - return - if(is_mainship_level(supply_shuttle.z)) - to_chat(usr, span_danger("Elevator raised. Lower to deploy vehicle.")) - return - supply_shuttle.buy(usr, src) - ui_act("send", params, ui, state) - SStgui.close_user_uis(usr, src) - current_veh_type = null - current_primary = null - current_secondary = null - current_driver_mod = null - current_gunner_mod = null - primary_ammo = list() - secondary_ammo = list() - update_static_data(usr) - - if(.) - update_static_data(usr) diff --git a/code/modules/reqs/computer.dm b/code/modules/reqs/computer.dm new file mode 100644 index 00000000000..7adbdd8b4d2 --- /dev/null +++ b/code/modules/reqs/computer.dm @@ -0,0 +1,47 @@ +/obj/machinery/computer/supplycomp + name = "ASRS console" + desc = "A console for an Automated Storage and Retrieval System" + icon = 'icons/obj/machines/computer.dmi' + icon_state = "computer" + screen_overlay = "supply" + req_access = list(ACCESS_MARINE_CARGO) + circuit = /obj/item/circuitboard/computer/supplycomp + var/datum/supply_ui/supply_ui + ///Id of the shuttle controlled + var/shuttle_id = SHUTTLE_SUPPLY + /// Id of the home docking port + var/home_id = "supply_home" + /// Faction of the computer + var/faction = FACTION_TERRAGOV + +/obj/machinery/computer/supplycomp/interact(mob/user) + . = ..() + if(.) + return + if(isliving(user) && !allowed(user)) + return + if(!supply_ui) + supply_ui = new(src) + supply_ui.shuttle_id = shuttle_id + supply_ui.home_id = home_id + supply_ui.faction = faction + return supply_ui.interact(user) + +/obj/machinery/computer/ordercomp + name = "Supply ordering console" + icon = 'icons/obj/machines/computer.dmi' + icon_state = "computer" + screen_overlay = "request" + broken_icon = "computer_orange_broken" + circuit = /obj/item/circuitboard/computer/ordercomp + var/datum/supply_ui/requests/supply_ui + +/obj/machinery/computer/ordercomp/interact(mob/user) + . = ..() + if(.) + return + if(!allowed(user)) + return + if(!supply_ui) + supply_ui = new(src) + return supply_ui.interact(user) diff --git a/code/modules/reqs/elevator.dm b/code/modules/reqs/elevator.dm new file mode 100644 index 00000000000..53362324d42 --- /dev/null +++ b/code/modules/reqs/elevator.dm @@ -0,0 +1,227 @@ +GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( + /mob/living, + /obj/item/disk/nuclear, + /obj/item/radio/beacon, + /obj/vehicle, +))) + +/obj/docking_port/stationary/supply + id = "supply_home" + roundstart_template = /datum/map_template/shuttle/supply + width = 5 + dwidth = 2 + dheight = 2 + height = 5 + +/obj/docking_port/mobile/supply + name = "supply shuttle" + id = SHUTTLE_SUPPLY + callTime = 15 SECONDS + + dir = WEST + port_direction = EAST + width = 5 + dwidth = 2 + dheight = 2 + height = 5 + movement_force = list("KNOCKDOWN" = 0, "THROW" = 0) + use_ripples = FALSE + var/list/gears = list() + var/list/obj/machinery/door/poddoor/railing/railings = list() + ///The faction of this docking port (aka, on which ship it is located) + var/faction = FACTION_TERRAGOV + /// Id of the home docking port + var/home_id = "supply_home" + ///prefix for railings and gear todo should probbaly be defines instead? + var/railing_gear_name = "supply" + +/obj/docking_port/mobile/supply/Destroy(force) + for(var/i in railings) + var/obj/machinery/door/poddoor/railing/railing = i + railing.linked_pad = null + railings.Cut() + return ..() + +/obj/docking_port/mobile/supply/afterShuttleMove() + . = ..() + if(getDockedId() != home_id) + return + for(var/j in railings) + var/obj/machinery/door/poddoor/railing/our_railing = j + our_railing.open() + +/obj/docking_port/mobile/supply/on_ignition() + if(getDockedId() == home_id) + for(var/j in railings) + var/obj/machinery/door/poddoor/railing/our_railing = j + our_railing.close() + for(var/i in gears) + var/obj/machinery/gear/our_gear = i + our_gear.start_moving(NORTH) + else + for(var/i in gears) + var/obj/machinery/gear/our_gear = i + our_gear.start_moving(SOUTH) + +/obj/docking_port/mobile/supply/register() + . = ..() + for(var/obj/machinery/gear/our_gear in GLOB.machines) + if(our_gear.id != (railing_gear_name + "_elevator_gear")) + continue + gears += our_gear + RegisterSignal(our_gear, COMSIG_QDELETING, PROC_REF(clean_gear)) + for(var/obj/machinery/door/poddoor/railing/our_railing in GLOB.machines) + if(our_railing.id != (railing_gear_name + "_elevator_railing")) + continue + railings += our_railing + RegisterSignal(our_railing, COMSIG_QDELETING, PROC_REF(clean_railing)) + our_railing.linked_pad = src + our_railing.open() + +///Signal handler when a gear is destroyed +/obj/docking_port/mobile/supply/proc/clean_gear(datum/source) + SIGNAL_HANDLER + gears -= source + +///Signal handler when a railing is destroyed +/obj/docking_port/mobile/supply/proc/clean_railing(datum/source) + SIGNAL_HANDLER + railings -= source + +/obj/docking_port/mobile/supply/canMove() + if(is_station_level(z)) + return check_blacklist(shuttle_areas) + return ..() + +/obj/docking_port/mobile/supply/proc/check_blacklist(areaInstances) + if(!areaInstances) + areaInstances = shuttle_areas + for(var/place in areaInstances) + var/area/shuttle/shuttle_area = place + for(var/trf in shuttle_area) + var/turf/T = trf + for(var/a in T.GetAllContents()) + if(isxeno(a)) + var/mob/living/L = a + if(L.stat == DEAD) + continue + if(ishuman(a)) + var/mob/living/carbon/human/human_to_sell = a + if(human_to_sell.stat == DEAD && can_sell_human_body(human_to_sell, faction)) + continue + if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types)) + return FALSE + return TRUE + +/obj/docking_port/mobile/supply/request(obj/docking_port/stationary/S) + if(mode != SHUTTLE_IDLE) + return 2 + return ..() + +/obj/docking_port/mobile/supply/proc/buy(mob/user, datum/supply_ui/supply_ui) + if(!length(SSpoints.shoppinglist[faction])) + return + log_game("Supply pack orders have been purchased by [key_name(user)]") + + var/list/empty_turfs = list() + for(var/place in shuttle_areas) + var/area/shuttle/shuttle_area = place + for(var/turf/open/floor/T in shuttle_area) + if(is_blocked_turf(T)) + continue + empty_turfs += T + + for(var/i in SSpoints.shoppinglist[faction]) + if(!length(empty_turfs)) + break + var/datum/supply_order/our_order = LAZYACCESSASSOC(SSpoints.shoppinglist, faction, i) + + var/datum/supply_packs/firstpack = our_order.pack[1] + + var/obj/structure/crate_type = firstpack.containertype || firstpack.contains[1] + + var/obj/structure/our_structure = new crate_type(pick_n_take(empty_turfs)) + if(firstpack.containertype) + our_structure.name = "Order #[our_order.id] for [our_order.orderer]" + + var/list/contains = list() + //spawn the stuff, finish generating the manifest while you're at it + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + // yes i know + if(our_pack.access) + our_structure.req_access = list() + our_structure.req_access += text2num(our_pack.access) + + if(our_pack.randomised_num_contained) + if(length(our_pack.contains)) + for(var/j in 1 to our_pack.randomised_num_contained) + contains += pick(our_pack.contains) + else + contains += our_pack.contains + + for(var/typepath in contains) + if(!typepath) + continue + if(!firstpack.containertype) + break + new typepath(our_structure) + + SSpoints.shoppinglist[faction] -= "[our_order.id]" + SSpoints.shopping_history += our_order + +/obj/docking_port/mobile/supply/proc/sell() + for(var/place in shuttle_areas) + var/area/shuttle/shuttle_area = place + for(var/atom/movable/AM in shuttle_area) + if(AM.anchored) + continue + var/datum/export_report = AM.supply_export(faction) + if(export_report) + SSpoints.export_history += export_report + qdel(AM) + +/obj/docking_port/mobile/supply/vehicle + railing_gear_name = "vehicle" + id = SHUTTLE_VEHICLE_SUPPLY + home_id = "vehicle_home" + +/obj/docking_port/mobile/supply/vehicle/buy(mob/user, datum/supply_ui/supply_ui) + var/datum/supply_ui/vehicles/veh_ui = supply_ui + if(!veh_ui || !veh_ui.current_veh_type) + return + var/obj/vehicle/sealed/armored/tanktype = veh_ui.current_veh_type + var/is_assault = initial(tanktype.flags_armored) & ARMORED_PURCHASABLE_ASSAULT + if(GLOB.purchased_tanks[user.faction]?["[is_assault]"]) + to_chat(usr, span_danger("A vehicle of this type has already been purchased!")) + return + if(!GLOB.purchased_tanks[user.faction]) + GLOB.purchased_tanks[user.faction] = list() + GLOB.purchased_tanks[user.faction]["[is_assault]"] += 1 + var/obj/vehicle/sealed/armored/tank = new tanktype(loc) + if(veh_ui.current_primary) + var/obj/item/armored_weapon/gun = new veh_ui.current_primary(loc) + gun.attach(tank, TRUE) + if(veh_ui.current_secondary) + var/obj/item/armored_weapon/gun = new veh_ui.current_secondary(loc) + gun.attach(tank, FALSE) + if(veh_ui.current_driver_mod) + var/obj/item/tank_module/mod = new veh_ui.current_driver_mod(loc) + mod.on_equip(tank) + if(veh_ui.current_gunner_mod) + var/obj/item/tank_module/mod = new veh_ui.current_gunner_mod(loc) + mod.on_equip(tank) + if(length(veh_ui.primary_ammo)) + var/turf/dumploc = get_step(get_step(loc, NORTH), NORTH) // todo should autoload depending on tank prolly + for(var/ammo in veh_ui.primary_ammo) + for(var/i=1 to veh_ui.primary_ammo[ammo]) + new ammo(dumploc) + if(length(veh_ui.secondary_ammo)) + var/turf/dumploc = get_step(get_step(loc, NORTH), NORTH) // todo should autoload depending on tank prolly + for(var/ammo in veh_ui.secondary_ammo) + for(var/i=1 to veh_ui.secondary_ammo[ammo]) + new ammo(dumploc) + +/obj/docking_port/stationary/supply/vehicle + id = "vehicle_home" + roundstart_template = /datum/map_template/shuttle/supply/vehicle diff --git a/code/modules/reqs/_supplypacks.dm b/code/modules/reqs/supplypacks/_supplypacks.dm similarity index 100% rename from code/modules/reqs/_supplypacks.dm rename to code/modules/reqs/supplypacks/_supplypacks.dm diff --git a/code/modules/reqs/armor.dm b/code/modules/reqs/supplypacks/armor.dm similarity index 99% rename from code/modules/reqs/armor.dm rename to code/modules/reqs/supplypacks/armor.dm index 0c44b1efb7f..6df2f7c5286 100644 --- a/code/modules/reqs/armor.dm +++ b/code/modules/reqs/supplypacks/armor.dm @@ -86,7 +86,7 @@ /obj/item/armor_module/module/mimir_environment_protection/mimir_helmet, /obj/item/armor_module/module/mimir_environment_protection, ) - cost = 120 + cost = 160 /datum/supply_packs/armor/modular/attachments/artemis_mark_two name = "Freyr Mark 2 helmet module" diff --git a/code/modules/reqs/clothing.dm b/code/modules/reqs/supplypacks/clothing.dm similarity index 100% rename from code/modules/reqs/clothing.dm rename to code/modules/reqs/supplypacks/clothing.dm diff --git a/code/modules/reqs/engineering.dm b/code/modules/reqs/supplypacks/engineering.dm similarity index 100% rename from code/modules/reqs/engineering.dm rename to code/modules/reqs/supplypacks/engineering.dm diff --git a/code/modules/reqs/explosives.dm b/code/modules/reqs/supplypacks/explosives.dm similarity index 100% rename from code/modules/reqs/explosives.dm rename to code/modules/reqs/supplypacks/explosives.dm diff --git a/code/modules/reqs/factory.dm b/code/modules/reqs/supplypacks/factory.dm similarity index 100% rename from code/modules/reqs/factory.dm rename to code/modules/reqs/supplypacks/factory.dm diff --git a/code/modules/reqs/imports.dm b/code/modules/reqs/supplypacks/imports.dm similarity index 100% rename from code/modules/reqs/imports.dm rename to code/modules/reqs/supplypacks/imports.dm diff --git a/code/modules/reqs/launchers.dm b/code/modules/reqs/supplypacks/launchers.dm similarity index 100% rename from code/modules/reqs/launchers.dm rename to code/modules/reqs/supplypacks/launchers.dm diff --git a/code/modules/reqs/medical.dm b/code/modules/reqs/supplypacks/medical.dm similarity index 100% rename from code/modules/reqs/medical.dm rename to code/modules/reqs/supplypacks/medical.dm diff --git a/code/modules/reqs/operations.dm b/code/modules/reqs/supplypacks/operations.dm similarity index 100% rename from code/modules/reqs/operations.dm rename to code/modules/reqs/supplypacks/operations.dm diff --git a/code/modules/reqs/smartguns.dm b/code/modules/reqs/supplypacks/smartguns.dm similarity index 100% rename from code/modules/reqs/smartguns.dm rename to code/modules/reqs/supplypacks/smartguns.dm diff --git a/code/modules/reqs/stationary.dm b/code/modules/reqs/supplypacks/stationary.dm similarity index 100% rename from code/modules/reqs/stationary.dm rename to code/modules/reqs/supplypacks/stationary.dm diff --git a/code/modules/reqs/supplies.dm b/code/modules/reqs/supplypacks/supplies.dm similarity index 100% rename from code/modules/reqs/supplies.dm rename to code/modules/reqs/supplypacks/supplies.dm diff --git a/code/modules/reqs/vehicles.dm b/code/modules/reqs/supplypacks/vehicles.dm similarity index 100% rename from code/modules/reqs/vehicles.dm rename to code/modules/reqs/supplypacks/vehicles.dm diff --git a/code/modules/reqs/weapons.dm b/code/modules/reqs/supplypacks/weapons.dm similarity index 100% rename from code/modules/reqs/weapons.dm rename to code/modules/reqs/supplypacks/weapons.dm diff --git a/code/modules/reqs/tablet.dm b/code/modules/reqs/tablet.dm new file mode 100644 index 00000000000..373413c7edc --- /dev/null +++ b/code/modules/reqs/tablet.dm @@ -0,0 +1,28 @@ +/obj/item/supplytablet + name = "ASRS tablet" + desc = "A tablet for an Automated Storage and Retrieval System" + icon = 'icons/Marine/marine-navigation.dmi' + icon_state = "req_tablet_off" + req_access = list(ACCESS_MARINE_CARGO) + flags_equip_slot = ITEM_SLOT_POCKET + w_class = WEIGHT_CLASS_NORMAL + var/datum/supply_ui/supply_ui + ///Id of the shuttle controlled + var/shuttle_id = SHUTTLE_SUPPLY + /// Id of the home docking port + var/home_id = "supply_home" + /// Faction of the tablet + var/faction = FACTION_TERRAGOV + +/obj/item/supplytablet/interact(mob/user) + . = ..() + if(.) + return + if(!allowed(user)) + return + if(!supply_ui) + supply_ui = new(src) + supply_ui.shuttle_id = shuttle_id + supply_ui.home_id = home_id + supply_ui.faction = faction + return supply_ui.interact(user) diff --git a/code/modules/reqs/ui/_ui.dm b/code/modules/reqs/ui/_ui.dm new file mode 100644 index 00000000000..495ddbdf9f3 --- /dev/null +++ b/code/modules/reqs/ui/_ui.dm @@ -0,0 +1,316 @@ +/datum/supply_ui + interaction_flags = INTERACT_MACHINE_TGUI + var/atom/source_object + var/tgui_name = "Cargo" + ///Id of the shuttle controlled + var/shuttle_id = "" + ///Reference to the supply shuttle + var/obj/docking_port/mobile/supply/supply_shuttle + ///Faction of the supply console linked + var/faction = FACTION_TERRAGOV + ///Id of the home port + var/home_id = "" + +/datum/supply_ui/New(atom/source_object) + . = ..() + src.source_object = source_object + RegisterSignal(source_object, COMSIG_QDELETING, PROC_REF(clean_ui)) + +///Signal handler to delete the ui when the source object is deleting +/datum/supply_ui/proc/clean_ui() + SIGNAL_HANDLER + qdel(src) + +/datum/supply_ui/Destroy(force) + source_object = null + return ..() + +/datum/supply_ui/ui_host() + return source_object + +/datum/supply_ui/can_interact(mob/user) + . = ..() + if(!.) + return FALSE + if(!user.CanReach(source_object)) + return FALSE + return TRUE + +/datum/supply_ui/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + + if(ui) + return + if(shuttle_id) + supply_shuttle = SSshuttle.getShuttle(shuttle_id) + supply_shuttle.home_id = home_id + supply_shuttle.faction = faction + ui = new(user, src, tgui_name, source_object.name) + ui.open() + +/datum/supply_ui/ui_static_data(mob/user) + . = list() + .["categories"] = GLOB.all_supply_groups + .["supplypacks"] = SSpoints.supply_packs_ui + .["supplypackscontents"] = SSpoints.supply_packs_contents + .["elevator_size"] = supply_shuttle?.return_number_of_turfs() + +/datum/supply_ui/ui_data(mob/living/user) + . = list() + .["currentpoints"] = round(SSpoints.supply_points[user.faction]) + .["personalpoints"] = round(SSpoints.personal_supply_points[user.ckey]) + .["requests"] = list() + for(var/key in SSpoints.requestlist) + var/datum/supply_order/our_order = SSpoints.requestlist[key] + if(our_order.faction != user.faction) + continue + var/list/packs = list() + var/cost = 0 + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + if(packs[our_pack.type]) + packs[our_pack.type] += 1 + else + packs[our_pack.type] = 1 + cost += our_pack.cost + .["requests"] += list(list("id" = our_order.id, "orderer" = our_order.orderer, "orderer_rank" = our_order.orderer_rank, "reason" = our_order.reason, "cost" = cost, "packs" = packs, "authed_by" = our_order.authorised_by)) + .["deniedrequests"] = list() + for(var/i in length(SSpoints.deniedrequests) to 1 step -1) + var/datum/supply_order/our_order = SSpoints.deniedrequests[SSpoints.deniedrequests[i]] + if(our_order.faction != user.faction) + continue + var/list/packs = list() + var/cost = 0 + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + if(packs[our_pack.type]) + packs[our_pack.type] += 1 + else + packs[our_pack.type] = 1 + cost += our_pack.cost + .["deniedrequests"] += list(list( + "id" = our_order.id, + "orderer" = our_order.orderer, + "orderer_rank" = our_order.orderer_rank, + "reason" = our_order.reason, + "cost" = cost, "packs" = packs, + "authed_by" = our_order.authorised_by + )) + .["approvedrequests"] = list() + for(var/i in length(SSpoints.approvedrequests) to 1 step -1) + var/datum/supply_order/our_order = SSpoints.approvedrequests[SSpoints.approvedrequests[i]] + if(our_order.faction != user.faction) + continue + var/list/packs = list() + var/cost = 0 + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + if(packs[our_pack.type]) + packs[our_pack.type] += 1 + else + packs[our_pack.type] = 1 + cost += our_pack.cost + .["approvedrequests"] += list(list( + "id" = our_order.id, + "orderer" = our_order.orderer, + "orderer_rank" = our_order.orderer_rank, + "reason" = our_order.reason, + "cost" = cost, "packs" = packs, + "authed_by" = our_order.authorised_by + )) + .["awaiting_delivery"] = list() + .["awaiting_delivery_orders"] = 0 + for(var/key in SSpoints.shoppinglist[faction]) + var/datum/supply_order/our_order = LAZYACCESSASSOC(SSpoints.shoppinglist, faction, key) + .["awaiting_delivery_orders"]++ + var/list/packs = list() + var/cost = 0 + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + if(packs[our_pack.type]) + packs[our_pack.type] += 1 + else + packs[our_pack.type] = 1 + cost += our_pack.cost + .["awaiting_delivery"] += list(list( + "id" = our_order.id, + "orderer" = our_order.orderer, + "orderer_rank" = our_order.orderer_rank, + "reason" = our_order.reason, + "cost" = cost, + "packs" = packs, + "authed_by" = our_order.authorised_by + )) + .["export_history"] = list() + var/id = 0 + var/lastexport = "" + for(var/datum/export_report/report AS in SSpoints.export_history) + if(report.faction != user.faction) + continue + if(report.points == 0) + continue + if(report.export_name == lastexport) + .["export_history"][id]["amount"] += 1 + .["export_history"][id]["total"] += report.points + else + .["export_history"] += list(list( + "id" = id, + "name" = report.export_name, + "points" = report.points, + "amount" = 1, + total = report.points + )) + id++ + lastexport = report.export_name + .["shopping_history"] = list() + for(var/datum/supply_order/our_order AS in SSpoints.shopping_history) + if(our_order.faction != user.faction) + continue + var/list/packs = list() + var/cost = 0 + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + if(packs[our_pack.type]) + packs[our_pack.type] += 1 + else + packs[our_pack.type] = 1 + cost += our_pack.cost + .["shopping_history"] += list(list( + "id" = our_order.id, + "orderer" = our_order.orderer, + "orderer_rank" = our_order.orderer_rank, + "reason" = our_order.reason, + "cost" = cost, + "packs" = packs, + "authed_by" = our_order.authorised_by + )) + .["shopping_list_cost"] = 0 + .["shopping_list_items"] = 0 + .["shopping_list"] = list() + for(var/i in SSpoints.shopping_cart) + var/datum/supply_packs/our_pack = SSpoints.supply_packs[i] + .["shopping_list_items"] += SSpoints.shopping_cart[i] + .["shopping_list_cost"] += our_pack.cost * SSpoints.shopping_cart[our_pack.type] + .["shopping_list"][our_pack.type] = list("count" = SSpoints.shopping_cart[our_pack.type]) + if(supply_shuttle) + if(supply_shuttle?.mode == SHUTTLE_CALL) + if(is_mainship_level(supply_shuttle.destination.z)) + .["elevator"] = "Raising" + .["elevator_dir"] = "up" + else + .["elevator"] = "Lowering" + .["elevator_dir"] = "down" + else if(supply_shuttle?.mode == SHUTTLE_IDLE) + if(is_mainship_level(supply_shuttle.z)) + .["elevator"] = "Raised" + .["elevator_dir"] = "down" + else + .["elevator"] = "Lowered" + .["elevator_dir"] = "up" + else + if(is_mainship_level(supply_shuttle.z)) + .["elevator"] = "Lowering" + .["elevator_dir"] = "down" + else + .["elevator"] = "Raising" + .["elevator_dir"] = "up" + else + .["elevator"] = "MISSING!" + .["beacon"] = length(GLOB.supply_beacon) ? TRUE : FALSE + +/datum/supply_ui/proc/get_shopping_cart(mob/user) + return SSpoints.shopping_cart + +/datum/supply_ui/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + switch(action) + if("cart") + var/datum/supply_packs/P = SSpoints.supply_packs[text2path(params["id"])] + if(!P) + return + var/shopping_cart = get_shopping_cart(ui.user) + switch(params["mode"]) + if("removeall") + shopping_cart -= P.type + if("removeone") + if(shopping_cart[P.type] > 1) + shopping_cart[P.type]-- + else + shopping_cart -= P.type + if("addone") + if(shopping_cart[P.type]) + shopping_cart[P.type]++ + else + shopping_cart[P.type] = 1 + if("addall") + var/mob/living/ui_user = ui.user + var/cart_cost = 0 + for(var/i in shopping_cart) + var/datum/supply_packs/SP = SSpoints.supply_packs[i] + cart_cost += SP.cost * shopping_cart[SP.type] + var/excess_points = SSpoints.supply_points[ui_user.faction] - cart_cost + var/number_to_buy = min(round(excess_points / P.cost), 20) //hard cap at 20 + if(shopping_cart[P.type]) + shopping_cart[P.type] += number_to_buy + else + shopping_cart[P.type] = number_to_buy + . = TRUE + if("send") + if(supply_shuttle.mode != SHUTTLE_IDLE) + return + if(is_mainship_level(supply_shuttle.z)) + if (!supply_shuttle.check_blacklist()) + to_chat(usr, "For safety reasons, the Automated Storage and Retrieval System cannot store live, friendlies, classified nuclear weaponry or homing beacons.") + playsound(supply_shuttle.return_center_turf(), 'sound/machines/buzz-two.ogg', 50, 0) + else + playsound(supply_shuttle.return_center_turf(), 'sound/machines/elevator_move.ogg', 50, 0) + SSshuttle.moveShuttleToTransit(shuttle_id, TRUE) + addtimer(CALLBACK(supply_shuttle, TYPE_PROC_REF(/obj/docking_port/mobile/supply, sell)), 15 SECONDS) + else + var/obj/docking_port/D = SSshuttle.getDock(home_id) + supply_shuttle.buy(usr, src) + playsound(D.return_center_turf(), 'sound/machines/elevator_move.ogg', 50, 0) + SSshuttle.moveShuttle(shuttle_id, home_id, TRUE) + . = TRUE + if("approve") + var/datum/supply_order/O = SSpoints.requestlist["[params["id"]]"] + if(!O) + O = SSpoints.deniedrequests["[params["id"]]"] + if(!O) + return + SSpoints.approve_request(O, ui.user) + . = TRUE + if("deny") + var/datum/supply_order/O = SSpoints.requestlist["[params["id"]]"] + if(!O) + return + SSpoints.deny_request(O) + . = TRUE + if("approveall") + for(var/i in SSpoints.requestlist) + var/datum/supply_order/O = SSpoints.requestlist[i] + SSpoints.approve_request(O, ui.user) + . = TRUE + if("denyall") + for(var/i in SSpoints.requestlist) + var/datum/supply_order/O = SSpoints.requestlist[i] + SSpoints.deny_request(O) + . = TRUE + if("buycart") + SSpoints.buy_cart(ui.user) + . = TRUE + if("clearcart") + var/list/shopping_cart = get_shopping_cart(ui.user) + shopping_cart.Cut() + . = TRUE + if("buypersonal") + SSpoints.buy_using_psp(ui.user) + . = TRUE + if("delivery") + var/datum/supply_order/O = SSpoints.shoppinglist[faction]["[params["id"]]"] + if(!O) + return + SSpoints.fast_delivery(O, ui.user) + . = TRUE diff --git a/code/modules/reqs/ui/request.dm b/code/modules/reqs/ui/request.dm new file mode 100644 index 00000000000..f9b92be3cca --- /dev/null +++ b/code/modules/reqs/ui/request.dm @@ -0,0 +1,133 @@ + +/datum/supply_ui/requests + tgui_name = "CargoRequest" + +// yes these are copy pasted from above because SPEEEEEEEEEEEEED +/datum/supply_ui/requests/ui_static_data(mob/user) + . = list() + .["categories"] = GLOB.all_supply_groups + .["supplypacks"] = SSpoints.supply_packs_ui + .["supplypackscontents"] = SSpoints.supply_packs_contents + +/datum/supply_ui/requests/ui_data(mob/living/user) + . = list() + .["currentpoints"] = round(SSpoints.supply_points[user.faction]) + .["personalpoints"] = round(SSpoints.personal_supply_points[user.ckey]) + .["requests"] = list() + for(var/i in SSpoints.requestlist) + var/datum/supply_order/our_order = SSpoints.requestlist[i] + if(our_order.faction != user.faction) + continue + var/list/packs = list() + var/cost = 0 + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + if(packs[our_pack.type]) + packs[our_pack.type] += 1 + else + packs[our_pack.type] = 1 + cost += our_pack.cost + .["requests"] += list(list( + "id" = our_order.id, + "orderer" = our_order.orderer, + "orderer_rank" = our_order.orderer_rank, + "reason" = our_order.reason, + "cost" = cost, + "packs" = packs, + "authed_by" = our_order.authorised_by + )) + .["deniedrequests"] = list() + for(var/i in length(SSpoints.deniedrequests) to 1 step -1) + var/datum/supply_order/our_order = SSpoints.deniedrequests[SSpoints.deniedrequests[i]] + if(our_order.faction != user.faction) + continue + var/list/packs = list() + var/cost = 0 + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + if(packs[our_pack.type]) + packs[our_pack.type] += 1 + else + packs[our_pack.type] = 1 + cost += our_pack.cost + .["deniedrequests"] += list(list( + "id" = our_order.id, + "orderer" = our_order.orderer, + "orderer_rank" = our_order.orderer_rank, + "reason" = our_order.reason, + "cost" = cost, + "packs" = packs, + "authed_by" = our_order.authorised_by + )) + .["approvedrequests"] = list() + for(var/i in length(SSpoints.approvedrequests) to 1 step -1) + var/datum/supply_order/our_order = SSpoints.approvedrequests[SSpoints.approvedrequests[i]] + if(our_order.faction != user.faction) + continue + var/list/packs = list() + var/cost = 0 + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + if(packs[our_pack.type]) + packs[our_pack.type] += 1 + else + packs[our_pack.type] = 1 + cost += our_pack.cost + .["approvedrequests"] += list(list( + "id" = our_order.id, + "orderer" = our_order.orderer, + "orderer_rank" = our_order.orderer_rank, + "reason" = our_order.reason, + "cost" = cost, + "packs" = packs, + "authed_by" = our_order.authorised_by + )) + .["awaiting_delivery"] = list() + .["awaiting_delivery_orders"] = 0 + for(var/key in SSpoints.shoppinglist[faction]) + //only own orders + var/datum/supply_order/our_order = LAZYACCESSASSOC(SSpoints.shoppinglist, faction, key) + if(user.real_name != our_order.orderer) + continue + .["awaiting_delivery_orders"]++ + var/list/packs = list() + var/cost = 0 + for(var/P in our_order.pack) + var/datum/supply_packs/our_pack = P + if(packs[our_pack.type]) + packs[our_pack.type] += 1 + else + packs[our_pack.type] = 1 + cost += our_pack.cost + .["awaiting_delivery"] += list(list( + "id" = our_order.id, + "orderer" = our_order.orderer, + "orderer_rank" = our_order.orderer_rank, + "reason" = our_order.reason, + "cost" = cost, + "packs" = packs, + "authed_by" = our_order.authorised_by + )) + if(!SSpoints.request_shopping_cart[user.ckey]) + SSpoints.request_shopping_cart[user.ckey] = list() + .["shopping_list_cost"] = 0 + .["shopping_list_items"] = 0 + .["shopping_list"] = list() + for(var/i in SSpoints.request_shopping_cart[user.ckey]) + var/datum/supply_packs/our_pack = SSpoints.supply_packs[i] + .["shopping_list_items"] += SSpoints.request_shopping_cart[user.ckey][i] + .["shopping_list_cost"] += our_pack.cost * SSpoints.request_shopping_cart[user.ckey][our_pack.type] + .["shopping_list"][our_pack.type] = list("count" = SSpoints.request_shopping_cart[user.ckey][our_pack.type]) + .["beacon"] = length(GLOB.supply_beacon) ? TRUE : FALSE + +/datum/supply_ui/requests/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return TRUE + switch(action) + if("submitrequest") + SSpoints.submit_request(ui.user, params["reason"]) + . = TRUE + +/datum/supply_ui/requests/get_shopping_cart(mob/user) + return SSpoints.request_shopping_cart[user.ckey] diff --git a/code/modules/reqs/ui/vehicle.dm b/code/modules/reqs/ui/vehicle.dm new file mode 100644 index 00000000000..8b08be0395f --- /dev/null +++ b/code/modules/reqs/ui/vehicle.dm @@ -0,0 +1,264 @@ +#define DEFAULT_MAX_ARMORED_AMMO 20 + +GLOBAL_LIST_EMPTY(armored_gunammo) +GLOBAL_LIST_EMPTY(armored_modtypes) +GLOBAL_LIST_INIT(armored_guntypes, armored_init_guntypes()) +GLOBAL_LIST_EMPTY(purchased_tanks) + +///im a lazy bum who cant use initial on lists, so we just load everything into a list +/proc/armored_init_guntypes() + . = list() + for(var/obj/vehicle/sealed/armored/vehtype AS in typesof(/obj/vehicle/sealed/armored)) + vehtype = new vehtype + GLOB.armored_modtypes[vehtype.type] = vehtype.permitted_mods + .[vehtype.type] = vehtype.permitted_weapons + qdel(vehtype) + for(var/obj/item/armored_weapon/gun AS in typesof(/obj/item/armored_weapon)) + gun = new gun + GLOB.armored_gunammo[gun.type] = gun.accepted_ammo + qdel(gun) + +/datum/supply_ui/vehicles + tgui_name = "VehicleSupply" + shuttle_id = SHUTTLE_VEHICLE_SUPPLY + home_id = "vehicle_home" + /// current selected vehicles typepath + var/current_veh_type + /// current selected primary weapons typepath + var/current_primary + /// current selected secondaryies typepath + var/current_secondary + /// current driver mod typepath + var/current_driver_mod + /// current gunner mod typepath + var/current_gunner_mod + /// current primary ammo list, type = count + var/list/primary_ammo = list() + /// current secondary ammo list, type = count + var/list/secondary_ammo = list() + +/datum/supply_ui/vehicles/ui_static_data(mob/user) + var/list/data = list() + for(var/obj/vehicle/sealed/armored/vehtype AS in typesof(/obj/vehicle/sealed/armored)) + var/flags = vehtype::flags_armored + + if(flags & ARMORED_PURCHASABLE_TRANSPORT) + if(user.skills.getRating(SKILL_LARGE_VEHICLE) < SKILL_LARGE_VEHICLE_EXPERIENCED) + continue + else if(flags & ARMORED_PURCHASABLE_ASSAULT) + if(user.skills.getRating(SKILL_LARGE_VEHICLE) < SKILL_LARGE_VEHICLE_VETERAN) + continue + else + continue + + data["vehicles"] += list(list("name" = initial(vehtype.name), "desc" = initial(vehtype.desc), "type" = "[vehtype]", "isselected" = (vehtype == current_veh_type))) + if(vehtype != current_veh_type) + continue + for(var/obj/item/armored_weapon/gun AS in GLOB.armored_guntypes[vehtype]) + var/primary_selected = (current_primary == gun) + var/secondary_selected = (current_secondary == gun) + if(initial(gun.weapon_slot) & MODULE_PRIMARY) + data["primaryWeapons"] += list(list( + "name" = initial(gun.name), + "desc" = initial(gun.desc), + "type" = gun, + "isselected" = primary_selected, + )) + if(primary_selected) + for(var/obj/item/ammo_magazine/mag AS in primary_ammo) + data["primaryammotypes"] += list(list( + "name" = initial(mag.name), + "type" = mag, + "current" = primary_ammo[mag], + "max" = DEFAULT_MAX_ARMORED_AMMO, //TODO make vehicle ammo dynamic instead of fixed number + )) + + if(initial(gun.weapon_slot) & MODULE_SECONDARY) + data["secondaryWeapons"] += list(list( + "name" = initial(gun.name), + "desc" = initial(gun.desc), + "type" = gun, + "isselected" = secondary_selected, + )) + if(secondary_selected) + for(var/obj/item/ammo_magazine/mag AS in secondary_ammo) + data["secondarymmotypes"] += list(list( + "name" = initial(mag.name), + "type" = mag, + "current" = secondary_ammo[mag], + "max" = DEFAULT_MAX_ARMORED_AMMO, //TODO make vehicle ammo dynamic instead of fixed number + )) + + for(var/obj/item/tank_module/mod AS in GLOB.armored_modtypes[vehtype]) + if(initial(mod.is_driver_module)) + data["driverModules"] += list(list( + "name" = initial(mod.name), + "desc" = initial(mod.desc), + "type" = mod, + "isselected" = (current_driver_mod == mod), + )) + else + data["gunnerModules"] += list(list( + "name" = initial(mod.name), + "desc" = initial(mod.desc), + "type" = mod, + "isselected" = (current_gunner_mod == mod), + )) + return data + +/datum/supply_ui/vehicles/ui_data(mob/living/user) + var/list/data = list() + if(supply_shuttle) + if(supply_shuttle?.mode == SHUTTLE_CALL) + if(is_mainship_level(supply_shuttle.destination.z)) + data["elevator"] = "Raising" + data["elevator_dir"] = "up" + else + data["elevator"] = "Lowering" + data["elevator_dir"] = "down" + else if(supply_shuttle?.mode == SHUTTLE_IDLE) + if(is_mainship_level(supply_shuttle.z)) + data["elevator"] = "Raised" + data["elevator_dir"] = "down" + else if(current_veh_type) + data["elevator"] = "Purchase" + data["elevator_dir"] = "store" + else + data["elevator"] = "Lowered" + data["elevator_dir"] = "up" + else + if(is_mainship_level(supply_shuttle.z)) + data["elevator"] = "Lowering" + data["elevator_dir"] = "down" + else + data["elevator"] = "Raising" + data["elevator_dir"] = "up" + else + data["elevator"] = "MISSING!" + return data + +/datum/supply_ui/vehicles/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + switch(action) + if("setvehicle") + var/newtype = text2path(params["type"]) + if(!ispath(newtype, /obj/vehicle/sealed/armored)) + return + var/obj/vehicle/sealed/armored/tank_type = newtype + var/is_assault = initial(tank_type.flags_armored) & ARMORED_PURCHASABLE_ASSAULT + if(GLOB.purchased_tanks[usr.faction]?["[is_assault]"]) + to_chat(usr, span_danger("A vehicle of this type has already been purchased!")) + return + current_veh_type = newtype + current_primary = null // set everything to null, to avoid bugs + current_secondary = null + current_driver_mod = null + current_gunner_mod = null + primary_ammo = list() + secondary_ammo = list() + . = TRUE + + if("setprimary") + if(!current_veh_type) + return + var/newtype = text2path(params["type"]) + if(!(newtype in GLOB.armored_guntypes[current_veh_type])) + return + current_primary = newtype + var/list/assoc_cast = GLOB.armored_gunammo[newtype] + primary_ammo = assoc_cast.Copy() + for(var/ammo in primary_ammo) + primary_ammo[ammo] = 0 + . = TRUE + + if("setsecondary") + if(!current_veh_type) + return + var/newtype = text2path(params["type"]) + if(!(newtype in GLOB.armored_guntypes[current_veh_type])) + return + current_secondary = newtype + var/list/assoc_cast = GLOB.armored_gunammo[newtype] + secondary_ammo = assoc_cast.Copy() + for(var/ammo in secondary_ammo) + secondary_ammo[ammo] = 0 + . = TRUE + + if("set_ammo_primary") + if(!current_primary) + return + var/newtype = text2path(params["type"]) + if(!(newtype in primary_ammo)) + return + var/non_adjusted_total = 0 + for(var/ammo in primary_ammo) + if(ammo == newtype) + continue + non_adjusted_total += primary_ammo[ammo] + var/newvalue = clamp(params["new_value"], 0, DEFAULT_MAX_ARMORED_AMMO-non_adjusted_total) + primary_ammo[newtype] = newvalue + . = TRUE + + if("set_ammo_secondary") + if(!current_secondary) + return + var/newtype = text2path(params["type"]) + if(!(newtype in secondary_ammo)) + return + var/non_adjusted_total = 0 + for(var/ammo in secondary_ammo) + if(ammo == newtype) + continue + non_adjusted_total += secondary_ammo[ammo] + var/newvalue = clamp(params["new_value"], 0, DEFAULT_MAX_ARMORED_AMMO-non_adjusted_total) + secondary_ammo[newtype] = newvalue + . = TRUE + + if("set_driver_mod") + if(!current_veh_type) + return + var/newtype = text2path(params["type"]) + if(!ispath(newtype, /obj/item/tank_module)) + return + if(!(newtype in GLOB.armored_modtypes[current_veh_type])) + return + current_driver_mod = newtype + . = TRUE + + if("set_gunner_mod") + if(!current_veh_type) + return + var/newtype = text2path(params["type"]) + if(!ispath(newtype, /obj/item/tank_module)) + return + if(!(newtype in GLOB.armored_modtypes[current_veh_type])) + return + current_gunner_mod = newtype + . = TRUE + + if("deploy") + if(supply_shuttle.mode != SHUTTLE_IDLE) + to_chat(usr, span_danger("Elevator moving!")) + return + if(is_mainship_level(supply_shuttle.z)) + to_chat(usr, span_danger("Elevator raised. Lower to deploy vehicle.")) + return + supply_shuttle.buy(usr, src) + ui_act("send", params, ui, state) + SStgui.close_user_uis(usr, src) + current_veh_type = null + current_primary = null + current_secondary = null + current_driver_mod = null + current_gunner_mod = null + primary_ammo = list() + secondary_ammo = list() + update_static_data(usr) + + if(.) + update_static_data(usr) + +#undef DEFAULT_MAX_ARMORED_AMMO diff --git a/code/modules/reqtorio/assembly_crafts.dm b/code/modules/reqtorio/assembly_crafts.dm index 8591ceca2ed..f57c6e362c8 100644 --- a/code/modules/reqtorio/assembly_crafts.dm +++ b/code/modules/reqtorio/assembly_crafts.dm @@ -75,7 +75,7 @@ GLOBAL_LIST_INIT(all_assembly_craft_groups, list("Operations", "Weapons", "Explo name = "Clearing junk in phoron and glass? Explosion transformation power!" craft_time = 15 SECONDS input = list(/obj/item/stack/sheet/mineral/junk = 4) // 20 points - output = list(/obj/item/stack/sheet/glass = 3, /obj/item/stack/sheet/mineral/phoron = 1) //that expensive! but automized! + output = list(/obj/item/stack/sheet/glass/glass = 3, /obj/item/stack/sheet/mineral/phoron = 1) //that expensive! but automized! //one in one craft cuz junk is multi use resource /datum/assembly_craft/engineering/junk_phoron_iron @@ -87,7 +87,7 @@ GLOBAL_LIST_INIT(all_assembly_craft_groups, list("Operations", "Weapons", "Explo /datum/assembly_craft/engineering/drop_pod name = "Zeus orbital drop pod" craft_time = 20 SECONDS - input = list(/obj/item/stack/sheet/plasteel = 5, /obj/item/stack/sheet/glass = 3) // 40 + 6 + input = list(/obj/item/stack/sheet/plasteel = 5, /obj/item/stack/sheet/glass/glass = 3) // 40 + 6 output = list(/obj/structure/droppod = 1) //40 points /******************************************************************************* @@ -98,7 +98,7 @@ CLOTHING /datum/assembly_craft/clothing/swat_mask name = "SWAT mask" - input = list(/obj/item/stack/sheet/plasteel = 3, /obj/item/stack/sheet/glass = 3) // 24 + 6 points + input = list(/obj/item/stack/sheet/plasteel = 3, /obj/item/stack/sheet/glass/glass = 3) // 24 + 6 points output = list(/obj/item/clothing/mask/gas/swat = 1) // 25 points from old factory diff --git a/code/modules/requisitions/supply_export.dm b/code/modules/requisitions/supply_export.dm index dfcd0c4d500..750d96a83b0 100644 --- a/code/modules/requisitions/supply_export.dm +++ b/code/modules/requisitions/supply_export.dm @@ -18,46 +18,46 @@ if(!.) return FALSE - var/list/points = get_export_value() - GLOB.round_statistics.points_from_xenos += points[1] + var/points = get_export_value() + GLOB.round_statistics.points_from_xenos += points -/atom/movable/proc/get_export_value() - return 0 +/atom/movable/proc/get_export_value(export_value = 0) + return export_value -/mob/living/carbon/human/get_export_value() +/mob/living/carbon/human/get_export_value(export_value) if(!job) - return 0 + return export_value switch(job.job_category) if(JOB_CAT_CIVILIAN) - . = 10 + export_value = 10 if(JOB_CAT_ENGINEERING, JOB_CAT_MEDICAL, JOB_CAT_REQUISITIONS) - . = 150 + export_value = 150 if(JOB_CAT_MARINE) - . = 100 + export_value = 100 if(JOB_CAT_SILICON) - . = 800 + export_value = 800 if(JOB_CAT_COMMAND) - . = 1000 - return 0 + export_value = 1000 + return export_value /mob/living/carbon/human/species/yautja/get_export_value() return 3000 -/mob/living/carbon/xenomorph/get_export_value() +/mob/living/carbon/xenomorph/get_export_value(export_value) switch(tier) if(XENO_TIER_MINION) - . = 50 + export_value = 50 if(XENO_TIER_ZERO) - . = 70 + export_value = 70 if(XENO_TIER_ONE) - . = 150 + export_value = 150 if(XENO_TIER_TWO) - . = 300 + export_value = 300 if(XENO_TIER_THREE) - . = 500 + export_value = 500 if(XENO_TIER_FOUR) - . = 1000 - return + export_value = 1000 + return export_value //I hate it but it's how it was so I'm not touching it further than this /mob/living/carbon/xenomorph/shrike/get_export_value() diff --git a/code/modules/screen_alert/command_alert.dm b/code/modules/screen_alert/command_alert.dm index b489b9fb9bc..4f4afd9f118 100644 --- a/code/modules/screen_alert/command_alert.dm +++ b/code/modules/screen_alert/command_alert.dm @@ -24,6 +24,9 @@ var/skill_min = SKILL_LEAD_EXPERT /datum/action/innate/message_squad/should_show() + . = ..() + if(!.) + return return owner.skills.getRating(skill_name) >= skill_min /datum/action/innate/message_squad/can_use_action() @@ -39,7 +42,7 @@ if(!can_use_action()) return var/mob/living/carbon/human/human_owner = owner - var/text = tgui_input_text(human_owner, "Maximum message length [MAX_COMMAND_MESSAGE_LEN]", "Send message to squad", max_length = MAX_COMMAND_MESSAGE_LEN, multiline = TRUE) + var/text = tgui_input_text(human_owner, "Максимальная длина [MAX_COMMAND_MESSAGE_LEN]", "Отправить сообщение отряду", max_length = MAX_COMMAND_MESSAGE_LEN, multiline = TRUE) if(!text) return var/filter_result = CAN_BYPASS_FILTER(human_owner) ? null : is_ic_filtered(text) @@ -53,7 +56,9 @@ return var/sound/S = sound('sound/misc/notice2.ogg') S.channel = CHANNEL_ANNOUNCEMENTS - TIMER_COOLDOWN_START(owner, COOLDOWN_HUD_ORDER, ORDER_COOLDOWN) + TIMER_COOLDOWN_START(owner, COOLDOWN_HUD_ORDER, CIC_ORDER_COOLDOWN) + addtimer(CALLBACK(src, PROC_REF(update_button_icon)), CIC_ORDER_COOLDOWN + 1) + update_button_icon() log_game("[key_name(human_owner)] has broadcasted the hud message [text] at [AREACOORD(human_owner)]") var/override_color // for squad colors var/list/alert_receivers = (GLOB.alive_human_list + GLOB.ai_list + GLOB.observer_list) // for full faction alerts, do this so that faction's AI and ghosts can hear aswell @@ -70,21 +75,21 @@ else override_color = "grey" for(var/mob/living/carbon/human/marine AS in human_owner.assigned_squad.marines_list | GLOB.observer_list) - marine.play_screen_text("SQUAD ANNOUNCEMENT:
" + text, /atom/movable/screen/text/screen_text/command_order) + marine.play_screen_text("ПРИКАЗ ОТРЯДУ:
" + text, /atom/movable/screen/text/screen_text/command_order) to_chat(marine, assemble_alert( - title = "Squad [human_owner.assigned_squad.name] Announcement", - subtitle = "Sent by [human_owner.real_name]", + title = "Приказ отряду [human_owner.assigned_squad.name]", + subtitle = "Отправлен [human_owner.real_name]", message = text, color_override = override_color )) return for(var/mob/faction_receiver in alert_receivers) if(faction_receiver.faction == human_owner.faction || isdead(faction_receiver)) - var/faction_title = GLOB.faction_to_acronym[human_owner.faction] ? GLOB.faction_to_acronym[human_owner.faction] + " Command" : "Unknown Faction" + " Command" - faction_receiver.play_screen_text("[uppertext(faction_title)] ANNOUNCEMENT:
" + text, /atom/movable/screen/text/screen_text/command_order) + var/faction_title = GLOB.faction_to_acronym[human_owner.faction] ? "Командования " + GLOB.faction_to_acronym[human_owner.faction] : "Командования" + " Неизвестной Фракции" + faction_receiver.play_screen_text(" ПРИКАЗ [uppertext(faction_title)]:
" + text, /atom/movable/screen/text/screen_text/command_order) to_chat(faction_receiver, assemble_alert( - title = "[faction_title] Announcement", - subtitle = "Sent by [human_owner.job.title] [human_owner.real_name]", + title = "Сообщение от [faction_title]", + subtitle = "Отправлен [human_owner.job.title] [human_owner.real_name]", message = text )) SEND_SOUND(faction_receiver, S) diff --git a/code/modules/shuttle/marine_dropship.dm b/code/modules/shuttle/marine_dropship.dm index 89fa792a981..e47e4026de6 100644 --- a/code/modules/shuttle/marine_dropship.dm +++ b/code/modules/shuttle/marine_dropship.dm @@ -261,7 +261,7 @@ if(hijack_state != HIJACK_STATE_NORMAL) return cycle_timer = addtimer(CALLBACK(src, PROC_REF(go_to_previous_destination)), 20 SECONDS, TIMER_STOPPABLE) - priority_announce("The Alamo will depart towards [previous.name] in 20 seconds.", "Dropship Automatic Departure", color_override = "grey", playing_sound = FALSE) + priority_announce("Десантный шаттл взлетает через 20 секунд по направлению к [previous.name]", "Автопилот Нормандии", color_override = "grey", playing_sound = FALSE) ///Send the dropship to its previous dock /obj/docking_port/mobile/marine_dropship/proc/go_to_previous_destination() @@ -324,7 +324,7 @@ /obj/docking_port/mobile/marine_dropship/on_prearrival() . = ..() if(hijack_state == HIJACK_STATE_CRASHING) - priority_announce("DROPSHIP ON COLLISION COURSE. CRASH IMMINENT.", "EMERGENCY", sound = 'sound/AI/dropship_emergency.ogg', color_override = "red") + priority_announce("ДЕСАНТНЫЙ ШАТТЛ НА КУРСЕ СТОЛКНОВЕНИЯ. АВАРИЯ НЕИЗБЕЖНА.", "ТРЕВОГА", sound = 'sound/AI/dropship_emergency.ogg', color_override = "red") for(var/obj/machinery/landinglight/light AS in GLOB.landing_lights) if(light.linked_port == destination) light.turn_on() @@ -376,7 +376,7 @@ message_admins("[ADMIN_TPMONTY(src)] has summoned the dropship") log_admin("[key_name(src)] has summoned the dropship") hive?.xeno_message("[src] has summoned down the metal bird to [port], gather to her now!") - priority_announce("Unknown external interference with dropship control. Shutting down autopilot.", "Critical Dropship Alert", type = ANNOUNCEMENT_PRIORITY, color_override = "red") + priority_announce("Неизвестное вмешательство в управление десантным шаттлом. Выключение автопилота...", "Неисправность Шаттла", type = ANNOUNCEMENT_PRIORITY, color_override = "red", sound = 'sound/AI/dropship_wrong.ogg') #define ALIVE_HUMANS_FOR_CALLDOWN 0.1 @@ -414,37 +414,37 @@ locked_sides++ break if(!locked_sides) - to_chat(user, span_warning("The bird is already on the ground, open and vulnerable.")) + to_chat(user, span_warning("Птица уже на земле, открыта и уязвимая.")) return FALSE if(locked_sides < 3 && !isdropshiparea(get_area(user))) - to_chat(user, span_warning("At least one side is still unlocked!")) + to_chat(user, span_warning("По крайней мере одна сторона все еще разблокирована!")) return FALSE - to_chat(user, span_xenodanger("We crack open the metal bird's shell.")) + to_chat(user, span_xenodanger("Мы вскрываем металлическую оболочку птицы.")) if(D.hijack_state != HIJACK_STATE_NORMAL) return FALSE - to_chat(user, span_warning("We begin overriding the shuttle lockdown. This will take a while...")) + to_chat(user, span_warning("Мы начинаем отменять блокировку шаттла. Это займет некоторое время...")) if(!do_after(user, 30 SECONDS, FALSE, null, BUSY_ICON_DANGER, BUSY_ICON_DANGER)) - to_chat(user, span_warning("We cease overriding the shuttle lockdown.")) + to_chat(user, span_warning("Мы прекращаем отмену блокировки шаттла.")) return FALSE if(!is_ground_level(D.z)) - to_chat(user, span_warning("The bird has left meanwhile, try again.")) + to_chat(user, span_warning("Птица улетела, попробуйте еще раз.")) return FALSE D.unlock_all() if(D.mode != SHUTTLE_IGNITING) D.set_hijack_state(HIJACK_STATE_UNLOCKED) D.do_start_hijack_timer(GROUND_LOCKDOWN_TIME) - to_chat(user, span_warning("We were unable to prevent the bird from flying as it is already taking off.")) + to_chat(user, span_warning("Мы не можем помешать птице улететь, так как она уже взлетает.")) D.silicon_lock_airlocks(TRUE) - to_chat(user, span_warning("We have overriden the shuttle lockdown!")) + to_chat(user, span_warning("Мы отменили блокировку шаттла!")) playsound(user, "alien_roar", 50) - priority_announce("Normandy lockdown protocol compromised. Interference preventing remote control.", "Dropship Lock Alert", type = ANNOUNCEMENT_PRIORITY, color_override = "red") + priority_announce("Протокол блокировки Нормандии скомпрометирован. Постороннее вмешательство блокирует попытки удалённого управления.", "Шаттл Заблокирован", type = ANNOUNCEMENT_PRIORITY, color_override = "red", sound = 'sound/AI/dropship_block.ogg') return FALSE if(D.mode != SHUTTLE_IDLE && D.mode != SHUTTLE_RECHARGING) - to_chat(user, span_warning("The bird's mind is currently active. We need to wait until it's more vulnerable...")) + to_chat(user, span_warning("Сознание птицы активно. Нужно подождать, пока она станет более уязвимым...")) return FALSE var/list/living_player_list = count_humans_and_xenos(SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND)), COUNT_IGNORE_ALIVE_SSD) if(length_char(GLOB.alive_human_list) && ((living_player_list[1] / length_char(GLOB.alive_human_list)) > ALIVE_HUMANS_FOR_CALLDOWN)) - to_chat(user, span_warning("There's too many tallhosts still on the ground. They interfere with our psychic field. We must dispatch them before we are able to do this.")) + to_chat(user, span_warning("Ещё много живой добычи на земле. Они мешают нашему психическому полю. Мы должны уничтожить их, прежде чем сможем это сделать.")) return FALSE return TRUE @@ -695,23 +695,23 @@ if(href_list["hijack"]) if(!(X.hive.hive_flags & HIVE_CAN_HIJACK)) - to_chat(X, span_warning("Our hive lacks the psychic prowess to hijack the bird.")) + to_chat(X, span_warning("Нашему улью не хватает экстрасенсорных способностей, чтобы украсть птицу.")) return var/list/living_player_list = SSticker.mode.count_humans_and_xenos(list(X.z), COUNT_IGNORE_ALIVE_SSD) if(living_player_list[1] > living_player_list[2]) // if there are more marines than xenos, we are unable to hijack - to_chat(X, span_xenowarning("There is still prey left to hunt!")) + to_chat(X, span_xenowarning("Еще осталась добыча, на которую можно поохотиться!")) return switch(M.mode) if(SHUTTLE_RECHARGING) - to_chat(X, span_xenowarning("The bird is still cooling down.")) + to_chat(X, span_xenowarning("Птица все еще остывает...")) return if(SHUTTLE_IDLE) //Continue. EMPTY_BLOCK_GUARD else - to_chat(X, span_xenowarning("We can't do that right now.")) + to_chat(X, span_xenowarning("Мы не можем сделать это сейчас.")) return - var/confirm = tgui_alert(usr, "Would you like to hijack the metal bird?", "Hijack the bird?", list("Yes", "No")) - if(confirm != "Yes") + var/confirm = tgui_alert(usr, "Хотите угнать металлическую птицу?", "Угнать птицу?", list("Да", "Нет")) + if(confirm != "Да") return var/obj/docking_port/stationary/marine_dropship/crash_target/CT = pick(SSshuttle.crash_targets) if(!CT) @@ -721,13 +721,13 @@ if(href_list["abduct"]) var/list/living_player_list = SSticker.mode.count_humans_and_xenos(list(X.z), COUNT_IGNORE_ALIVE_SSD) if(living_player_list[1] > 5) - to_chat(X, span_xenowarning("There is still prey left to hunt!")) + to_chat(X, span_xenowarning("Еще осталась добыча, на которую можно поохотиться!")) return - var/confirm = tgui_alert(usr, "Would you like to capture the metal bird?\n THIS WILL END THE ROUND", "Capture the ship?", list( "Yes", "No")) - if(confirm != "Yes") + var/confirm = tgui_alert(usr, "Хотите захватить металлическую птицу?\n ЭТО ЗАВЕРШИТ РАУНД", "Захватить птицу?", list( "Да", "Нет")) + if(confirm != "Да") return - priority_announce("The Normandy has been captured! Losing their main mean of accessing the ground, the marines have no choice but to retreat.", title = "Normandy Captured", color_override = "orange") + priority_announce("Нормандия захвачена! Потеряв главный путь к земле, морпехи вынуждены отступить.", title = "Нормандия Захвачена", color_override = "orange") var/datum/game_mode/infestation/infestation_mode = SSticker.mode infestation_mode.round_stage = INFESTATION_DROPSHIP_CAPTURED_XENOS return @@ -741,7 +741,7 @@ crashing_dropship.crashing = TRUE crashing_dropship.unlock_all() SEND_GLOBAL_SIGNAL(COMSIG_GLOB_DROPSHIP_HIJACKED) - priority_announce("Unscheduled dropship departure detected from operational area. Hijack likely.", title = "Critical Dropship Alert", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/hijack.ogg', color_override = "red") + priority_announce("Зафиксирован незапланированный вылет Нормандии из зоны боевых действий. Вероятен угон.", title = "Неисправность Нормандии", type = ANNOUNCEMENT_PRIORITY, sound = 'sound/AI/hijack.ogg', color_override = "red") to_chat(user, span_danger("A loud alarm erupts from [src]! The fleshy hosts must know that you can access it!")) user.hive.on_shuttle_hijack(crashing_dropship) playsound(src, 'sound/misc/queen_alarm.ogg') @@ -749,12 +749,12 @@ SSevacuation.flags_scuttle &= ~FLAGS_SDEVAC_TIMELOCK switch(SSshuttle.moveShuttleToDock(shuttleId, crash_target, TRUE)) if(0) - visible_message("Shuttle departing. Please stand away from the doors.") + visible_message("Отправление шаттла. Осторожно, двери закрываются.") if(1) - to_chat(user, span_warning("Invalid shuttle requested. This shouldn't happen, please report it.")) + to_chat(user, span_warning("Неверный запрос на шаттл. Такого не должно быть! Сообщите об этом администрации.")) CRASH("moveShuttleToDock() returned 1.") else - to_chat(user, span_warning("ERROR. This shouldn't happen, please report it.")) + to_chat(user, span_warning("ОШИБКА. Такого не должно быть! Сообщите об этом администрации.")) CRASH("moveShuttleToDock() returned a non-zero-nor-one value.") /obj/machinery/computer/shuttle/marine_dropship/one @@ -1481,7 +1481,7 @@ if(admin_response == "deny") TIMER_COOLDOWN_START(src, COOLDOWN_EVACUATION, 15 SECONDS) - priority_announce("An evacuation attempt has been blocked, the engines are now restarting.", "Evacuation Attempt", ANNOUNCEMENT_COMMAND) + priority_announce("Попытка эвакуации заблокирована. Перезапуск двигателей...", "Попытка Эвакуации", ANNOUNCEMENT_COMMAND) return TRUE if(admin_response =="deny without annoncing") TIMER_COOLDOWN_START(src, COOLDOWN_EVACUATION, 15 SECONDS) diff --git a/code/modules/vehicles/armored/ammo_magazine.dm b/code/modules/vehicles/armored/ammo_magazine.dm index eae4cb05ef9..6968e6c6be2 100644 --- a/code/modules/vehicles/armored/ammo_magazine.dm +++ b/code/modules/vehicles/armored/ammo_magazine.dm @@ -1,6 +1,7 @@ //FEB 2024 NOTE: some of these are missing loading_sounds, fix it before using these ingame //Special ammo magazines for hardpoint modules. Some may not be here since you can use normal magazines on them /obj/item/ammo_magazine/tank + icon = 'icons/obj/items/ammo/tank.dmi' flags_magazine = NONE ///loading sound to play when var/loading_sound @@ -9,7 +10,7 @@ name = "high explosive LTB round" desc = "A primary armament cannon magazine" caliber = CALIBER_84MM - icon_state = "ltbammo" + icon_state = "ltb" w_class = WEIGHT_CLASS_GIGANTIC default_ammo = /datum/ammo/rocket/ltb max_rounds = 1 @@ -18,7 +19,7 @@ /obj/item/ammo_magazine/tank/ltb_cannon/apfds name = "LTB APFDS round (105mm)" desc = "A 105mm armor piercing shell with exceptional velocity and penetrating characteristics. Will pierce through walls and targets." - icon_state = "ltbammo_apfds" + icon_state = "ltb_apfds" default_ammo = /datum/ammo/bullet/tank_apfds /obj/item/ammo_magazine/tank/ltaap_chaingun @@ -36,6 +37,7 @@ desc = "A secondary armament flamethrower magazine" caliber = CALIBER_FUEL_THICK icon_state = "flametank_large" + icon = 'icons/obj/items/ammo/flamer.dmi' w_class = WEIGHT_CLASS_GIGANTIC default_ammo = /datum/ammo/flamethrower/tank_flamer max_rounds = 120 @@ -45,6 +47,7 @@ desc = "A secondary armament rocket magazine" caliber = CALIBER_68MM icon_state = "quad_rocket" + icon = 'icons/obj/items/ammo/rocket.dmi' w_class = WEIGHT_CLASS_GIGANTIC default_ammo = /datum/ammo/rocket/ap //Fun fact, AP rockets seem to be a straight downgrade from normal rockets. Maybe I'm missing something... max_rounds = 5 @@ -53,7 +56,7 @@ name = "M56 Cupola Magazine" desc = "A secondary armament MG magazine" caliber = CALIBER_10X28 - icon_state = "cupolaammo" + icon_state = "cupola" loading_sound = 'sound/weapons/guns/interact/working_the_bolt.ogg' w_class = WEIGHT_CLASS_GIGANTIC default_ammo = /datum/ammo/bullet/cupola diff --git a/code/modules/xenomorph/acidwell.dm b/code/modules/xenomorph/acidwell.dm index c20a593047e..2f2778df295 100644 --- a/code/modules/xenomorph/acidwell.dm +++ b/code/modules/xenomorph/acidwell.dm @@ -186,9 +186,10 @@ charges_used ++ if(!isxeno(stepper)) + var/mob/living/carbon/human/H = stepper stepper.next_move_slowdown += charges * 2 //Acid spray has slow down so this should too; scales with charges, Min 2 slowdown, Max 10 - stepper.apply_damage(charges * 10, BURN, BODY_ZONE_PRECISE_L_FOOT, ACID, penetration = 33) - stepper.apply_damage(charges * 10, BURN, BODY_ZONE_PRECISE_R_FOOT, ACID, penetration = 33) + stepper.apply_damage(charges * 10, BURN, BODY_ZONE_PRECISE_L_FOOT, ACID, penetration = 33 - 20 * H.get_permeability_protection()) //Wearing mimir MK1/2 will soften damage from wells by reducing AP + stepper.apply_damage(charges * 10, BURN, BODY_ZONE_PRECISE_R_FOOT, ACID, penetration = 33 - 20 * H.get_permeability_protection()) //without providing full protection against them stepper.visible_message(span_danger("[stepper] is immersed in [src]'s acid!") , \ span_danger("We are immersed in [src]'s acid!") , null, 5) playsound(stepper, "sound/bullets/acid_impact1.ogg", 10 * charges) diff --git a/code/modules/xenomorph/turret.dm b/code/modules/xenomorph/turret.dm index f686859696a..db8d94ca555 100644 --- a/code/modules/xenomorph/turret.dm +++ b/code/modules/xenomorph/turret.dm @@ -1,16 +1,17 @@ -/obj/structure/xeno/xeno_turret - icon = 'icons/Xeno/acidturret.dmi' - icon_state = XENO_TURRET_ACID_ICONSTATE +#define TURRET_HEALTH_REGEN 8 + +/obj/structure/xeno/turret name = "acid turret" desc = "A menacing looking construct of resin, it seems to be alive. It fires acid against intruders." - bound_width = 32 - bound_height = 32 + icon = 'icons/Xeno/acidturret.dmi' + icon_state = "acid_turret" + base_icon_state = "acid_turret" obj_integrity = 600 max_integrity = 1500 layer = ABOVE_MOB_LAYER density = TRUE - resistance_flags = UNACIDABLE | DROPSHIP_IMMUNE - xeno_structure_flags = IGNORE_WEED_REMOVAL|HAS_OVERLAY + resistance_flags = UNACIDABLE|DROPSHIP_IMMUNE + xeno_structure_flags = IGNORE_WEED_REMOVAL allow_pass_flags = PASS_AIR|PASS_THROW ///What kind of spit it uses var/datum/ammo/ammo = /datum/ammo/xeno/acid/heavy/turret @@ -21,25 +22,22 @@ ///Last target of the turret var/atom/last_hostile ///Potential list of targets found by scan - var/list/atom/potential_hostiles + var/list/atom/potential_hostiles = list() ///Fire rate of the target in ticks - var/firerate = 5 - ///The last time the sentry did a scan - var/last_scan_time + var/firerate = 0.5 SECONDS ///light color that gets set in initialize var/light_initial_color = LIGHT_COLOR_GREEN ///For minimap icon change if sentry is firing var/firing ///Change minimap icon if its firing or not firing -/obj/structure/xeno/xeno_turret/proc/update_minimap_icon() +/obj/structure/xeno/turret/proc/update_minimap_icon() SSminimaps.remove_marker(src) SSminimaps.add_marker(src, MINIMAP_FLAG_XENO, image('icons/UI_icons/map_blips.dmi', null, "xeno_turret[firing ? "_firing" : "_passive"]")) // RU TGMC edit - map blips -/obj/structure/xeno/xeno_turret/Initialize(mapload, _hivenumber) +/obj/structure/xeno/turret/Initialize(mapload, _hivenumber) . = ..() ammo = GLOB.ammo_list[ammo] - potential_hostiles = list() LAZYADDASSOC(GLOB.xeno_resin_turrets_by_hive, hivenumber, src) START_PROCESSING(SSobj, src) AddComponent(/datum/component/automatedfire/xeno_turret_autofire, firerate) @@ -51,57 +49,52 @@ update_icon() ///Signal handler to delete the turret when the alamo is hijacked -/obj/structure/xeno/xeno_turret/proc/destroy_on_hijack() +/obj/structure/xeno/turret/proc/destroy_on_hijack() SIGNAL_HANDLER qdel(src) -/obj/structure/xeno/xeno_turret/obj_destruction(damage_amount, damage_type, damage_flag) +/obj/structure/xeno/turret/obj_destruction(damage_amount, damage_type, damage_flag) if(damage_amount) //Spawn effects only if we actually get destroyed by damage on_destruction() + playsound(loc,'sound/effects/alien/turret_death.ogg', 70) return ..() -/obj/structure/xeno/xeno_turret/proc/on_destruction() +/obj/structure/xeno/turret/proc/on_destruction() var/datum/effect_system/smoke_spread/xeno/smoke = new /datum/effect_system/smoke_spread/xeno/acid(src) smoke.set_up(1, get_turf(src)) smoke.start() -/obj/structure/xeno/xeno_turret/Destroy() +/obj/structure/xeno/turret/Destroy() GLOB.xeno_resin_turrets_by_hive[hivenumber] -= src set_hostile(null) set_last_hostile(null) STOP_PROCESSING(SSobj, src) - playsound(loc,'sound/effects/alien/turret_death.ogg', 70) return ..() -/obj/structure/xeno/xeno_turret/ex_act(severity) +/obj/structure/xeno/turret/ex_act(severity) take_damage(severity * 5, BRUTE, BOMB) -/obj/structure/xeno/xeno_turret/fire_act(burn_level, flame_color) +/obj/structure/xeno/turret/fire_act(burn_level, flame_color) take_damage(burn_level * 2, BURN, FIRE) ENABLE_BITFIELD(resistance_flags, ON_FIRE) -/obj/structure/xeno/xeno_turret/update_overlays() +/obj/structure/xeno/turret/update_overlays() . = ..() - if(!(xeno_structure_flags & HAS_OVERLAY)) - return if(obj_integrity <= max_integrity * 0.5) - . += image('icons/Xeno/acidturret.dmi', src, "+turret_damage") + . += image(icon, src, "[base_icon_state]_damage") if(CHECK_BITFIELD(resistance_flags, ON_FIRE)) - . += image('icons/Xeno/acidturret.dmi', src, "+turret_on_fire") + . += image(icon, src, "turret_on_fire") -/obj/structure/xeno/xeno_turret/process() +/obj/structure/xeno/turret/process() //Turrets regen some HP, every 2 sec if(obj_integrity < max_integrity) obj_integrity = min(obj_integrity + TURRET_HEALTH_REGEN, max_integrity) update_icon() DISABLE_BITFIELD(resistance_flags, ON_FIRE) - if(world.time > last_scan_time + TURRET_SCAN_FREQUENCY) - scan() - last_scan_time = world.time - if(!length(potential_hostiles)) + if(!scan()) return set_hostile(get_target()) - if (!hostile) + if(!hostile) if(last_hostile) set_last_hostile(null) return @@ -112,7 +105,7 @@ set_last_hostile(hostile) SEND_SIGNAL(src, COMSIG_AUTOMATIC_SHOOTER_START_SHOOTING_AT) -/obj/structure/xeno/xeno_turret/attackby(obj/item/I, mob/living/user, params) +/obj/structure/xeno/turret/attackby(obj/item/I, mob/living/user, params) if(I.flags_item & NOBLUDGEON || !isliving(user)) return attack_hand(user) @@ -135,89 +128,87 @@ playsound(src, "alien_resin_break", 25) ///Signal handler for hard del of hostile -/obj/structure/xeno/xeno_turret/proc/unset_hostile() +/obj/structure/xeno/turret/proc/unset_hostile() SIGNAL_HANDLER hostile = null -///Signal handler for hard del of last_hostile -/obj/structure/xeno/xeno_turret/proc/unset_last_hostile() - SIGNAL_HANDLER - last_hostile = null - ///Setter for hostile with hard del in mind -/obj/structure/xeno/xeno_turret/proc/set_hostile(_hostile) - if(hostile != _hostile) - hostile = _hostile - RegisterSignal(hostile, COMSIG_QDELETING, PROC_REF(unset_hostile)) +/obj/structure/xeno/turret/proc/set_hostile(_hostile) + if(hostile == _hostile) + return + hostile = _hostile + RegisterSignal(hostile, COMSIG_QDELETING, PROC_REF(unset_hostile)) ///Setter for last_hostile with hard del in mind -/obj/structure/xeno/xeno_turret/proc/set_last_hostile(_last_hostile) +/obj/structure/xeno/turret/proc/set_last_hostile(_last_hostile) if(last_hostile) UnregisterSignal(last_hostile, COMSIG_QDELETING) last_hostile = _last_hostile ///Look for the closest human in range and in light of sight. If no human is in range, will look for xenos of other hives -/obj/structure/xeno/xeno_turret/proc/get_target() - var/distance = range + 0.5 //we add 0.5 so if a potential target is at range, it is accepted by the system - var/buffer_distance +/obj/structure/xeno/turret/proc/get_target() var/list/turf/path = list() for(var/atom/nearby_hostile AS in potential_hostiles) - if(isliving(nearby_hostile)) - var/mob/living/nearby_living_hostile = nearby_hostile - if(nearby_living_hostile.stat == DEAD) - continue - if(HAS_TRAIT(nearby_hostile, TRAIT_STEALTH)) - continue - buffer_distance = get_dist(nearby_hostile, src) - if(distance <= buffer_distance) //If we already found a target that's closer - continue path = getline(src, nearby_hostile) path -= get_turf(src) - if(!length(path)) //Can't shoot if it's on the same turf - continue - var/blocked = FALSE + var/blocked = FALSE //LoF Broken; stop checking; we can't proceed further. for(var/turf/T AS in path) if(IS_OPAQUE_TURF(T) || T.density && !(T.allow_pass_flags & PASS_PROJECTILE)) blocked = TRUE - break //LoF Broken; stop checking; we can't proceed further. + break for(var/obj/machinery/MA in T) - if(MA.opacity || MA.density && !(MA.allow_pass_flags & PASS_PROJECTILE)) - blocked = TRUE - break //LoF Broken; stop checking; we can't proceed further. + if(!MA.opacity) + continue + if(!MA.density && MA.allow_pass_flags & PASS_PROJECTILE) + continue + blocked = TRUE + break for(var/obj/structure/S in T) - if(S.opacity || S.density && !(S.allow_pass_flags & PASS_PROJECTILE)) - blocked = TRUE - break //LoF Broken; stop checking; we can't proceed further. - if(!blocked) - distance = buffer_distance - . = nearby_hostile - -///Return TRUE if a possible target is near -/obj/structure/xeno/xeno_turret/proc/scan() + if(!S.opacity) + continue + if(!S.density && S.allow_pass_flags & PASS_PROJECTILE) + continue + blocked = TRUE + break + if(blocked) + continue + return nearby_hostile + +///Checks the nearby mobs for eligability. If they can be targets it stores them in potential_targets. Returns TRUE if there are targets, FALSE if not. +/obj/structure/xeno/turret/proc/scan() potential_hostiles.Cut() - for (var/mob/living/carbon/human/nearby_human AS in cheap_get_humans_near(src, TURRET_SCAN_RANGE)) + for(var/mob/living/carbon/human/nearby_human AS in cheap_get_humans_near(src, range)) if(nearby_human.stat == DEAD) continue if(nearby_human.get_xeno_hivenumber() == hivenumber) continue + if(HAS_TRAIT(nearby_human, TRAIT_STEALTH)) + continue potential_hostiles += nearby_human - for (var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(src, range)) + for(var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(src, range)) if(GLOB.hive_datums[hivenumber] == nearby_xeno.hive) continue if(nearby_xeno.stat == DEAD) continue + if(HAS_TRAIT(nearby_xeno, TRAIT_STEALTH)) + continue potential_hostiles += nearby_xeno - for(var/obj/vehicle/unmanned/vehicle AS in GLOB.unmanned_vehicles) - if(vehicle.z == z && get_dist(vehicle, src) <= range) - potential_hostiles += vehicle - for(var/obj/vehicle/sealed/mecha/mech AS in GLOB.mechas_list) - if(mech.z == z && get_dist(mech, src) <= range) - potential_hostiles += mech + for(var/obj/vehicle/unmanned/nearby_unmanned_vehicle AS in cheap_get_unmanned_vehicles_near(src, range)) + potential_hostiles += nearby_unmanned_vehicle + for(var/obj/vehicle/sealed/mecha/nearby_mech AS in cheap_get_mechs_near(src, range)) + var/list/driver_list = nearby_mech.return_drivers() + if(!length(driver_list)) + continue + var/mob/living/carbon/human/human_occupant = driver_list[1] + if(human_occupant.get_xeno_hivenumber() == hivenumber) // what if zombie rides a mech? + continue + potential_hostiles += nearby_mech + return potential_hostiles ///Signal handler to make the turret shoot at its target -/obj/structure/xeno/xeno_turret/proc/shoot() +/obj/structure/xeno/turret/proc/shoot() SIGNAL_HANDLER if(!hostile) SEND_SIGNAL(src, COMSIG_AUTOMATIC_SHOOTER_STOP_SHOOTING_AT) @@ -229,40 +220,67 @@ newshot.generate_bullet(ammo) newshot.def_zone = pick(GLOB.base_miss_chance) newshot.fire_at(hostile, null, src, ammo.max_range, ammo.shell_speed) - if(istype(ammo, /datum/ammo/xeno/hugger)) - var/datum/ammo/xeno/hugger/hugger_ammo = ammo - newshot.color = initial(hugger_ammo.hugger_type.color) - hugger_ammo.hivenumber = hivenumber firing = TRUE update_minimap_icon() -/obj/structure/xeno/xeno_turret/sticky +/obj/structure/xeno/turret/sticky name = "Sticky resin turret" - icon = 'icons/Xeno/acidturret.dmi' - icon_state = XENO_TURRET_STICKY_ICONSTATE desc = "A menacing looking construct of resin, it seems to be alive. It fires resin against intruders." + icon_state = "resin_turret" + base_icon_state = "resin_turret" light_initial_color = LIGHT_COLOR_PURPLE ammo = /datum/ammo/xeno/sticky/turret - firerate = 5 -/obj/structure/xeno/xeno_turret/sticky/on_destruction() - for(var/i = 1 to 20) // maybe a bit laggy +/obj/structure/xeno/turret/sticky/on_destruction() + for(var/i in 1 to 20) // maybe a bit laggy var/obj/projectile/new_proj = new(src) new_proj.generate_bullet(ammo) - new_proj.fire_at(null, src, range = rand(1, 4), angle = rand(1, 360), recursivity = TRUE) + new_proj.fire_at(null, src, src, range = rand(1, 4), angle = rand(1, 360), recursivity = TRUE) -/obj/structure/xeno/xeno_turret/hugger_turret +/obj/structure/xeno/turret/facehugger name = "hugger turret" - icon_state = "hugger_turret" desc = "A menacing looking construct of resin, it seems to be alive. It fires huggers against intruders." + icon_state = "hugger_turret" + base_icon_state = "hugger_turret" obj_integrity = 400 max_integrity = 400 light_initial_color = LIGHT_COLOR_BROWN ammo = /datum/ammo/xeno/hugger firerate = 5 SECONDS -/obj/structure/xeno/xeno_turret/hugger_turret/on_destruction() - for(var/i = 1 to 5) +/obj/structure/xeno/turret/facehugger/shoot() + if(!hostile) + SEND_SIGNAL(src, COMSIG_AUTOMATIC_SHOOTER_STOP_SHOOTING_AT) + firing = FALSE + update_minimap_icon() + return + face_atom(hostile) + var/obj/projectile/newshot = new(loc) + newshot.generate_bullet(ammo) + newshot.def_zone = pick(GLOB.base_miss_chance) + newshot.fire_at(hostile, null, src, ammo.max_range, ammo.shell_speed) + var/datum/ammo/xeno/hugger/hugger_ammo = ammo + newshot.color = initial(hugger_ammo.hugger_type.color) + hugger_ammo.hivenumber = hivenumber + firing = TRUE + update_minimap_icon() + +/obj/structure/xeno/turret/facehugger/on_destruction() + for(var/i in 1 to 5) var/obj/projectile/new_proj = new(src) new_proj.generate_bullet(ammo) - new_proj.fire_at(null, src, range = rand(1, 3), angle = rand(1, 360), recursivity = TRUE) + new_proj.fire_at(null, src, src, range = rand(1, 3), angle = rand(1, 360), recursivity = TRUE) + +/obj/structure/xeno/turret/facehugger/attack_ghost(mob/dead/observer/user) + . = ..() + + var/datum/hive_status/hive = GLOB.hive_datums[hivenumber] + if(!hive.can_spawn_as_hugger(user)) + return FALSE + + var/mob/living/carbon/xenomorph/facehugger/new_hugger = new(get_turf(src)) + new_hugger.transfer_to_hive(hivenumber) + new_hugger.transfer_mob(user) + return TRUE + +#undef TURRET_HEALTH_REGEN diff --git a/html/changelogs/AutoChangeLog-pr-739.yml b/html/changelogs/AutoChangeLog-pr-739.yml new file mode 100644 index 00000000000..7db99ca010a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-739.yml @@ -0,0 +1,4 @@ +author: "definitelynotspaghetti" +delete-after: True +changes: + - bugfix: "Создать спайдерлинга больше нельзя если у абилки нет зарядов" \ No newline at end of file diff --git a/html/changelogs/archive/2024-11.yml b/html/changelogs/archive/2024-11.yml index eb276bde2a3..f6fa5400fb9 100644 --- a/html/changelogs/archive/2024-11.yml +++ b/html/changelogs/archive/2024-11.yml @@ -515,3 +515,127 @@ \u0442 \u043F\u0430\u0442\u0440\u043E\u043D\u044B \u043D\u0430 \u0441\u043A\u0430\ \u0443\u0442\u0441\u043A\u0443\u044E \u0432\u0438\u043D\u0442\u043E\u0432\u043A\ \u0443." +2024-11-28: + Helg2: + - bugfix: "\u0418\u0441\u043F\u0440\u0430\u0432\u0438\u043B \u0442\u043E \u0447\u0442\ + \u043E \"Jump To Area\" \u043D\u0435 \u0440\u0430\u0431\u043E\u0442\u0430\u043B\ + ." +2024-11-29: + CheBokJam: + - balance: "\u0414\u043E\u0431\u0430\u0432\u0438\u043B \u0448\u0430\u0442\u0442\u0435\ + \u0440 (\u043C\u0438\u043D\u0443\u0441 20% \u0431\u0440\u043E\u043D\u0438) \u043D\ + \u0430 3 \u0441\u0435\u043A\u0443\u043D\u0434\u044B." + - balance: "\u0423\u0440\u043E\u043D 25 -> 12, \u0410\u041F -15 -> 20." + - balance: "\u0421\u043D\u0438\u0436\u0435\u043D\u043E \u043A\u043E\u043B-\u0432\ + \u043E \u043F\u0430\u0442\u0440\u043E\u043D\u043E\u0432 \u0432 \u043F\u0430\u0432\ + \u0435\u0440\u043F\u0430\u043A\u0435 \u0441 2000 \u0434\u043E 1000." + Helg2: + - map: "\u041A\u0435\u0439\u043A\u0430\u0440\u0434 \u0430\u0443\u0442\u0435\u043D\ + \u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u044B \u0442\u0435\u043F\ + \u0435\u0440\u044C \u0435\u0441\u0442\u044C \u043D\u0435 \u0442\u043E\u043B\u044C\ + \u043A\u043E \u043D\u0430 \u043C\u043E\u0441\u0442\u0438\u043A\u0435, \u043D\ + \u043E \u0438 \u0432 \u043A\u043E\u043C\u043D\u0430\u0442\u0430\u0445 \u043A\ + \u043E\u043C\u043C\u0430\u043D\u0434\u043E\u0432\u0430\u043D\u0438\u044F." + - bugfix: "\u0418\u0441\u043F\u0440\u0430\u0432\u0438\u043B \u0442\u043E \u0447\u0442\ + \u043E \u0440\u0435\u0446\u0435\u043F\u0442\u044B \u0434\u043B\u044F \u0437\u0430\ + \u0432\u043E\u0434\u0430 \u0442\u0440\u0435\u0431\u0443\u044E\u0449\u0438\u0435\ + \ \u0441\u0442\u0435\u043A\u043B\u043E, \u043D\u0435 \u043F\u0440\u0438\u043D\ + \u0438\u043C\u0430\u043B\u0438 \u0441\u0442\u0435\u043A\u043B\u043E." + - balance: "\u0422\u043E\u0447\u043D\u0430\u044F \u0434\u0438\u0441\u0442\u0430\u043D\ + \u0446\u0438\u044F \u0441\u0442\u0440\u0435\u043B\u044C\u0431\u044B \u0441\u0433\ + 29 \u043F\u043E\u0434\u043D\u044F\u0442\u0430 \u0441 8 \u0434\u043E 20. \u041F\ + \u0440\u043E\u0431\u0438\u0442\u0438\u0435 \u043F\u043E\u0434\u043D\u044F\u0442\ + \u043E \u0441 25 \u0434\u043E 45. \u0417\u0430\u0434\u0435\u0440\u0436\u043A\ + \u0430 \u043C\u0435\u0436\u0434\u0443 \u0432\u044B\u0441\u0442\u0440\u0435\u043B\ + \u0430\u043C\u0438 \u0443\u043C\u0435\u043D\u044C\u0448\u0435\u043D\u0430 \u0441\ + \ 0.2 \u0441\u0435\u043A\u0443\u043D\u0434 \u0434\u043E 0.15." + - qol: "\u0418\u0437\u043C\u0435\u043D\u0438\u043B \u0434\u0435\u0444\u043E\u043B\ + \u0442\u043D\u044B\u0439 \u043A\u0435\u0439\u0431\u0438\u043D\u0434 \u0434\u043B\ + \u044F \u043F\u0440\u044B\u0436\u043A\u0430 \u0441 \u043F\u0440\u043E\u0431\u0435\ + \u043B\u0430 \u043D\u0430 V." + - bugfix: "\u0418\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043A\u043D\u043E\ + \u043F\u043A\u0430 \u0434\u043B\u044F \u0431\u0443\u0441\u0442\u044B \u0442\u0435\ + \u043F\u0435\u0440\u044C \u043D\u0435 \u0432\u044B\u0431\u0438\u0432\u0430\u0435\ + \u0442\u0441\u044F \u0438\u0437 \u043E\u0431\u0449\u0435\u0439 \u0442\u0435\u043C\ + \u044B \u043E\u0441\u0442\u0430\u043B\u044C\u043D\u044B\u0445 \u043A\u043D\u043E\ + \u043F\u043E\u043A." + - rscdel: "\u0423\u0434\u0430\u043B\u0438\u043B \u0410\u0410 \u0443 \u043A\u043B\ + \u043E\u0443\u043D\u0430." + - image: "\u0414\u043E\u0431\u0430\u0432\u0438\u043B \u0437\u0435\u0440\u043A\u0430\ + \u043B\u0430\u043C \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\ + \u0435 \u0441\u0442\u043E\u0440\u043E\u043D." + homexp13: + - rscadd: Added steel crest defender strain + "\u041E\u0434\u0438\u043D\u043E\u043A\u0438\u0439 \u0410\u0441\u043A\u0435\u0442": + - balance: "\u041C\u0435\u0442\u0430\u0431\u043E\u043B\u0438\u0437\u0430\u0446\u0438\ + \u044F \u041E\u043A\u0441\u0438\u043A\u043E\u0434\u043E\u043D\u0430 \u043F\u0440\ + \u0438\u0432\u0435\u0434\u0435\u043D\u0430 \u043A \u0441\u0442\u0430\u043D\u0434\ + \u0430\u0440\u0442\u043D\u043E\u0439." +2024-11-30: + Basia: + - spellcheck: "\u041F\u0435\u0440\u0435\u0432\u043E\u0434 \u0430\u043D\u043E\u043D\ + \u0441\u043E\u0432 \u043D\u0430 \u0440\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\ + \u0437\u044B\u043A." + - sound: "\u041F\u0435\u0440\u0435\u043E\u0437\u0432\u0443\u0447\u043A\u0430 \u0430\ + \u043D\u043E\u043D\u0441\u043E\u0432 \u043D\u0430 \u0440\u0443\u0441\u0441\u043A\ + \u0438\u0439 \u044F\u0437\u044B\u043A." + CheBokJam: + - bugfix: "\u0411\u043E\u043B\u044C\u0448\u0435 \u0432 \u043A\u0430\u043C\u043D\u0435\ + \ \u041A\u0438\u043D\u0433\u0430 \u043D\u0435\u043B\u044C\u0437\u044F \u0443\ + \u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C/\u0441\u043D\u044F\u0442\ + \u044C \u043B\u044E\u0431\u0443\u044E \u0440\u0430\u0441\u043A\u043B\u0430\u0434\ + \u044B\u0432\u0430\u0435\u043C\u0443\u044E \u0432\u0435\u0449\u044C." + - balance: "\u0417\u0430\u0449\u0438\u0442\u0430 \u043C\u0438\u043C\u0438\u0440\u0430\ + \ 1 \u043E\u0442 \u043A\u0438\u0441\u043B\u043E\u0442\u044B 5 -> 10, \u0437\u0430\ + \u0449\u0438\u0442\u0430 \u043E\u0442 \u0433\u0430\u0437\u043E\u0432 \u0441\u043D\ + \u0438\u0436\u0435\u043D\u0430 \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430\ + ." + - balance: "\u0417\u0430\u0449\u0438\u0442\u0430 \u043C\u0438\u043C\u0438\u0440\u0430\ + \ 2 \u043E\u0442 \u043A\u0438\u0441\u043B\u043E\u0442\u044B 10 -> 25." + - balance: "\u0421\u043D\u0438\u0436\u0435\u043D\u0438\u0435 \u0443\u0440\u043E\u043D\ + \u0430 \u043E\u0442 \u043A\u043E\u043B\u043E\u0434\u0446\u0435\u0432 \u0432\ + \ \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438 \u043E\u0442\ + \ \u043D\u0430\u0434\u0435\u0442\u043E\u0433\u043E \u0448\u043B\u0435\u043C\u0430\ + \ \u0441 \u043C\u0438\u043C\u0438\u0440\u043E\u043C + \u0432\u0435\u0440\u0441\ + \u0438\u0438 \u043C\u0438\u043C\u0438\u0440\u0430." + - balance: "\u0426\u0435\u043D\u0430\u043C \u043C\u0438\u043C\u0438\u0440\u0430\ + \ 2 \u0432 \u043A\u0430\u0440\u0433\u043E 120 -> 160." + Helg2: + - rscdel: "\u0423\u0434\u0430\u043B\u0438\u043B \u0437\u0430\u0442\u0435\u043C\u043D\ + \u0435\u043D\u0438\u0435 \u043F\u0440\u0438 \u044D\u0432\u043E\u043B\u044E\u0446\ + \u0438\u0438 \u043A\u0441\u0435\u043D\u043E\u0441\u043E\u0432." + - bugfix: "\u0418\u0441\u043F\u0440\u0430\u0432\u0438\u043B \u0442\u043E \u0447\u0442\ + \u043E \u043E\u043F\u043E\u0432\u0435\u0449\u0435\u043D\u0438\u0435 \u043E \u043F\ + \u043E\u044F\u0432\u043B\u0435\u043D\u0438\u0438 \u043F\u0440\u0430\u0432\u0438\ + \u0442\u0435\u043B\u044F \u0445\u0430\u0439\u0432\u0430 \u043D\u0435\u043F\u0440\ + \u0430\u0432\u0438\u043B\u044C\u043D\u043E \u043E\u0442\u043E\u0431\u0440\u0430\ + \u0436\u0430\u043B\u043E \u0435\u0433\u043E \u0438\u043C\u044F." + - rscdel: "\u0423\u0434\u0430\u043B\u0438\u043B \u0431\u0435\u0441\u043F\u043B\u0430\ + \u0442\u043D\u044B\u0435 \u043A\u0430\u0440\u0433\u043E \u0431\u043E\u0435\u043F\ + \u0440\u0438\u043F\u0430\u0441\u044B \u0438\u0437 \u043A\u0430\u0440\u0433\u043E\ + \ \u0432\u0435\u043D\u0434\u043E\u0440\u0430 \u0432\u043E \u0432\u043A\u043B\ + \u0430\u0434\u043A\u0435 \"Surplus Special Equipment\" (\u0448\u0430\u0445\u0438\ + \u0434\u043E\u043A)" + - bugfix: "\u0418\u0441\u043F\u0440\u0430\u0432\u0438\u043B \u0442\u043E \u0447\u0442\ + \u043E \u0442\u0430\u0439\u043C\u0435\u0440 \u0441\u043C\u0435\u0440\u0442\u0438\ + \ \u04224 \u043A\u0441\u0435\u043D\u043E\u0441\u043E\u0432 \u043D\u0435 \u0440\ + \u0430\u0431\u043E\u0442\u0430\u043B." + - code_imp: "\u0410\u0431\u0438\u043B\u043A\u0438 \u0442\u0435\u043F\u0435\u0440\ + \u044C \u043D\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u044E\u0442\u0441\ + \u044F \u043A\u043E\u0433\u0434\u0430 \u043D\u0435 \u043D\u0443\u0436\u043D\u043E\ + , \u0438 \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u044E\u0442\u0441\u044F\ + \ \u043A\u043E\u0433\u0434\u0430 \u043D\u0443\u0436\u043D\u043E." + - admin: "\u041F\u0440\u043E\u0441\u0442\u0440\u0430\u043D\u0441\u0442\u0432\u0435\ + \u043D\u043D\u044B\u0439 \u0430\u0433\u0435\u043D\u0442 \u0442\u0435\u043F\u0435\ + \u0440\u044C \u0438\u043C\u0435\u0435\u0442 \u043D\u0430\u0443\u0448\u043D\u0438\ + \u043A." + MalorMorfin: + - bugfix: "\u0425\u0430\u0439\u0432 \u041C\u0430\u0439\u043D\u0434 \u0431\u043E\u043B\ + \u044C\u0448\u0435 \u043D\u0435 \u043E\u0441\u0442\u0430\u0432\u043B\u044F\u0435\ + \u0442 \u043A\u0438\u0441\u043B\u043E\u0442\u043D\u044B\u0439 \u0441\u043B\u0435\ + \u0434 \u0432 \u043F\u0440\u0438\u0437\u0440\u0430\u0447\u043D\u043E\u0439 \u0444\ + \u043E\u0440\u043C\u0435." + - bugfix: "\u041A\u0441\u0435\u043D\u043E\u043C\u043E\u0440\u0444\u044B \u0432 \u0432\ + \u0435\u043D\u0442\u0438\u043B\u044F\u0446\u0438\u0438 \u043D\u0435 \u043E\u0441\ + \u0442\u0430\u0432\u043B\u044F\u044E\u0442 \u043A\u0438\u0441\u043B\u043E\u0442\ + \u043D\u044B\u0439 \u0441\u043B\u0435\u0434." diff --git a/html/changelogs/archive/2024-12.yml b/html/changelogs/archive/2024-12.yml new file mode 100644 index 00000000000..76b297e7405 --- /dev/null +++ b/html/changelogs/archive/2024-12.yml @@ -0,0 +1,113 @@ +2024-12-01: + Helg2: + - image: "\u0414\u043E\u0431\u0430\u0432\u0438\u043B \u0441\u043F\u0440\u0430\u0439\ + \u0442 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0435\ + \u0439 \u0431\u0430\u0437\u043E\u0432\u043E\u0439 \u0440\u0430\u043A\u0435\u0442\ + \u044B." + - image: "\u0421\u043F\u0440\u0430\u0439\u0442\u044B \u0434\u043B\u044F \u0431\u043E\ + \u043B\u044C\u0448\u0438\u043D\u0441\u0442\u0432\u0430 \u0430\u043F, \u0445\u043F\ + \ \u0438 \u0437\u0430\u0436\u0438\u0433\u0430\u0442\u0435\u043B\u044C\u043D\u044B\ + \u0445 \u043C\u0430\u0433\u0430\u0437\u0438\u043D\u043E\u0432 \u043F\u0435\u0440\ + \u0435\u0434\u0435\u043B\u0430\u043D\u044B \u043F\u043E\u0434 \u0433\u0440\u0435\ + \u0439\u0441\u043A\u0435\u0439\u043B." + - code_imp: "\u0420\u0430\u0441\u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\ + \u043B \u0441\u043F\u0440\u0430\u0439\u0442\u044B \u0430\u043C\u0443\u043D\u0438\ + \u0446\u0438\u0438 \u043F\u043E \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u044B\ + \u043C \u0444\u0430\u0439\u043B\u0430\u043C." +2024-12-02: + CheBokJam: + - map: "\u041D\u0430 \u0442\u0430\u043B\u043E\u0441 \u0434\u043E\u0431\u0430\u0432\ + \u043B\u0435\u043D\u044B \u0437\u0430\u0440\u044F\u0434\u043D\u0438\u043A\u0438\ + \ \u0434\u043B\u044F \u0434\u0435\u0444\u0438\u0431\u0440\u0438\u043B\u043B\u044F\ + \u0442\u043E\u0440\u043E\u0432: \u0432 \u0431\u0443\u0434\u043A\u0435 \u0443\ + \u0447\u0451\u043D\u043E\u0433\u043E, \u0432 \u0433\u043B\u0430\u0432\u043D\u043E\ + \u043C \u0445\u043E\u043B\u0435 \u043C\u0435\u0434 \u043F\u0443\u043D\u043A\u0442\ + \u0430 \u0438 \u043D\u0430 \u0441\u043A\u043B\u0430\u0434\u0435." + MrFloppa: + - rscadd: "\u0425\u0430\u0439\u0432\u043C\u0430\u0439\u043D\u0434 \u0442\u0435\u043F\ + \u0435\u0440\u044C \u043F\u043E\u043D\u0438\u043C\u0430\u0435\u0442 \u044F\u0437\ + \u044B\u043A \u043C\u0430\u0440\u043E\u0432" + mister-onion: + - rscadd: "Prime \u0440\u0430\u043D\u0433 \u043A\u0441\u0435\u043D\u043E\u043C\u043E\ + \u0440\u0444\u043E\u0432 \u0431\u044B\u043B \u0438\u0437\u043C\u0435\u043D\u0435\ + \u043D \u043D\u0430 Primal." + - balance: "\u043A\u0438\u043D\u0433 \u0442\u0435\u043F\u0435\u0440\u044C \u0438\ + \u043C\u0435\u0435\u0442 \u0438\u043C\u043C\u0443\u043D\u0438\u0442\u0435\u0442\ + \ \u043A \u043C\u043E\u043B\u043E\u0442\u043A\u0443" +2024-12-03: + Helg2: + - bugfix: "\u041F\u0440\u043E\u0434\u0430\u0436\u0430 \u043B\u044E\u0434\u0435\u0439\ + \ \u0432 \u043A\u0430\u0440\u0433\u043E \u0442\u0435\u043F\u0435\u0440\u044C\ + \ \u043F\u0440\u0438\u043D\u043E\u0441\u0438\u0442 \u043E\u0447\u043A\u0438\ + , \u043A\u0430\u043A \u0438 \u0434\u043E\u043B\u0436\u043D\u043E." + - bugfix: "\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0430 \u043F\u043E\ + \ \u043F\u0440\u043E\u0434\u0430\u0436\u0435 \u043A\u0441\u0435\u043D\u043E\u0441\ + \u043E\u0432 \u0432 \u043A\u0430\u0440\u0433\u043E \u0442\u0435\u043F\u0435\u0440\ + \u044C \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442." + - rscadd: "\u0418\u0437 \u0445\u0430\u0433\u0433\u0435\u0440 \u0442\u0443\u0440\u0435\ + \u043B\u0438 \u0442\u0435\u043F\u0435\u0440\u044C \u043C\u043E\u0436\u043D\u043E\ + \ \u043F\u043E\u044F\u0432\u0438\u0442\u044C\u0441\u044F \u0432 \u0440\u043E\ + \u043B\u0438 \u0440\u0430\u0437\u0443\u043C\u043D\u043E\u0433\u043E \u0445\u0430\ + \u0433\u0433\u0435\u0440\u0430." + - balance: "\u0425\u0430\u0433\u0433\u0435\u0440\u044B \u0438\u0437 \u0445\u0430\ + \u0433\u0433\u0435\u0440 \u0442\u0443\u0440\u0435\u043B\u0438 \u0442\u0435\u043F\ + \u0435\u0440\u044C \u043F\u0440\u0438 \u043F\u0440\u044F\u043C\u043E\u043C \u043F\ + \u043E\u043F\u0430\u0434\u0430\u043D\u0438\u0438 \u043F\u043E \u043C\u043E\u0431\ + \u0443 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043A \u043D\u0435\u043C\ + \u0443 \u0446\u0435\u043F\u043B\u044F\u044E\u0442\u0441\u044F. \u041F\u0440\u0438\ + \ \u043F\u043E\u043F\u0430\u0434\u0430\u043D\u0438\u0438 \u0432 \u043E\u0431\ + \u044A\u0435\u043A\u0442/\u0442\u0443\u0440\u0444 \u043E\u043D\u0438 \u0432\u043C\ + \u0435\u0441\u0442\u043E \u0442\u043E\u0433\u043E \u0447\u0442\u043E\u0431\u044B\ + \ \u043D\u0430\u0447\u0438\u043D\u0430\u0442\u044C \u0441\u043F\u044F\u0449\u0438\ + \u043C\u0438, \u0441\u0440\u0430\u0437\u0443 \u044F\u0432\u043B\u044F\u044E\u0442\ + \u0441\u044F \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u043C\u0438, \u0447\u0442\ + \u043E \u0443\u043C\u0435\u043D\u044C\u0448\u0430\u0435\u0442 \u0432\u0440\u0435\ + \u043C\u0435\u043D\u043D\u043E\u0435 \u043E\u043A\u043D\u043E \u0441 3 \u0441\ + \u0435\u043A\u0443\u043D\u0434 \u0434\u043E 1-\u0443\u0445." + - bugfix: "\u0417\u0432\u0443\u043A \u0441\u043C\u0435\u0440\u0442\u0438 \u0442\u0443\ + \u0440\u0435\u043B\u0438 \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u0432\ + \u043E\u0441\u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0441\ + \u044F \u043F\u0440\u0438 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0438 \u0442\ + \u0443\u0440\u0435\u043B\u0438." + - bugfix: "\u0418\u0441\u043F\u0440\u0430\u0432\u0438\u043B \u0442\u043E \u0447\u0442\ + \u043E \u0443\u043D\u0438\u0447\u0442\u043E\u0436\u0435\u043D\u0438\u0435 \u0440\ + \u0435\u0437\u0438\u043D\u043E\u0432\u043E\u0439/\u0445\u0430\u0433\u0433\u0435\ + \u0440 \u0442\u0443\u0440\u0435\u043B\u0438 \u043D\u0435 \u0432\u044B\u0441\u0442\ + \u0440\u0435\u043B\u0438\u0432\u0430\u043B\u043E \u043F\u043E\u0434\u0445\u043E\ + \u0434\u044F\u0449\u0438\u043C\u0438 \u0441\u043D\u0430\u0440\u044F\u0434\u0438\ + \ \u0432\u043E \u0432\u0441\u0435 \u0441\u0442\u043E\u0440\u043E\u043D\u044B\ + ." + - image: "\u041A\u0441\u0435\u043D\u043E \u0442\u0443\u0440\u0435\u043B\u044F\u043C\ + \ \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u044B \u043E\u0442\u043B\u0438\ + \u0447\u0430\u044E\u0449\u0438\u0435\u0441\u044F \u043E\u0442 \u0434\u0440\u0443\ + \u0433 \u0434\u0440\u0443\u0433\u0430 \u043E\u0432\u0435\u0440\u043B\u0435\u0438\ + \ \u0434\u043B\u044F \u0440\u0435\u0433\u0435\u043D\u0430 \u0446\u0435\u043B\ + \u043E\u0441\u0442\u043D\u043E\u0441\u0442\u0438 \u0441\u0442\u0440\u0443\u043A\ + \u0442\u0443\u0440\u044B." + - code_imp: "\u041A\u0441\u0435\u043D\u043E \u0442\u0443\u0440\u0435\u043B\u0438\ + \ \u0442\u0435\u043F\u0435\u0440\u044C \u0441\u043A\u0430\u043D\u0438\u0440\u0443\ + \u044E\u0442 \u043E\u043A\u0440\u0443\u0433\u0443 \u043D\u0430 \u043F\u0440\u0435\ + \u0434\u043C\u0435\u0442 \u043F\u043E\u0434\u0445\u043E\u0434\u044F\u0449\u0435\ + \u0439 \u0446\u0435\u043B\u0438 \u043D\u0435 \u0440\u0430\u0437 \u0432 10 \u0441\ + \u0435\u043A\u0443\u043D\u0434, \u0430 \u043A\u0430\u0436\u0434\u044B\u0439\ + \ \u0442\u0438\u043A." + - code_imp: "\u0424\u0430\u0439\u043B\u044B \u0440\u0430\u0441 \u0438 \u044D\u043C\ + \u043E\u0446\u0438\u0439 \u043B\u044E\u0434\u0435\u0439 \u0440\u0430\u0441\u0441\ + \u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u044B \u0432 \u043E\u0442\ + \u0434\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u0430\u043F\u043A\u0438." + - qol: "\u0414\u043B\u044F \u0441\u043D\u044F\u0442\u0438\u044F \u0445\u0430\u0433\ + \u0433\u0435\u0440\u0430 \u0441 \u043B\u0438\u0446\u0430 \u0442\u0435\u043F\u0435\ + \u0440\u044C \u0435\u0441\u0442\u044C \u0441\u043E\u0431\u0441\u0442\u0432\u0435\ + \u043D\u043D\u043E\u0435 \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\ + \u0438\u0435." + - code_imp: "`getflaticon()` \u043E\u0442\u0432\u0435\u0447\u0430\u044E\u0449\u0438\ + \u0439 \u0437\u0430 \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0438 \u0432\ + \ \u043F\u0440\u0435\u0444. \u043C\u0435\u043D\u044E \u0431\u044B\u043B \u043D\ + \u0435\u043C\u043D\u043E\u0433\u043E \u043E\u043F\u0442\u0438\u043C\u0438\u0437\ + \u0438\u0440\u043E\u0432\u0430\u043D." + - code_imp: "\u0420\u0430\u0441\u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\ + \u043B Supply.dm" + homexp13: + - balance: "\u043C\u0443\u0442\u0430\u0446\u0438\u0438 \u0442\u0435\u043F\u0435\u0440\ + \u044C \u0441\u043E\u0445\u0440\u0430\u043D\u044F\u044E\u0442\u0441\u044F \u043F\ + \u0440\u0438 \u044D\u0432\u043E\u043B\u0432\u0435." diff --git a/icons/Xeno/acidturret.dmi b/icons/Xeno/acidturret.dmi index eaec2436421..9fd15a13f6a 100644 Binary files a/icons/Xeno/acidturret.dmi and b/icons/Xeno/acidturret.dmi differ diff --git a/icons/Xeno/actions.dmi b/icons/Xeno/actions.dmi index 92e37923d6f..d1dd26d3cbc 100644 Binary files a/icons/Xeno/actions.dmi and b/icons/Xeno/actions.dmi differ diff --git a/icons/Xeno/castes/defender/steel_crest.dmi b/icons/Xeno/castes/defender/steel_crest.dmi new file mode 100644 index 00000000000..414a578f107 Binary files /dev/null and b/icons/Xeno/castes/defender/steel_crest.dmi differ diff --git a/icons/effects/progressicons.dmi b/icons/effects/progressicons.dmi index 659db025d1d..165cd4added 100644 Binary files a/icons/effects/progressicons.dmi and b/icons/effects/progressicons.dmi differ diff --git a/icons/obj/items/ammo.dmi b/icons/obj/items/ammo.dmi deleted file mode 100644 index 36fe7d7ebdf..00000000000 Binary files a/icons/obj/items/ammo.dmi and /dev/null differ diff --git a/icons/obj/items/ammo/box.dmi b/icons/obj/items/ammo/box.dmi new file mode 100644 index 00000000000..f346d1e21c5 Binary files /dev/null and b/icons/obj/items/ammo/box.dmi differ diff --git a/icons/obj/items/ammo/energy.dmi b/icons/obj/items/ammo/energy.dmi new file mode 100644 index 00000000000..a8d52c386b9 Binary files /dev/null and b/icons/obj/items/ammo/energy.dmi differ diff --git a/icons/obj/items/ammo/flamer.dmi b/icons/obj/items/ammo/flamer.dmi new file mode 100644 index 00000000000..da271eba147 Binary files /dev/null and b/icons/obj/items/ammo/flamer.dmi differ diff --git a/icons/obj/items/ammo/handful.dmi b/icons/obj/items/ammo/handful.dmi new file mode 100644 index 00000000000..46da9d0591f Binary files /dev/null and b/icons/obj/items/ammo/handful.dmi differ diff --git a/icons/obj/items/ammo/magazine.dmi b/icons/obj/items/ammo/magazine.dmi new file mode 100644 index 00000000000..ecc7b1e2e79 Binary files /dev/null and b/icons/obj/items/ammo/magazine.dmi differ diff --git a/icons/obj/items/ammo/misc.dmi b/icons/obj/items/ammo/misc.dmi new file mode 100644 index 00000000000..04ccd5b9df6 Binary files /dev/null and b/icons/obj/items/ammo/misc.dmi differ diff --git a/icons/obj/items/ammo/packet.dmi b/icons/obj/items/ammo/packet.dmi new file mode 100644 index 00000000000..35411f5bdc6 Binary files /dev/null and b/icons/obj/items/ammo/packet.dmi differ diff --git a/icons/obj/items/ammo/pistol.dmi b/icons/obj/items/ammo/pistol.dmi new file mode 100644 index 00000000000..db124563518 Binary files /dev/null and b/icons/obj/items/ammo/pistol.dmi differ diff --git a/icons/obj/items/ammo/revolver.dmi b/icons/obj/items/ammo/revolver.dmi new file mode 100644 index 00000000000..fdf1a230b1f Binary files /dev/null and b/icons/obj/items/ammo/revolver.dmi differ diff --git a/icons/obj/items/ammo/rocket.dmi b/icons/obj/items/ammo/rocket.dmi new file mode 100644 index 00000000000..41a4d64c13a Binary files /dev/null and b/icons/obj/items/ammo/rocket.dmi differ diff --git a/icons/obj/items/ammo/smg.dmi b/icons/obj/items/ammo/smg.dmi new file mode 100644 index 00000000000..6ad205e3093 Binary files /dev/null and b/icons/obj/items/ammo/smg.dmi differ diff --git a/icons/obj/items/ammo/stationary.dmi b/icons/obj/items/ammo/stationary.dmi new file mode 100644 index 00000000000..2c516c9cd66 Binary files /dev/null and b/icons/obj/items/ammo/stationary.dmi differ diff --git a/icons/obj/items/ammo/tank.dmi b/icons/obj/items/ammo/tank.dmi new file mode 100644 index 00000000000..bacaad1cd53 Binary files /dev/null and b/icons/obj/items/ammo/tank.dmi differ diff --git a/icons/obj/watercloset.dmi b/icons/obj/watercloset.dmi index c18b9c79d27..571ed69013c 100644 Binary files a/icons/obj/watercloset.dmi and b/icons/obj/watercloset.dmi differ diff --git a/interface/interface.dm b/interface/interface.dm index 4c9153c29f5..6691a31ea5c 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -7,12 +7,11 @@ to_chat(src, span_warning("The wiki URL is not set in the server configuration.")) return - if(alert("This will open the wiki in your browser. Are you sure?", "Wiki", "Yes", "No") != "Yes") + if(tgui_alert(src, "This will open the wiki in your browser. Are you sure?", "Wiki", list("Yes", "No"), 0) != "Yes") return DIRECT_OUTPUT(src, link(CONFIG_GET(string/wikiurl))) - /client/verb/boosty() set name = "boosty" set hidden = TRUE @@ -21,12 +20,11 @@ to_chat(src, span_warning("The donation URL is not set in the server configuration.")) return - if(alert("This will open the boosty in your browser. Are you sure?", "Forum", "Yes", "No") != "Yes") + if(tgui_alert(src, "This will open the boosty in your browser. Are you sure?", "Forum", list("Yes", "No"), 0) != "Yes") return DIRECT_OUTPUT(src, link(CONFIG_GET(string/donationurl))) - /client/verb/rules() set name = "rules" set hidden = TRUE @@ -35,12 +33,11 @@ to_chat(src, span_warning("The rules URL is not set in the server configuration.")) return - if(alert("This will open the rules in your browser. Are you sure?", "Rules", "Yes", "No") != "Yes") + if(tgui_alert("This will open the rules in your browser. Are you sure?", "Rules", list("Yes", "No"), 0) != "Yes") return DIRECT_OUTPUT(src, link(CONFIG_GET(string/rulesurl))) - /client/verb/discord() set name = "discord" set hidden = TRUE @@ -49,12 +46,11 @@ to_chat(src, span_warning("The Discord URL is not set in the server configuration.")) return - if(alert("This will open our Discord in your browser. Are you sure?", "Discord", "Yes", "No") != "Yes") + if(tgui_alert(src, "This will open our Discord in your browser. Are you sure?", "Discord", list("Yes", "No"), 0) != "Yes") return DIRECT_OUTPUT(src, link(CONFIG_GET(string/discordurl))) - /client/verb/github() set name = "github" set hidden = TRUE @@ -63,12 +59,11 @@ to_chat(src, span_warning("The bug tracker URL is not set in the server configuration.")) return - if(alert("This will open our bug tracker page in your browser. Are you sure?", "Github", "Yes", "No") != "Yes") + if(tgui_alert(src, "This will open our bug tracker page in your browser. Are you sure?", "Github", list("Yes", "No"), 0) != "Yes") return DIRECT_OUTPUT(src, link(CONFIG_GET(string/githuburl))) - /client/verb/webmap() set name = "webmap" set hidden = TRUE @@ -79,7 +74,7 @@ return var/map_url - var/choice = alert("Do you want to view the ground or the ship?",,"Ship","Ground","Cancel") + var/choice = tgui_alert(src, "Do you want to view the ground or the ship?", "Webmap", list("Ship", "Ground"), 0) switch(choice) if("Ship") map_url = SSmapping.configs[SHIP_MAP].map_file diff --git a/interface/skin.dmf b/interface/skin.dmf index 488811298bb..52a7aebd567 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -154,8 +154,8 @@ window "infowindow" is-vert = false elem "changelog" type = BUTTON - pos = 6,5 - size = 94x20 + pos = 0,5 + size = 90x20 anchor1 = 1,0 anchor2 = 16,0 saved-params = "is-checked" @@ -163,7 +163,7 @@ window "infowindow" command = "changelog" elem "discord" type = BUTTON - pos = 100,5 + pos = 90,5 size = 90x20 anchor1 = 16,0 anchor2 = 30,0 @@ -172,7 +172,7 @@ window "infowindow" command = "discord" elem "rules" type = BUTTON - pos = 190,5 + pos = 180,5 size = 90x20 anchor1 = 30,0 anchor2 = 44,0 @@ -181,7 +181,7 @@ window "infowindow" command = "rules" elem "wiki" type = BUTTON - pos = 280,5 + pos = 270,5 size = 90x20 anchor1 = 44,0 anchor2 = 58,0 @@ -190,7 +190,7 @@ window "infowindow" command = "wiki" elem "boosty" type = BUTTON - pos = 370,5 + pos = 360,5 size = 90x20 anchor1 = 58,0 anchor2 = 72,0 @@ -199,7 +199,7 @@ window "infowindow" command = "boosty" elem "github" type = BUTTON - pos = 460,5 + pos = 450,5 size = 90x20 anchor1 = 72,0 anchor2 = 86,0 @@ -208,15 +208,14 @@ window "infowindow" command = "github" elem "webmap" type = BUTTON - pos = 550,5 - size = 90x20 + pos = 540,5 + size = 95x20 anchor1 = 86,0 anchor2 = 100,0 saved-params = "is-checked" text = "Webmap" command = "webmap" - window "outputwindow" elem "outputwindow" type = MAIN diff --git a/sound/AI/aileft.ogg b/sound/AI/aileft.ogg new file mode 100644 index 00000000000..22a0a1b9c4c Binary files /dev/null and b/sound/AI/aileft.ogg differ diff --git a/sound/AI/aireport.ogg b/sound/AI/aireport.ogg index 82e4ca425de..d1138563403 100644 Binary files a/sound/AI/aireport.ogg and b/sound/AI/aireport.ogg differ diff --git a/sound/AI/bioscan.ogg b/sound/AI/bioscan.ogg index 3ab30d73b23..8e28931c3ba 100644 Binary files a/sound/AI/bioscan.ogg and b/sound/AI/bioscan.ogg differ diff --git a/sound/AI/bonus_climed.ogg b/sound/AI/bonus_climed.ogg new file mode 100644 index 00000000000..7dbec57a306 Binary files /dev/null and b/sound/AI/bonus_climed.ogg differ diff --git a/sound/AI/bonus_found.ogg b/sound/AI/bonus_found.ogg new file mode 100644 index 00000000000..5b9a0c3b018 Binary files /dev/null and b/sound/AI/bonus_found.ogg differ diff --git a/sound/AI/code_blue_elevated.ogg b/sound/AI/code_blue_elevated.ogg index d69edbda7b4..4b07b1cc1b1 100644 Binary files a/sound/AI/code_blue_elevated.ogg and b/sound/AI/code_blue_elevated.ogg differ diff --git a/sound/AI/code_blue_lowered.ogg b/sound/AI/code_blue_lowered.ogg index bf0a7c9113a..b71d319f2cf 100644 Binary files a/sound/AI/code_blue_lowered.ogg and b/sound/AI/code_blue_lowered.ogg differ diff --git a/sound/AI/code_delta.ogg b/sound/AI/code_delta.ogg new file mode 100644 index 00000000000..cf512041518 Binary files /dev/null and b/sound/AI/code_delta.ogg differ diff --git a/sound/AI/code_green.ogg b/sound/AI/code_green.ogg index cd4666c9917..8089daea600 100644 Binary files a/sound/AI/code_green.ogg and b/sound/AI/code_green.ogg differ diff --git a/sound/AI/code_red_elevated.ogg b/sound/AI/code_red_elevated.ogg index 3b2de8368ff..5def4c50878 100644 Binary files a/sound/AI/code_red_elevated.ogg and b/sound/AI/code_red_elevated.ogg differ diff --git a/sound/AI/code_red_lowered.ogg b/sound/AI/code_red_lowered.ogg index 4409d345bac..c2c35050ac9 100644 Binary files a/sound/AI/code_red_lowered.ogg and b/sound/AI/code_red_lowered.ogg differ diff --git a/sound/AI/commandreport.ogg b/sound/AI/commandreport.ogg index 9b6bb9bd6e9..4518c1c3d01 100644 Binary files a/sound/AI/commandreport.ogg and b/sound/AI/commandreport.ogg differ diff --git a/sound/AI/crash_start.ogg b/sound/AI/crash_start.ogg new file mode 100644 index 00000000000..809203ee67b Binary files /dev/null and b/sound/AI/crash_start.ogg differ diff --git a/sound/AI/distress_deny.ogg b/sound/AI/distress_deny.ogg new file mode 100644 index 00000000000..6954ef89030 Binary files /dev/null and b/sound/AI/distress_deny.ogg differ diff --git a/sound/AI/distressbeacon.ogg b/sound/AI/distressbeacon.ogg index 77defb64f82..ae40764c570 100644 Binary files a/sound/AI/distressbeacon.ogg and b/sound/AI/distressbeacon.ogg differ diff --git a/sound/AI/distressbeacon_none.ogg b/sound/AI/distressbeacon_none.ogg new file mode 100644 index 00000000000..909c7db38e7 Binary files /dev/null and b/sound/AI/distressbeacon_none.ogg differ diff --git a/sound/AI/distressbeaconlocked.ogg b/sound/AI/distressbeaconlocked.ogg new file mode 100644 index 00000000000..a533d16da0c Binary files /dev/null and b/sound/AI/distressbeaconlocked.ogg differ diff --git a/sound/AI/distressreceived.ogg b/sound/AI/distressreceived.ogg index 1f819146c5b..02aef2745cf 100644 Binary files a/sound/AI/distressreceived.ogg and b/sound/AI/distressreceived.ogg differ diff --git a/sound/AI/dropship_block.ogg b/sound/AI/dropship_block.ogg new file mode 100644 index 00000000000..d9b429a17f9 Binary files /dev/null and b/sound/AI/dropship_block.ogg differ diff --git a/sound/AI/dropship_emergency.ogg b/sound/AI/dropship_emergency.ogg index c8ff2903df9..cc92deedc5f 100644 Binary files a/sound/AI/dropship_emergency.ogg and b/sound/AI/dropship_emergency.ogg differ diff --git a/sound/AI/dropship_wrong.ogg b/sound/AI/dropship_wrong.ogg new file mode 100644 index 00000000000..e0b4cec1733 Binary files /dev/null and b/sound/AI/dropship_wrong.ogg differ diff --git a/sound/AI/evacuate.ogg b/sound/AI/evacuate.ogg index a0fe44536b9..de440a92428 100644 Binary files a/sound/AI/evacuate.ogg and b/sound/AI/evacuate.ogg differ diff --git a/sound/AI/evacuate_cancelled.ogg b/sound/AI/evacuate_cancelled.ogg index ebb74b6d4eb..c1e30c8c5a5 100644 Binary files a/sound/AI/evacuate_cancelled.ogg and b/sound/AI/evacuate_cancelled.ogg differ diff --git a/sound/AI/evacuation_complete.ogg b/sound/AI/evacuation_complete.ogg index d611f7c5287..c01eab7c5e8 100644 Binary files a/sound/AI/evacuation_complete.ogg and b/sound/AI/evacuation_complete.ogg differ diff --git a/sound/AI/evacuation_confirmed.ogg b/sound/AI/evacuation_confirmed.ogg index a1fccb0ccb4..0de76fe3762 100644 Binary files a/sound/AI/evacuation_confirmed.ogg and b/sound/AI/evacuation_confirmed.ogg differ diff --git a/sound/AI/hijack.ogg b/sound/AI/hijack.ogg index 774de641173..c6723229692 100644 Binary files a/sound/AI/hijack.ogg and b/sound/AI/hijack.ogg differ diff --git a/sound/AI/musical_pause.ogg b/sound/AI/musical_pause.ogg new file mode 100644 index 00000000000..7dc323594c3 Binary files /dev/null and b/sound/AI/musical_pause.ogg differ diff --git a/sound/AI/orbit_change.ogg b/sound/AI/orbit_change.ogg new file mode 100644 index 00000000000..cafda86b579 Binary files /dev/null and b/sound/AI/orbit_change.ogg differ diff --git a/sound/AI/poweroff.ogg b/sound/AI/poweroff.ogg index a0617d0f0e7..d334c7e9809 100644 Binary files a/sound/AI/poweroff.ogg and b/sound/AI/poweroff.ogg differ diff --git a/sound/AI/poweron.ogg b/sound/AI/poweron.ogg index 2598c1b7560..77b2b619baf 100644 Binary files a/sound/AI/poweron.ogg and b/sound/AI/poweron.ogg differ diff --git a/sound/AI/selfdestruct.ogg b/sound/AI/selfdestruct.ogg index 0dc503f865f..9a0efd64d5a 100644 Binary files a/sound/AI/selfdestruct.ogg and b/sound/AI/selfdestruct.ogg differ diff --git a/sound/AI/selfdestruct_deactivated.ogg b/sound/AI/selfdestruct_deactivated.ogg index b214440a349..62fb665444d 100644 Binary files a/sound/AI/selfdestruct_deactivated.ogg and b/sound/AI/selfdestruct_deactivated.ogg differ diff --git a/sound/AI/sup_drop.ogg b/sound/AI/sup_drop.ogg new file mode 100644 index 00000000000..eb01e3817fa Binary files /dev/null and b/sound/AI/sup_drop.ogg differ diff --git a/sound/AI/sup_drop_act.ogg b/sound/AI/sup_drop_act.ogg new file mode 100644 index 00000000000..ecf8f1b4239 Binary files /dev/null and b/sound/AI/sup_drop_act.ogg differ diff --git a/sound/AI/sup_drop_enemy.ogg b/sound/AI/sup_drop_enemy.ogg new file mode 100644 index 00000000000..2170aeeb41b Binary files /dev/null and b/sound/AI/sup_drop_enemy.ogg differ diff --git a/sound/AI/supply_increase.ogg b/sound/AI/supply_increase.ogg new file mode 100644 index 00000000000..861bfb2d42a Binary files /dev/null and b/sound/AI/supply_increase.ogg differ diff --git a/sound/effects/OB_warning_announce.ogg b/sound/effects/OB_warning_announce.ogg index 788a64790f2..540e7d58f51 100644 Binary files a/sound/effects/OB_warning_announce.ogg and b/sound/effects/OB_warning_announce.ogg differ diff --git a/tgmc.dme b/tgmc.dme index 76026e5cf25..3419d877925 100644 --- a/tgmc.dme +++ b/tgmc.dme @@ -210,6 +210,7 @@ #include "code\_globalvars\lists\client.dm" #include "code\_globalvars\lists\flavor_misc.dm" #include "code\_globalvars\lists\hud.dm" +#include "code\_globalvars\lists\icons.dm" #include "code\_globalvars\lists\keybinding.dm" #include "code\_globalvars\lists\mapping.dm" #include "code\_globalvars\lists\mobs.dm" @@ -390,6 +391,7 @@ #include "code\datums\actions\skill.dm" #include "code\datums\actions\weapon_actions.dm" #include "code\datums\actions\xeno_action.dm" +#include "code\datums\actions\species_actions\robot_action.dm" #include "code\datums\actions\species_actions\sectoid_action.dm" #include "code\datums\autocells\auto_cell.dm" #include "code\datums\autocells\explosion.dm" @@ -1619,8 +1621,6 @@ #include "code\modules\mob\living\carbon\update_icons.dm" #include "code\modules\mob\living\carbon\human\death.dm" #include "code\modules\mob\living\carbon\human\dummy.dm" -#include "code\modules\mob\living\carbon\human\emote-yautja.dm" -#include "code\modules\mob\living\carbon\human\emote.dm" #include "code\modules\mob\living\carbon\human\examine.dm" #include "code\modules\mob\living\carbon\human\human.dm" #include "code\modules\mob\living\carbon\human\human_attackhand.dm" @@ -1636,10 +1636,13 @@ #include "code\modules\mob\living\carbon\human\login.dm" #include "code\modules\mob\living\carbon\human\logout.dm" #include "code\modules\mob\living\carbon\human\say.dm" -#include "code\modules\mob\living\carbon\human\species.dm" #include "code\modules\mob\living\carbon\human\update_icons.dm" #include "code\modules\mob\living\carbon\human\yautja.dm" #include "code\modules\mob\living\carbon\human\zombie.dm" +#include "code\modules\mob\living\carbon\human\emote\human.dm" +#include "code\modules\mob\living\carbon\human\emote\necoarc.dm" +#include "code\modules\mob\living\carbon\human\emote\robot.dm" +#include "code\modules\mob\living\carbon\human\emote\yautja.dm" #include "code\modules\mob\living\carbon\human\life\handle_disabilities.dm" #include "code\modules\mob\living\carbon\human\life\handle_environment.dm" #include "code\modules\mob\living\carbon\human\life\handle_fire.dm" @@ -1649,6 +1652,21 @@ #include "code\modules\mob\living\carbon\human\life\handle_regular_hud_updates.dm" #include "code\modules\mob\living\carbon\human\life\handle_status_effects.dm" #include "code\modules\mob\living\carbon\human\life\life_helpers.dm" +#include "code\modules\mob\living\carbon\human\species\_species.dm" +#include "code\modules\mob\living\carbon\human\species\early_synthetic.dm" +#include "code\modules\mob\living\carbon\human\species\hud_data.dm" +#include "code\modules\mob\living\carbon\human\species\human.dm" +#include "code\modules\mob\living\carbon\human\species\monkey.dm" +#include "code\modules\mob\living\carbon\human\species\moth.dm" +#include "code\modules\mob\living\carbon\human\species\necoarc.dm" +#include "code\modules\mob\living\carbon\human\species\robot.dm" +#include "code\modules\mob\living\carbon\human\species\sectoid.dm" +#include "code\modules\mob\living\carbon\human\species\skeleton.dm" +#include "code\modules\mob\living\carbon\human\species\synthetic.dm" +#include "code\modules\mob\living\carbon\human\species\unarmed_attack.dm" +#include "code\modules\mob\living\carbon\human\species\vatborn.dm" +#include "code\modules\mob\living\carbon\human\species\vatgrown.dm" +#include "code\modules\mob\living\carbon\human\species\yautja.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities.dm" #include "code\modules\mob\living\carbon\xenomorph\attack_alien.dm" #include "code\modules\mob\living\carbon\xenomorph\charge_crush.dm" @@ -1868,9 +1886,12 @@ #include "code\modules\predator\yautja\weapons\one_handed.dm" #include "code\modules\predator\yautja\weapons\ranged.dm" #include "code\modules\predator\yautja\weapons\two_handed.dm" +#include "code\modules\projectiles\ammo_casing.dm" #include "code\modules\projectiles\ammunition.dm" +#include "code\modules\projectiles\big_ammo_box.dm" #include "code\modules\projectiles\gun_helpers.dm" #include "code\modules\projectiles\gun_system.dm" +#include "code\modules\projectiles\handful.dm" #include "code\modules\projectiles\mounted.dm" #include "code\modules\projectiles\projectile.dm" #include "code\modules\projectiles\sentries.dm" @@ -1951,21 +1972,27 @@ #include "code\modules\recycling\recycler.dm" #include "code\modules\recycling\sortingmachinery.dm" #include "code\modules\reqs\_supply.dm" -#include "code\modules\reqs\_supplypacks.dm" -#include "code\modules\reqs\armor.dm" -#include "code\modules\reqs\clothing.dm" -#include "code\modules\reqs\engineering.dm" -#include "code\modules\reqs\explosives.dm" -#include "code\modules\reqs\factory.dm" -#include "code\modules\reqs\imports.dm" -#include "code\modules\reqs\launchers.dm" -#include "code\modules\reqs\medical.dm" -#include "code\modules\reqs\operations.dm" -#include "code\modules\reqs\smartguns.dm" -#include "code\modules\reqs\stationary.dm" -#include "code\modules\reqs\supplies.dm" -#include "code\modules\reqs\vehicles.dm" -#include "code\modules\reqs\weapons.dm" +#include "code\modules\reqs\computer.dm" +#include "code\modules\reqs\elevator.dm" +#include "code\modules\reqs\tablet.dm" +#include "code\modules\reqs\supplypacks\_supplypacks.dm" +#include "code\modules\reqs\supplypacks\armor.dm" +#include "code\modules\reqs\supplypacks\clothing.dm" +#include "code\modules\reqs\supplypacks\engineering.dm" +#include "code\modules\reqs\supplypacks\explosives.dm" +#include "code\modules\reqs\supplypacks\factory.dm" +#include "code\modules\reqs\supplypacks\imports.dm" +#include "code\modules\reqs\supplypacks\launchers.dm" +#include "code\modules\reqs\supplypacks\medical.dm" +#include "code\modules\reqs\supplypacks\operations.dm" +#include "code\modules\reqs\supplypacks\smartguns.dm" +#include "code\modules\reqs\supplypacks\stationary.dm" +#include "code\modules\reqs\supplypacks\supplies.dm" +#include "code\modules\reqs\supplypacks\vehicles.dm" +#include "code\modules\reqs\supplypacks\weapons.dm" +#include "code\modules\reqs\ui\_ui.dm" +#include "code\modules\reqs\ui\request.dm" +#include "code\modules\reqs\ui\vehicle.dm" #include "code\modules\reqtorio\assembly_crafts.dm" #include "code\modules\reqtorio\craft_components.dm" #include "code\modules\reqtorio\howtopaper.dm" diff --git a/tgui/packages/tgui-panel/themes.ts b/tgui/packages/tgui-panel/themes.ts index a9443a70bfe..74970336782 100644 --- a/tgui/packages/tgui-panel/themes.ts +++ b/tgui/packages/tgui-panel/themes.ts @@ -59,6 +59,8 @@ export const setClientTheme = (name) => { 'github.text-color': '#000000', 'webmap.background-color': 'none', 'webmap.text-color': '#000000', + 'boosty.background-color': 'none', + 'boosty.text-color': '#000000', // Status and verb tabs 'output.background-color': 'none', 'output.text-color': '#000000', @@ -113,6 +115,8 @@ export const setClientTheme = (name) => { 'github.text-color': COLOR_DARK_TEXT, 'webmap.background-color': '#494949', 'webmap.text-color': COLOR_DARK_TEXT, + 'boosty.background-color': '#494949', + 'boosty.text-color': COLOR_DARK_TEXT, // Status and verb tabs 'output.background-color': COLOR_DARK_BG_DARKER, 'output.text-color': COLOR_DARK_TEXT, diff --git a/tgui/packages/tgui/interfaces/Changelog.jsx b/tgui/packages/tgui/interfaces/Changelog.jsx index fc0ec60167c..7ad46b8ff99 100644 --- a/tgui/packages/tgui/interfaces/Changelog.jsx +++ b/tgui/packages/tgui/interfaces/Changelog.jsx @@ -26,16 +26,12 @@ const icons = { expansion: { icon: 'check-circle', color: 'green' }, experiment: { icon: 'radiation', color: 'yellow' }, image: { icon: 'image', color: 'green' }, - imageadd: { icon: 'tg-image-plus', color: 'green' }, - imagedel: { icon: 'tg-image-minus', color: 'red' }, qol: { icon: 'hand-holding-heart', color: 'green' }, refactor: { icon: 'tools', color: 'green' }, rscadd: { icon: 'check-circle', color: 'green' }, rscdel: { icon: 'times-circle', color: 'red' }, server: { icon: 'server', color: 'purple' }, sound: { icon: 'volume-high', color: 'green' }, - soundadd: { icon: 'tg-sound-plus', color: 'green' }, - sounddel: { icon: 'tg-sound-minus', color: 'red' }, map: { icon: 'map', color: 'green' }, spellcheck: { icon: 'spell-check', color: 'green' }, tgs: { icon: 'toolbox', color: 'purple' }, diff --git a/tools/WebhookProcessor/github_webhook_processor.php b/tools/WebhookProcessor/github_webhook_processor.php index 2424cefcf80..47f046c1fa2 100644 --- a/tools/WebhookProcessor/github_webhook_processor.php +++ b/tools/WebhookProcessor/github_webhook_processor.php @@ -43,8 +43,8 @@ // Only these repositories will announce in game. // Any repository that players actually care about. $game_announce_whitelist = array( - "tgstation", - "TerraGov-Marine-Corps", + "PMC-Unga-Marines", + "Unga-Marines", ); // Any repository that matches in this blacklist will not appear on Discord. @@ -187,7 +187,6 @@ function validate_user($payload) { $res = github_apisend('https://api.github.com/search/issues?q='.$querystring); $res = json_decode($res, TRUE); return $res['total_count'] >= (int)$validation_count; - } function get_labels($payload){ @@ -248,6 +247,8 @@ function tag_pr($payload, $opened) { $tags[] = 'Revert'; if(strpos(strtolower($title), 'removes') !== FALSE) $tags[] = 'Removal'; + if(strpos(strtolower($title), 'ports') !== FALSE) + $tags[] = 'Port'; } $remove = array('Test Merge Candidate'); @@ -258,7 +259,7 @@ function tag_pr($payload, $opened) { else if ($mergeable === FALSE) $tags[] = 'Merge Conflict'; - $treetags = array('_maps' => 'Map Edit', 'tools' => 'Tools', 'SQL' => 'SQL', '.github' => 'GitHub'); + $treetags = array('_maps' => 'Mapping', 'tools' => 'Tools', 'SQL' => 'SQL', '.github' => 'GitHub'); $addonlytags = array('icons' => 'Sprites', 'sound' => 'Sound', 'config' => 'Config Update', 'code/controllers/configuration/entries' => 'Config Update', 'tgui' => 'UI'); foreach($treetags as $tree => $tag) if(has_tree_been_edited($payload, $tree)) @@ -270,7 +271,6 @@ function tag_pr($payload, $opened) { $tags[] = $tag; check_tag_and_replace($payload, '[dnm]', 'Do Not Merge', $tags); - check_tag_and_replace($payload, '[no gbp]', 'GBP: No Update', $tags); return array($tags, $remove); } @@ -709,21 +709,14 @@ function checkchangelog($payload, $compile = true) { break; case 'qol': if($item != 'made something easier to use') { - $tags[] = 'Quality of Life'; + $tags[] = 'QoL'; $currentchangelogblock[] = array('type' => 'qol', 'body' => $item); } break; - case 'soundadd': + case 'sound': if($item != 'added a new sound thingy') { $tags[] = 'Sound'; - $currentchangelogblock[] = array('type' => 'soundadd', 'body' => $item); - } - break; - case 'sounddel': - if($item != 'removed an old sound thingy') { - $tags[] = 'Sound'; - $tags[] = 'Removal'; - $currentchangelogblock[] = array('type' => 'sounddel', 'body' => $item); + $currentchangelogblock[] = array('type' => 'sound', 'body' => $item); } break; case 'add': @@ -742,17 +735,10 @@ function checkchangelog($payload, $compile = true) { $currentchangelogblock[] = array('type' => 'rscdel', 'body' => $item); } break; - case 'imageadd': + case 'image': if($item != 'added some icons and images') { $tags[] = 'Sprites'; - $currentchangelogblock[] = array('type' => 'imageadd', 'body' => $item); - } - break; - case 'imagedel': - if($item != 'deleted some icons and images') { - $tags[] = 'Sprites'; - $tags[] = 'Removal'; - $currentchangelogblock[] = array('type' => 'imagedel', 'body' => $item); + $currentchangelogblock[] = array('type' => 'image', 'body' => $item); } break; case 'typo': @@ -768,6 +754,13 @@ function checkchangelog($payload, $compile = true) { $currentchangelogblock[] = array('type' => 'balance', 'body' => $item); } break; + case 'mapping': + case 'map': + if($item != 'added/modified/removed map content'){ + $tags[] = 'Mapping'; + $currentchangelogblock[] = array('type' => 'balance', 'body' => $item); + } + break; case 'code_imp': case 'code': if($item != 'changed some code'){ diff --git a/tools/WebhookProcessor/secret.php b/tools/WebhookProcessor/secret.php index 57773bffa16..8e18e728037 100644 --- a/tools/WebhookProcessor/secret.php +++ b/tools/WebhookProcessor/secret.php @@ -11,10 +11,10 @@ $apiKey = '209ab8d879c0f987d06a09b9d879c0f987d06a09b9d8787d0a089c'; //The repository auto-updates are sourced from. -$repoOwnerAndName = "tgstation/tgstation"; +$repoOwnerAndName = "PMC-Unga-Marines/Unga-Marines"; //Whitelist of repository names that have PRs auto-tagged -$repoAutoTaggerWhitelist = array("tgstation", "TerraGov-Marine-Corps"); +$repoAutoTaggerWhitelist = array("PMC-Unga-Marines", "Unga-Marines"); //Auto update settings $enable_live_tracking = true; //auto update this file from the repository