diff --git a/aurorastation.dme b/aurorastation.dme index a205652f1ec..836642512f1 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -640,6 +640,7 @@ #include "code\game\gamemodes\mixed\infestation.dm" #include "code\game\gamemodes\mixed\insurrection.dm" #include "code\game\gamemodes\mixed\intrigue.dm" +#include "code\game\gamemodes\mixed\rebellion.dm" #include "code\game\gamemodes\mixed\siege.dm" #include "code\game\gamemodes\mixed\towerdefense.dm" #include "code\game\gamemodes\mixed\traitorling.dm" @@ -2862,6 +2863,7 @@ #include "code\modules\projectiles\gun.dm" #include "code\modules\projectiles\pins.dm" #include "code\modules\projectiles\projectile.dm" +#include "code\modules\projectiles\suppressor.dm" #include "code\modules\projectiles\ammunition\ammo_pile.dm" #include "code\modules\projectiles\ammunition\boxes.dm" #include "code\modules\projectiles\ammunition\bullets.dm" diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index d7959254d44..5acd09f3ea2 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -91,6 +91,7 @@ //movement intents #define M_WALK "walk" #define M_RUN "run" +#define M_LAY "lay" // Intentional lying only! To not confuse with the state (variable with the same name on the mob, but not necessarity intentional) // Limbs and robotic stuff. #define BP_L_FOOT "l_foot" diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm index e204f860050..acba5cca978 100644 --- a/code/_onclick/hud/action.dm +++ b/code/_onclick/hud/action.dm @@ -32,6 +32,7 @@ /datum/action/Destroy() if(owner) Remove(owner) + target = null return ..() /datum/action/proc/SetTarget(var/atom/Target) @@ -51,8 +52,7 @@ if(button) if(T.client) T.client.screen -= button - qdel(button) - button = null + QDEL_NULL(button) T.actions.Remove(src) T.update_action_buttons() owner = null @@ -122,6 +122,10 @@ var/datum/action/owner screen_loc = "WEST,NORTH" +/obj/screen/movable/action_button/Destroy(force) + owner = null + . = ..() + /obj/screen/movable/action_button/Click(location,control,params) var/list/modifiers = params2list(params) if(modifiers["shift"]) @@ -266,4 +270,4 @@ #undef AB_CHECK_STUNNED #undef AB_CHECK_LYING #undef AB_CHECK_ALIVE -#undef AB_CHECK_INSIDE +#undef AB_CHECK_INSIDE diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 5a13107e378..f3469748a8b 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -454,9 +454,13 @@ if (user.m_intent == M_RUN) icon_state = "running" + else if (user.m_intent == M_LAY) + icon_state = "lying" else icon_state = "walking" +#define BLACKLIST_SPECIES_RUNNING list(SPECIES_DIONA, SPECIES_DIONA_COEUS) + /obj/screen/movement_intent/Click(location, control, params) if(!usr) return 1 @@ -477,7 +481,29 @@ if(M_RUN) usr.m_intent = M_WALK if(M_WALK) - usr.m_intent = M_RUN + if(!(usr.get_species() in BLACKLIST_SPECIES_RUNNING)) + usr.m_intent = M_RUN + + if(M_LAY) + + // No funny "haha i get the bonuses then stand up" + var/obj/item/gun/gun_in_hand = C.get_type_in_hands(/obj/item/gun) + if(gun_in_hand?.wielded) + to_chat(C, SPAN_WARNING("You cannot wield and stand up!")) + return + + if(C.lying_is_intentional) + usr.m_intent = M_WALK + + if(modifiers["button"] == "middle" && !C.lying) // See /mob/proc/update_canmove() for more logic on the lying FSM + + // You want this bonus weapon or not? Wield it when you are lying, not before! + var/obj/item/gun/gun_in_hand = C.get_type_in_hands(/obj/item/gun) + if(gun_in_hand?.wielded) + to_chat(C, SPAN_WARNING("You cannot wield and lie down!")) + return + C.m_intent = M_LAY + else if(istype(usr, /mob/living/simple_animal/hostile/morph)) var/mob/living/simple_animal/hostile/morph/M = usr switch(usr.m_intent) @@ -488,6 +514,8 @@ M.update_speed() update_move_icon(usr) +#undef BLACKLIST_SPECIES_RUNNING + // Hand slots are special to handle the handcuffs overlay /obj/screen/inventory/hand var/image/handcuff_overlay diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 337a75be990..8593dde18d1 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -256,6 +256,7 @@ var/list/gamemode_cache = list() //Unversal modifiers var/walk_speed = 0 var/walk_delay_multiplier = 1 + var/lying_delay_multiplier = 4 var/run_delay_multiplier = 1 var/vehicle_delay_multiplier = 1 diff --git a/code/datums/uplink/highly visible and dangerous weapons.dm b/code/datums/uplink/highly visible and dangerous weapons.dm index 86a82e4fa89..da02566e956 100644 --- a/code/datums/uplink/highly visible and dangerous weapons.dm +++ b/code/datums/uplink/highly visible and dangerous weapons.dm @@ -25,16 +25,23 @@ telecrystal_cost = 4 path = /obj/item/melee/energy/sword -/datum/uplink_item/item/visible_weapons/g9mm - name = "Silenced 9mm" - telecrystal_cost = 2 - path = /obj/item/storage/box/syndie_kit/g9mm - /datum/uplink_item/item/visible_weapons/hammer name = "Kneebreaker Hammer" telecrystal_cost = 3 path = /obj/item/melee/hammer +/datum/uplink_item/item/visible_weapons/suppressor + name = "Suppressor" + desc = "A suppressor that can be attached to most pistol-caliber weaponry. Will prevent sound from passing through walls." + telecrystal_cost = 1 + bluecrystal_cost = 1 + path = /obj/item/suppressor + +/datum/uplink_item/item/visible_weapons/g9mm + name = "9mm Pistol" + telecrystal_cost = 1 + path = /obj/item/gun/projectile/pistol + /datum/uplink_item/item/visible_weapons/revolver name = "Revolver" telecrystal_cost = 4 @@ -141,6 +148,12 @@ telecrystal_cost = 2 path = /obj/item/gun/projectile/colt +/datum/uplink_item/item/visible_weapons/suppressed_pistol + name = "Suppressed .45 Pistol" + desc = "A .45 pistol that comes with a suppressor integrated into the barrel. The suppressor cannot be removed." + telecrystal_cost = 2 + path = /obj/item/gun/projectile/silenced + /datum/uplink_item/item/visible_weapons/custom_ka name = "Kinetic Laser Assembly" telecrystal_cost = 3 diff --git a/code/game/gamemodes/mixed/rebellion.dm b/code/game/gamemodes/mixed/rebellion.dm new file mode 100644 index 00000000000..e5264f99e8f --- /dev/null +++ b/code/game/gamemodes/mixed/rebellion.dm @@ -0,0 +1,9 @@ +/datum/game_mode/rebellion + name = "rebellion (rev. + cult)" + round_description = "Some crewmembers are attempting to start a revolution while a cult gains followers to take over in the shadows!" + extended_round_description = "Revolutionaries and cultists spawn during this round." + config_tag = "rebellion" + required_players = 30 + required_enemies = 6 + antag_tags = list(MODE_REVOLUTIONARY, MODE_LOYALIST, MODE_CULTIST) + require_all_templates = TRUE diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 3c748e1cb0e..39f1e2d64da 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -101,6 +101,8 @@ pixel_x = 10; var/report_danger_level = 1 + var/global/image/alarm_overlay + /obj/machinery/alarm/north PRESET_NORTH @@ -350,6 +352,7 @@ pixel_x = 10; regulating_temperature = 1 visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\ "You hear a click and a faint electronic hum.") + update_icon() else //check for when we should stop adjusting temperature if (get_danger_level(target_temperature, TLV["temperature"]) || abs(environment.temperature - target_temperature) <= 0.5) @@ -357,6 +360,7 @@ pixel_x = 10; regulating_temperature = 0 visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\ "You hear a click as a faint electronic humming stops.") + update_icon() if (regulating_temperature) //Unnecessary checks removed, duplication of effort @@ -441,12 +445,13 @@ pixel_x = 10; /obj/machinery/alarm/update_icon() cut_overlays() + icon_state = "alarmp" + if(wiresexposed) icon_state = "alarmx" - set_light(0) - return + if((stat & (NOPOWER|BROKEN)) || shorted) - icon_state = "alarmp" + add_overlay("alarm_fan_off") set_light(0) return @@ -454,20 +459,25 @@ pixel_x = 10; if (alarm_area.atmosalm) icon_level = max(icon_level, 1) //if there's an atmos alarm but everything is okay locally, no need to go past yellow + alarm_overlay = make_screen_overlay(icon, "alarm[icon_level]") + add_overlay(alarm_overlay) + var/new_color = null switch(icon_level) if (0) - add_overlay("alarm0") - new_color = "#03A728" + new_color = COLOR_LIME if (1) - add_overlay("alarm2") //yes, alarm2 is yellow alarm new_color = COLOR_SUN if (2) - add_overlay("alarm1") - new_color = "#DA0205" + new_color = COLOR_RED_LIGHT set_light(l_range = L_WALLMOUNT_RANGE, l_power = L_WALLMOUNT_POWER, l_color = new_color) + if(regulating_temperature) + add_overlay("alarm_fan_on") + else + add_overlay("alarm_fan_off") + /obj/machinery/alarm/proc/refresh_all() for(var/id_tag in alarm_area.air_vent_names) var/list/I = alarm_area.air_vent_info[id_tag] diff --git a/code/game/objects/items/weapons/grenades/fragmentation.dm b/code/game/objects/items/weapons/grenades/fragmentation.dm index 3bc97312d84..70bdc676889 100644 --- a/code/game/objects/items/weapons/grenades/fragmentation.dm +++ b/code/game/objects/items/weapons/grenades/fragmentation.dm @@ -36,7 +36,7 @@ base_spread = 0 //causes it to be treated as a shrapnel explosion instead of cone spread_step = 20 - silenced = 1 //embedding messages are still produced so it's kind of weird when enabled. + suppressed = TRUE //embedding messages are still produced so it's kind of weird when enabled. no_attack_log = 1 muzzle_type = null diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index dff53a9dc26..32a68f80a44 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -263,6 +263,13 @@ item_state = "legion_bag" empty_delay = 0.8 SECOND +/obj/item/storage/backpack/tcaf + name = "\improper TCAF carapace backpack" + desc = "A hard shelled backpack with the flag of the Republic of Biesel front and center. Made for the Tau Ceti Armed Forces." + icon_state = "tcaf_carapace_backpack" + item_state = "tcaf_carapace_backpack" + empty_delay = 0.8 SECOND + /obj/item/storage/backpack/service name = "idris service backpack" desc = "The Idris Service Standard, known for it's professionalism. It also baffingly includes this monstrous, self-stabilizing back-mounted utensil and service item holder." diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 6e4eda40cde..629b49efbe6 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -110,11 +110,6 @@ icon_state = "box" item_state = "box" -/obj/item/storage/box/syndie_kit/g9mm - name = "smooth operator" - desc = "9mm with silencer kit." - starts_with = list(/obj/item/gun/projectile/pistol = 1, /obj/item/silencer = 1) - /obj/item/storage/box/syndie_kit/toxin name = "toxin kit" desc = "An apple will not be enough to keep the doctor away after this." diff --git a/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm b/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm index 90c7528affb..2e06cb06b8d 100644 --- a/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm +++ b/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm @@ -521,10 +521,10 @@ new /obj/item/gun/projectile/pistol(src) new /obj/item/gun/projectile/pistol(src) new /obj/item/gun/projectile/pistol(src) - new /obj/item/silencer(src) - new /obj/item/silencer(src) - new /obj/item/silencer(src) - new /obj/item/silencer(src) + new /obj/item/suppressor(src) + new /obj/item/suppressor(src) + new /obj/item/suppressor(src) + new /obj/item/suppressor(src) new /obj/item/ammo_magazine/mc9mm(src) new /obj/item/ammo_magazine/mc9mm(src) new /obj/item/ammo_magazine/mc9mm(src) @@ -539,7 +539,7 @@ new /obj/item/clothing/suit/space/void/einstein(src) new /obj/item/gun/energy/rifle(src) new /obj/item/gun/projectile/pistol(src) - new /obj/item/silencer(src) + new /obj/item/suppressor(src) new /obj/item/ammo_magazine/mc9mm(src) new /obj/item/ammo_magazine/mc9mm(src) @@ -770,7 +770,7 @@ /obj/structure/closet/crate/secure/gear_loadout/ninja/stealth/fill() ..() new /obj/item/gun/projectile/pistol(src) - new /obj/item/silencer(src) + new /obj/item/suppressor(src) new /obj/item/ammo_magazine/mc9mm(src) new /obj/item/ammo_magazine/mc9mm(src) diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 3cab8e0e2c3..e9dcf34069f 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -424,4 +424,4 @@ if(istype(mover, /obj/item/projectile)) return prob(30) else - return !density \ No newline at end of file + return !density diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index cbff0b8156d..8563210a051 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -24,7 +24,7 @@ icon = 'icons/obj/structure/beds.dmi' icon_state = "bed" anchored = TRUE - buckle_dir = SOUTH + buckle_dir = EAST buckle_lying = 1 build_amt = 2 var/material/padding_material diff --git a/code/modules/client/preference_setup/loadout/items/augments.dm b/code/modules/client/preference_setup/loadout/items/augments.dm index 0a0e8754d66..ca6c13a90aa 100644 --- a/code/modules/client/preference_setup/loadout/items/augments.dm +++ b/code/modules/client/preference_setup/loadout/items/augments.dm @@ -237,3 +237,13 @@ path = /obj/item/organ/internal/augment/head_fluff/lhand_fluff flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD, SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI, SPECIES_SKRELL, SPECIES_SKRELL_AXIORI, SPECIES_IPC, SPECIES_IPC_G1, SPECIES_IPC_G2, SPECIES_IPC_XION, SPECIES_IPC_ZENGHU, SPECIES_IPC_BISHOP, SPECIES_IPC_SHELL, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, SPECIES_UNATHI) + +/datum/gear/augment/skrell_language + display_name = "Zeng-Hu Nral'malic language processor" + description = "An augmentation developed by Zeng-Hu Pharmaceuticals' Nralakk Division to enable the recipient to understand the complex and inaudible tones of Nral'malic." + path = /obj/item/organ/internal/augment/language/zeng + whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD) + faction = "Zeng-Hu Pharmaceuticals" + allowed_roles = list("Physician", "Surgeon", "Chief Medical Officer", "Pharmacist", "First Responder", "Psychiatrist", "Medical Intern", "Corporate Liaison", "Research Director","Scientist", "Xenobiologist", "Xenobotanist", "Xenoarchaeologist", "Lab Assistant", "Assistant", "Off-Duty Crew Member", "Captain") + cost = 3 + diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index af732dd662c..13ab0f82ff4 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -284,6 +284,16 @@ build_from_parts = TRUE worn_overlay = "over" +/obj/item/clothing/gloves/tcaf + name = "\improper TCAF armsman gloves" + desc = "A pair of khaki tactical gloves with reinforcement at the knuckles and an adjustable strap at the wrist." + icon = 'icons/clothing/under/uniforms/tcaf_uniform.dmi' + contained_sprite = TRUE + icon_state = "tcaf_armsman_gloves" + item_state = "tcaf_armsman_gloves" + build_from_parts = TRUE + worn_overlay = "over" + /obj/item/clothing/gloves/ballistic name = "ballistic gauntlet" desc = "A metal gauntlet armed with a wrist-mounted shotgun." diff --git a/code/modules/clothing/head/berets.dm b/code/modules/clothing/head/berets.dm index 06fb6dd2e0c..b88690f0baa 100644 --- a/code/modules/clothing/head/berets.dm +++ b/code/modules/clothing/head/berets.dm @@ -172,10 +172,10 @@ icon_state = "orion" item_state = "orion" -// TCFL +// TCAF /obj/item/clothing/head/beret/legion - name = "TCFL dress beret" + name = "\improper TCFL dress beret" desc = "A pale blue dress beret with a rubber insignia of a torch, surrounded by red stars and the letters \"TCFL\". A common good luck charm among former legionaires." icon_state = "tcfl_dress" item_state = "tcfl_dress" @@ -192,6 +192,20 @@ icon_state = "tcfl_sentinel" item_state = "tcfl_sentinel" +/obj/item/clothing/head/beret/legion/tcaf + name = "\improper TCAF dress beret" + desc = "A blue dress beret bearing the flag of the Republic of Biesel. Often only seen worn by in-service members of the Tau Ceti Armed Forces." + icon = 'icons/clothing/under/uniforms/tcaf_uniform.dmi' + contained_sprite = TRUE + icon_state = "tcaf_dress_beret" + item_state = "tcaf_dress_beret" + +/obj/item/clothing/head/beret/legion/tcaf/tcaf_field + name = "\improper TCAF field beret" + desc = "A red beret bearing a golden torch in semblance of the Republic of Biesel. Often only seen worn by in-service members of the Tau Ceti Armed Forces." + icon_state = "tcaf_field_beret" + item_state = "tcaf_field_beret" + //centcom /obj/item/clothing/head/beret/centcom/officer diff --git a/code/modules/clothing/suits/modular_armor.dm b/code/modules/clothing/suits/modular_armor.dm index b23ca0409dc..8d94ed5faf3 100644 --- a/code/modules/clothing/suits/modular_armor.dm +++ b/code/modules/clothing/suits/modular_armor.dm @@ -93,6 +93,20 @@ /obj/item/clothing/accessory/storage/modular_pouch/large ) +/obj/item/clothing/suit/armor/carrier/tcaf + starting_accessories = list( + /obj/item/clothing/accessory/armor_plate/tcaf, + /obj/item/clothing/accessory/leg_guard/tcaf, + /obj/item/clothing/accessory/arm_guard/tcaf, + /obj/item/clothing/accessory/storage/chestpouch + ) + +/obj/item/clothing/suit/armor/carrier/tcaf/tcaf_light + starting_accessories = list( + /obj/item/clothing/accessory/armor_plate/tcaf/tcaf_light, + /obj/item/clothing/accessory/leg_guard/tcaf, + ) + /obj/item/clothing/accessory/armor_plate name = "corporate armor plate" desc = "A particularly light-weight armor plate in stylish corporate black. Unfortunately, not very good if you hold it with your hands." @@ -207,6 +221,39 @@ item_state = "plate_blue" slowdown = 0 // the SCC is hacking +/obj/item/clothing/accessory/armor_plate/tcaf + name = "\improper TCAF legionnaire carapace" + desc = "The blue carapace of the Tau Ceti Armed Forces. Polished and proud for Miranda Trasen's favorite soldiers." + icon = 'icons/clothing/kit/modular_armor.dmi' + icon_state = "tcaf_plate" + item_state = "tcaf_plate" + contained_sprite = TRUE + armor = list( + melee = ARMOR_MELEE_MAJOR, + bullet = ARMOR_BALLISTIC_MAJOR, + laser = ARMOR_LASER_RIFLE, + energy = ARMOR_ENERGY_SMALL, + bomb = ARMOR_BOMB_PADDED, + ) + slowdown = 0 // inherited the hacking from the scc + +/obj/item/clothing/accessory/armor_plate/tcaf/tcaf_light + name = "\improper TCAF legionnaire light carapace" + desc = "A lighter version of the blue carapace of the Tau Ceti Armed Forces. Reserved for recruits, recon, and prissy officers in the field." + icon_state = "tcaf_plate_light" + item_state = "tcaf_plate_light" + slowdown = 0 + +/obj/item/clothing/accessory/storage/chestpouch + name = "chestpouch rig" + desc = "A harness made to be worn over a set of armor. Comes with three pouches on the front, and a hidden pouch on the back for your snacks!" + icon = 'icons/clothing/kit/modular_armor.dmi' + icon_state = "tcaf_chestpouches" + item_state = "tcaf_chestpouches" + contained_sprite = TRUE + slot = ACCESSORY_SLOT_ARMOR_POCKETS + slots = 4 + /obj/item/clothing/accessory/storage/modular_pouch name = "plate carrier pouches" desc = "A comfortable set of pouches that can be attached to a plate carrier, allowing the wearer to store some small items." @@ -302,6 +349,32 @@ bomb = ARMOR_BOMB_PADDED, ) +/obj/item/clothing/head/helmet/tcaf + name = "\improper TCAF legionnaire faceplate helmet" + desc = "A carapace helmet in the traditional colors of the Tau Ceti Armed Forces. This one equipped with the signature faceplate." + icon = 'icons/clothing/kit/modular_armor.dmi' + contained_sprite = TRUE + icon_state = "tcaf_helm_face" + item_state = "tcaf_helm_face" + armor = list( + melee = ARMOR_MELEE_MAJOR, + bullet = ARMOR_BALLISTIC_MAJOR, + laser = ARMOR_LASER_MEDIUM, + energy = ARMOR_ENERGY_SMALL, + bomb = ARMOR_BOMB_PADDED, + ) + +/obj/item/clothing/head/helmet/tcaf/tcaf_novisor + name = "\improper TCAF legionnaire helmet" + desc = "A carapace helmet in the traditional colors of the Tau Ceti Armed Forces." + icon_state = "tcaf_helm_novisor" + item_state = "tcaf_helm_novisor" + +/obj/item/clothing/head/helmet/tcaf/tcaf_visor + name = "\improper TCAF legionnaire visored helmet" + desc = "A carapace helmet in the traditional colors of the Tau Ceti Armed Forces. This one is equipped with a stylish visor." + icon_state = "tcaf_helm_visor" + item_state = "tcaf_helm_visor" //Cosmetic Accessories @@ -672,3 +745,23 @@ Szalai and MacPherson sought to undo." icon_state = "flagpatch_ssmd" item_state = "flagpatch_ssmd" + +/obj/item/clothing/accessory/tcaf_prefect_pauldron + name = "\improper TCAF prefect pauldron" + desc = "A bright red hard pauldron to indicate the wearer has the rank of Prefect in the Tau Ceti Armed Forces." + icon = 'icons/clothing/kit/modular_armor.dmi' + icon_state = "tcaf_prefect_pauldron" + item_state = "tcaf_prefect_pauldron" + contained_sprite = TRUE + slot = ACCESSORY_SLOT_GENERIC + flippable = FALSE + +/obj/item/clothing/accessory/tcaf_senior_legion_pauldron + name = "\improper TCAF senior legionnaire pauldron" + desc = "A blue hard pauldron to indicate the wearer has the rank of Senior Legionnaire in the Tau Ceti Armed Forces." + icon = 'icons/clothing/kit/modular_armor.dmi' + icon_state = "tcaf_senior_legion_pauldron" + item_state = "tcaf_senior_legion_pauldron" + contained_sprite = TRUE + slot = ACCESSORY_SLOT_GENERIC + flippable = FALSE diff --git a/code/modules/clothing/under/accessories/armor.dm b/code/modules/clothing/under/accessories/armor.dm index 8d7779c1309..9a98a1105b3 100644 --- a/code/modules/clothing/under/accessories/armor.dm +++ b/code/modules/clothing/under/accessories/armor.dm @@ -113,6 +113,21 @@ bomb = ARMOR_BOMB_PADDED, ) +/obj/item/clothing/accessory/leg_guard/tcaf + name = "\improper TCAF legionnaire leg carapace" + desc = "Try to sweep the leg against someone wearing these." + icon = 'icons/clothing/kit/modular_armor.dmi' + icon_state = "tcaf_boot_armor" + item_state = "tcaf_boot_armor" + contained_sprite = TRUE + armor = list( + melee = ARMOR_MELEE_MAJOR, + bullet = ARMOR_BALLISTIC_MAJOR, + laser = ARMOR_LASER_MEDIUM, + energy = ARMOR_ENERGY_SMALL, + bomb = ARMOR_BOMB_PADDED, + ) + //Arm guards. /obj/item/clothing/accessory/arm_guard name = "corporate arm guards" @@ -239,3 +254,23 @@ energy = ARMOR_ENERGY_SMALL, bomb = ARMOR_BOMB_PADDED, ) + +/obj/item/clothing/accessory/arm_guard/tcaf + name = "\improper TCAF carapace arm guards" + desc = "Blue carapace armguards to protect you in the modern battlefield of 2465." + icon = 'icons/clothing/kit/modular_armor.dmi' + icon_state = "tcaf_armguards" + item_state = "tcaf_armguards" + contained_sprite = TRUE + armor = list( + melee = ARMOR_MELEE_MAJOR, + bullet = ARMOR_BALLISTIC_MAJOR, + laser = ARMOR_LASER_MEDIUM, + energy = ARMOR_ENERGY_SMALL, + bomb = ARMOR_BOMB_PADDED, + ) + +/obj/item/clothing/accessory/arm_guard/tcaf/tcaf_stripe + name = "striped TCAF carapace arm guards" + icon_state = "tcaf_armguards_stripe" + item_state = "tcaf_armguards_stripe" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 1340bc85d38..a21a42e7eb2 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -540,6 +540,15 @@ item_state = "tauceti_pilot" worn_state = "tauceti_pilot" +/obj/item/clothing/under/legion/tcaf + name = "\improper TCAF armsman uniform" + desc = "A black longsleeved top over rough khaki tactical pants. Designed for the use of on-ship legionnaires serving the Republic." + icon = 'icons/clothing/under/uniforms/tcaf_uniform.dmi' + contained_sprite = TRUE + icon_state = "tcaf_armsman_uniform" + item_state = "tcaf_armsman_uniform" + worn_state = "tcaf_armsman_uniform" + /obj/item/clothing/under/offworlder name = "\improper CR suit" desc = "A very tight form-fitting padded suit that looks extremely comfortable to wear." diff --git a/code/modules/custom_ka/barrels.dm b/code/modules/custom_ka/barrels.dm index 04356a69e1e..77beb040a7a 100644 --- a/code/modules/custom_ka/barrels.dm +++ b/code/modules/custom_ka/barrels.dm @@ -69,7 +69,7 @@ desc = "A very experimental kinetic accelerator energy converter. Not much is known about this thing, other than it kicks like a mule and stings like an e-sword." icon_state = "barrel05" damage_increase = 30 - firedelay_increase = 1 SECONDS + firedelay_increase = 2 SECONDS range_increase = 7 recoil_increase = 10 cost_increase = 10 diff --git a/code/modules/custom_ka/cells.dm b/code/modules/custom_ka/cells.dm index d7391870f56..0a94badc7af 100644 --- a/code/modules/custom_ka/cells.dm +++ b/code/modules/custom_ka/cells.dm @@ -234,7 +234,7 @@ icon_state = "cell_uraniumloader" cell_increase = 300 capacity_increase = -5 - + firedelay_increase = 0.5 SECONDS pump_restore = 0 pump_delay = 0 diff --git a/code/modules/custom_ka/core.dm b/code/modules/custom_ka/core.dm index b282ddc3749..e55b7d03a2c 100644 --- a/code/modules/custom_ka/core.dm +++ b/code/modules/custom_ka/core.dm @@ -20,7 +20,7 @@ fire_sound = 'sound/weapons/kinetic_accel.ogg' fire_sound_text = "blast" recoil = 0 - silenced = 0 + suppressed = FALSE muzzle_flash = 3 accuracy = 0 //accuracy is measured in tiles. +1 accuracy means that everything is effectively one tile closer for the purpose of miss chance, -1 means the opposite. launchers are not supported, at the moment. scoped_accuracy = null @@ -234,19 +234,30 @@ installed_upgrade_chip.on_fire(src) if(installed_barrel) installed_barrel.on_fire(src) + + var/turf/T = get_turf(src) - if(ispath(installed_barrel.projectile_type, /obj/item/projectile/kinetic)) - var/obj/item/projectile/kinetic/shot_projectile = new installed_barrel.projectile_type(get_turf(src)) - shot_projectile.damage = damage_increase - shot_projectile.range = range_increase - shot_projectile.aoe = max(1, aoe_increase) - shot_projectile.base_damage = damage_increase - return shot_projectile - if(ispath(installed_barrel.projectile_type, /obj/item/projectile/beam)) - var/obj/item/projectile/beam/shot_projectile = new installed_barrel.projectile_type(get_turf(src)) - shot_projectile.damage = damage_increase - shot_projectile.range = range_increase - return shot_projectile + if(T) + var/datum/gas_mixture/environment = T.return_air() + var/pressure = (environment)? environment.return_pressure() : 0 + if(ispath(installed_barrel.projectile_type, /obj/item/projectile/kinetic)) + var/obj/item/projectile/kinetic/shot_projectile = new installed_barrel.projectile_type(get_turf(src)) + shot_projectile.damage = damage_increase + shot_projectile.range = range_increase + shot_projectile.aoe = max(1, aoe_increase) + //If pressure is greater than about 40 kPA, reduce damage + if(pressure > ONE_ATMOSPHERE*0.4) + shot_projectile.base_damage = 5 + return shot_projectile + else + shot_projectile.base_damage = damage_increase + return shot_projectile + + if(ispath(installed_barrel.projectile_type, /obj/item/projectile/beam)) + var/obj/item/projectile/beam/shot_projectile = new installed_barrel.projectile_type(get_turf(src)) + shot_projectile.damage = damage_increase + shot_projectile.range = range_increase + return shot_projectile /obj/item/gun/custom_ka/Initialize() . = ..() diff --git a/code/modules/item_worth/worths_list.dm b/code/modules/item_worth/worths_list.dm index b1bbdef17d2..baf0b56cc9d 100644 --- a/code/modules/item_worth/worths_list.dm +++ b/code/modules/item_worth/worths_list.dm @@ -242,7 +242,7 @@ var/list/worths = list( /obj/item/tracker_electronics = 150, /obj/item/am_containment = 5000, /obj/item/syringe_cartridge = 20, - /obj/item/silencer = 60, + /obj/item/suppressor = 60, /obj/item/fossil = 100, /obj/item/vampiric = 666, /obj/item/anobattery = 1800, diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index 647b85ab148..fe034fe5604 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -180,6 +180,16 @@ /datum/language/proc/handle_message_mode(var/message_mode) return list(src, message_mode) +/** + * Checks if a language with special physical requirements can be spoken by a mob + * Returns `TRUE` if allowed to, `FALSE` otherwise + * + * * speaker - A `mob` to check for the ability to speak the language + */ +/datum/language/proc/check_speech_restrict(mob/speaker) + SHOULD_NOT_SLEEP(TRUE) + return TRUE + // Language handling. /mob/proc/add_language(var/language) var/datum/language/new_language @@ -210,7 +220,7 @@ // Can we speak this language, as opposed to just understanding it? /mob/proc/can_speak(datum/language/speaking) - return (universal_speak || (speaking && speaking.flags & INNATE) || (speaking in src.languages)) + return (speaking.check_speech_restrict(src) && (universal_speak || (speaking && speaking.flags & INNATE) || (speaking in src.languages))) /mob/proc/get_language_prefix() if(client && client.prefs.language_prefixes && client.prefs.language_prefixes.len) @@ -251,8 +261,10 @@ if(!(L.flags & NONGLOBAL)) if(L == default_language) dat += "[L.name] ([get_language_prefix()][L.key]) - default - reset
[L.desc]

" - else + else if(can_speak(L)) dat += "[L.name] ([get_language_prefix()][L.key]) - set default
[L.desc]

" + else + dat += "[L.name] ([get_language_prefix()][L.key]) - cannot speak!
[L.desc]

" if(L.written_style) dat += "You can write in this language on papers by writing \[lang=[L.key]\]YourTextHere\[/lang\].

" diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm index d6fc731a55c..8a282746a55 100644 --- a/code/modules/mob/language/station.dm +++ b/code/modules/mob/language/station.dm @@ -179,6 +179,17 @@ syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix","*","!") allow_accents = TRUE +/datum/language/skrell/check_speech_restrict(mob/speaker) + if(!ishuman(speaker)) + return FALSE + var/mob/living/carbon/human/H = speaker + var/obj/item/organ/internal/augment/language/zeng/aug = H.internal_organs_by_name[BP_AUG_LANGUAGE] + if(istype(aug) && !isskrell(H)) + to_chat(speaker, SPAN_WARNING("You are not capable of speaking Nral'malic!")) + return FALSE + else + return TRUE + /datum/language/skrell/get_random_name() var/new_name = "" var/suff = "" diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 50f4cb20296..13667a3f07c 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -118,6 +118,8 @@ . = ..() if(. && tail_style) update_tail_showing(1) + if(lying) + update_icon(forceDirUpdate = TRUE) /mob/living/carbon/human/Move() . = ..() diff --git a/code/modules/mob/living/carbon/human/species/species_hud.dm b/code/modules/mob/living/carbon/human/species/species_hud.dm index 92b423d6894..f5129adeffc 100644 --- a/code/modules/mob/living/carbon/human/species/species_hud.dm +++ b/code/modules/mob/living/carbon/human/species/species_hud.dm @@ -62,7 +62,7 @@ /datum/hud_data/diona has_hydration = FALSE has_internals = FALSE - has_m_intent = FALSE + has_m_intent = TRUE gear = list( "i_clothing" = list("loc" = ui_iclothing, "name" = "uniform", "slot" = slot_w_uniform, "state" = "center", "toggle" = 1), "o_clothing" = list("loc" = ui_shoes, "name" = "suit", "slot" = slot_wear_suit, "state" = "suit", "toggle" = 1), @@ -110,4 +110,4 @@ "id" = list("loc" = ui_id, "name" = "id", "slot" = slot_wear_id, "state" = "id"), "storage1" = list("loc" = ui_storage1, "name" = "left pocket", "slot" = slot_l_store, "state" = "pocket"), "storage2" = list("loc" = ui_storage2, "name" = "right pocket", "slot" = slot_r_store, "state" = "pocket") - ) \ No newline at end of file + ) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 023b9e99696..92a6aabb29b 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -102,8 +102,10 @@ There are several things that need to be remembered: var/list/overlays_raw[TOTAL_LAYERS] // Our set of "raw" overlays that can be modified, but cannot be directly applied to the mob without preprocessing. var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed +#define UPDATE_ICON_IGNORE_DIRECTION_UPDATE -1 + // Updates overlays from overlays_raw. -/mob/living/carbon/human/update_icon() +/mob/living/carbon/human/update_icon(var/forceDirUpdate = FALSE) if (QDELING(src)) return // No point. @@ -135,14 +137,28 @@ There are several things that need to be remembered: add_overlay(ovr) - if (lying_prev != lying || size_multiplier != 1) + if (((lying_prev != lying) || forceDirUpdate || size_multiplier != 1) && forceDirUpdate != UPDATE_ICON_IGNORE_DIRECTION_UPDATE) if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone. var/matrix/M = matrix() - M.Turn(90) + + switch(src.dir) + if(NORTH,EAST) + M.Turn(90) + else + M.Turn(-90) M.Scale(size_multiplier) M.Translate(1,-6) - animate(src, transform = M, time = ANIM_LYING_TIME) + animate(src, transform = M, time = (forceDirUpdate ? 0 : ANIM_LYING_TIME)) + + if(istype(src.l_hand, /obj/item/gun) && lying) + HeldObjectDirTransform(slot_l_hand, src.dir) + if(istype(src.r_hand, /obj/item/gun) && lying) + HeldObjectDirTransform(slot_r_hand, src.dir) + else + update_inv_l_hand(FALSE) + update_inv_r_hand(FALSE) + update_icon(UPDATE_ICON_IGNORE_DIRECTION_UPDATE) var/matrix/M = matrix() M.Scale(size_multiplier) M.Translate(0, 16*(size_multiplier-1)) @@ -151,6 +167,37 @@ There are several things that need to be remembered: compile_overlays() lying_prev = lying +/mob/living/carbon/human/proc/HeldObjectDirTransform(var/hand = slot_l_hand, var/direction) + var/layer = null + if(hand == slot_r_hand) + update_inv_r_hand(FALSE) + layer = R_HAND_LAYER + else + update_inv_l_hand(FALSE) + layer = L_HAND_LAYER + + switch(direction) + if(EAST) + TransformLayerIcon(layer, -90) + if(WEST) + TransformLayerIcon(layer, 90) + if(NORTH) + TransformLayerIcon(layer, 0) + if(SOUTH) + TransformLayerIcon(layer, 180) + + +/mob/living/carbon/human/proc/TransformLayerIcon(var/layer, var/rotation = 0) + var/image/item_image = overlays_raw[layer] + var/matrix/item_transform = matrix() + item_transform.Turn(rotation) + + animate(item_image, transform = item_transform) + overlays_raw[layer] = item_image + update_icon(UPDATE_ICON_IGNORE_DIRECTION_UPDATE) + +#undef UPDATE_ICON_IGNORE_DIRECTION_UPDATE + //DAMAGE OVERLAYS //constructs damage icon for each organ from mask * damage field and saves it in our overlays_raw list (as a list of icons). /mob/living/carbon/human/UpdateDamageIcon(var/update_icons = 1) @@ -1152,7 +1199,7 @@ There are several things that need to be remembered: overlays_raw[L_HAND_LAYER] = null if(update_icons) - update_icon() + update_icon(forceDirUpdate = TRUE) /mob/living/carbon/human/update_inv_r_hand(var/update_icons=1) if (QDELING(src)) @@ -1188,7 +1235,7 @@ There are several things that need to be remembered: overlays_raw[R_HAND_LAYER] = null if(update_icons) - update_icon() + update_icon(forceDirUpdate = TRUE) /mob/living/carbon/human/update_inv_wrists(var/update_icons=1) if (QDELING(src)) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index a11ace30a6b..2b0e2ecd603 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -52,6 +52,7 @@ var/stamina = 0 var/max_stamina = 100//Maximum stamina. We start taking oxyloss when this runs out while sprinting var/sprint_speed_factor = 0.4 + var/lying_speed_factor = 0 var/sprint_cost_factor = 1 var/stamina_recovery = 1 var/min_walk_delay = 0//When move intent is walk, movedelay is clamped to this value as a lower bound @@ -73,4 +74,4 @@ var/limb_breaking = FALSE // used to limit people from queuing up limb-breaks var/list/obj/aura/auras //Basically a catch-all aura/force-field thing. - var/named = FALSE //Affects renaming animals and monkey species. Set to TRUE for animals with unique names, such as station pets. Doesn't affect any other mob. \ No newline at end of file + var/named = FALSE //Affects renaming animals and monkey species. Set to TRUE for animals with unique names, such as station pets. Doesn't affect any other mob. diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index d6f28ebc3ed..db48a662f58 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -836,40 +836,50 @@ lying = TRUE break else if(!resting && cannot_stand() && can_stand_overridden()) - lying = 0 - canmove = 1 + lying = FALSE + lying_is_intentional = FALSE + canmove = TRUE else if(istype(buckled_to, /obj/vehicle)) var/obj/vehicle/V = buckled_to if(is_physically_disabled()) - lying = 1 - canmove = 0 + lying = TRUE + lying_is_intentional = FALSE + canmove = FALSE pixel_y = V.mob_offset_y - 5 else if(buckled_to.buckle_lying != -1) lying = buckled_to.buckle_lying - canmove = 1 + lying_is_intentional = FALSE + canmove = TRUE pixel_y = V.mob_offset_y else if(buckled_to) - anchored = 1 - canmove = 0 + anchored = TRUE + canmove = FALSE if(isobj(buckled_to)) if(buckled_to.buckle_lying != -1) lying = buckled_to.buckle_lying + lying_is_intentional = FALSE if(buckled_to.buckle_movable) - anchored = 0 - canmove = 1 + anchored = FALSE + canmove = TRUE else if(captured) - anchored = 1 - canmove = 0 - lying = 0 + anchored = TRUE + canmove = FALSE + lying = FALSE + else if(m_intent == M_LAY && !incapacitated()) + lying = TRUE + lying_is_intentional = TRUE + canmove = TRUE else lying = MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKDOWN) + lying_is_intentional = FALSE canmove = !MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKOUT) if(lying) density = 0 - if(l_hand) unEquip(l_hand) - if(r_hand) unEquip(r_hand) + if(!lying_is_intentional) + if(l_hand) unEquip(l_hand) + if(r_hand) unEquip(r_hand) else density = initial(density) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index e9a3f911510..00bb1a63051 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -93,8 +93,9 @@ var/sleeping = 0 //Carbon var/sleeping_msg_debounce = FALSE //Carbon - Used to show a message once every time someone falls asleep. var/resting = 0 //Carbon - var/lying = 0 - var/lying_prev = 0 + var/lying = 0 // Is the mob lying down? + var/lying_prev = 0 // Was the mob lying down before? + var/lying_is_intentional = FALSE // Is the mob lying down intentionally? (eg. a manouver) var/canmove = 1 //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. var/incorporeal_move = INCORPOREAL_DISABLE diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index b27e11f1a5c..17d99a8d202 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -313,6 +313,8 @@ if (H.m_intent == M_RUN && (H.status_flags & GODMODE || H.species.handle_sprint_cost(H, tally, TRUE))) //This will return false if we collapse from exhaustion sprint_tally = tally tally = (tally / (1 + H.sprint_speed_factor)) * config.run_delay_multiplier + else if (H.m_intent == M_LAY && (H.status_flags & GODMODE || H.species.handle_sprint_cost(H, tally, TRUE))) + tally = (tally / (1 + H.lying_speed_factor)) * config.lying_delay_multiplier else tally = max(tally * config.walk_delay_multiplier, H.min_walk_delay) //clamp walking speed if its limited else diff --git a/code/modules/organs/subtypes/augment.dm b/code/modules/organs/subtypes/augment.dm index f3fe61ed4fc..0a7c8d5c0e1 100644 --- a/code/modules/organs/subtypes/augment.dm +++ b/code/modules/organs/subtypes/augment.dm @@ -470,6 +470,10 @@ name = "Zino language processor" augment_languages = list(LANGUAGE_GUTTER) +/obj/item/organ/internal/augment/language/zeng + name = "Zeng-Hu Nral'malic language processor" + augment_languages = list(LANGUAGE_SKRELLIAN) + /obj/item/organ/internal/augment/gustatorial name = "gustatorial centre" action_button_name = "Activate Gustatorial Centre (tongue)" diff --git a/code/modules/projectiles/ammo_display.dm b/code/modules/projectiles/ammo_display.dm index 810ff843314..96ce979d2c4 100644 --- a/code/modules/projectiles/ammo_display.dm +++ b/code/modules/projectiles/ammo_display.dm @@ -1,7 +1,8 @@ /obj/item/ammo_display name = "holographic ammo display" desc = "A device that can be attached to most firearms, providing a holographic display of the remaining ammunition to the user." + desc_info = "Holographic ammo displays can be attached to firearms to give an ammo readout on the HUD. Click on a weapon adjacent to you or in your hand to attach it. Use a screwdriver on the weapon to remove it." icon = 'icons/obj/weapons.dmi' icon_state = "ammo_display" origin_tech = list(TECH_BLUESPACE = 3, TECH_MATERIAL = 4, TECH_DATA = 4) - w_class = ITEMSIZE_SMALL \ No newline at end of file + w_class = ITEMSIZE_TINY diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 4585c98f4e2..8de397b790e 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -62,15 +62,51 @@ attack_verb = list("struck", "hit", "bashed") zoomdevicename = "scope" +/* + * Suppression vars + */ + + ///Does the gun have a suppressor attached, or should it be suppressed? This will modify firing messages to obscure their source, and change the firing sound to use suppressed_sound + var/suppressed = FALSE + ///The suppressor item currently attached to the gun + var/obj/item/suppressor/suppressor + ///Whether the weapon can have a suppressor attached + var/can_suppress = FALSE + ///Whether the weapon can have a suppressor unattached + var/can_unsuppress = TRUE + +/* + * Sound vars + */ + + ///Sound of the gun firing + var/fire_sound = 'sound/weapons/gunshot/gunshot1.ogg' + ///Whether to vary the frequency of the firing sound + var/vary_fire_sound = TRUE + ///The volume of the firing sound + var/fire_sound_volume = 50 + ///Sound of the gun firing when empty (dryfiring) + var/empty_sound = /singleton/sound_category/out_of_ammo + ///Determines what a player should hear in audible_message when the gun is fired. e.g gunshot, blast + var/fire_sound_text = "gunshot" + ///The firing sound to play when suppressed = TRUE + var/suppressed_sound = 'sound/weapons/gunshot/gunshot_suppressed.ogg' + ///The volume of the suppressed sound + var/suppressed_volume = 60 + ///The sound of the safety being turned on + var/safetyon_sound = 'sound/weapons/blade_open.ogg' + ///The sound of the safety being turned off + var/safetyoff_sound = 'sound/weapons/blade_close.ogg' + drop_sound = 'sound/items/drop/gun.ogg' + pickup_sound = 'sound/items/pickup/gun.ogg' + var/burst = 1 var/can_autofire = FALSE var/fire_delay = 6 //delay after shooting before the gun can be used again var/burst_delay = 1 //delay between shots, if firing in bursts var/move_delay = 0 - var/fire_sound = 'sound/weapons/gunshot/gunshot1.ogg' - var/fire_sound_text = "gunshot" + var/recoil = 0 //screen shake - var/silenced = 0 var/muzzle_flash = 3 var/accuracy = 0 //accuracy is measured in tiles. +1 accuracy means that everything is effectively one tile closer for the purpose of miss chance, -1 means the opposite. launchers are not supported, at the moment. var/offhand_accuracy = 0 // the higher this number, the more accurate this weapon is when fired from the off-hand @@ -83,8 +119,6 @@ var/displays_maptext = FALSE var/can_ammo_display = TRUE var/obj/item/ammo_display - var/empty_sound = /singleton/sound_category/out_of_ammo - var/casing_drop_sound = /singleton/sound_category/casing_drop_sound maptext_x = 22 maptext_y = 2 @@ -124,13 +158,6 @@ var/iff_capable = FALSE // if true, applies the user's ID iff_faction to the projectile - // sounds n shit - var/safetyon_sound = 'sound/weapons/blade_open.ogg' - var/safetyoff_sound = 'sound/weapons/blade_close.ogg' - - drop_sound = 'sound/items/drop/gun.ogg' - pickup_sound = 'sound/items/pickup/gun.ogg' - /obj/item/gun/Initialize(mapload) . = ..() for(var/i in 1 to firemodes.len) @@ -404,17 +431,12 @@ P.dispersion = disp P.shot_from = src.name - P.silenced = silenced + P.suppressed = suppressed P.launch_projectile(target) handle_post_fire() // should be safe to not include arguments here, as there are failsafes in effect (?) - if(silenced) - playsound(src, fire_sound, 10, 1) - else - playsound(src, fire_sound, 75, 1, 3, 0.5, 1) - if (muzzle_flash) set_light(muzzle_flash) addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, set_light), 0), 2, TIMER_UNIQUE | TIMER_OVERRIDE) @@ -450,11 +472,8 @@ //called after successfully firing /obj/item/gun/proc/handle_post_fire(mob/user, atom/target, var/pointblank = FALSE, var/reflex = FALSE, var/playemote = TRUE) - if(silenced) - playsound(user, fire_sound, 10, 1) - else - playsound(user, fire_sound, 75, 1, 3, 0.5, 1) - + play_fire_sound() + if(!suppressed) if(playemote) if(reflex) user.visible_message( @@ -484,6 +503,12 @@ S.deactivate() update_icon() +/obj/item/gun/proc/play_fire_sound() + if(suppressed) + playsound(loc, suppressed_sound, suppressed_volume, vary_fire_sound) + else + playsound(loc, fire_sound, fire_sound_volume, vary_fire_sound, falloff = 0.5, is_global = TRUE) + /obj/item/gun/proc/process_point_blank(obj/projectile, mob/user, atom/target) var/obj/item/projectile/P = projectile if(!istype(P)) @@ -578,10 +603,7 @@ handle_click_empty(user) mouthshoot = FALSE return - if(silenced) - playsound(user, fire_sound, 10, 1) - else - playsound(user, fire_sound, 75, 1, 3, 0.5, 1) + play_fire_sound() in_chamber.on_hit(M) @@ -634,6 +656,14 @@ accuracy = initial(accuracy) recoil = initial(recoil) +///Handles removing the suppressor from the gun +/obj/item/gun/proc/clear_suppressor() + if(!can_unsuppress) + return + suppressed = FALSE + suppressor = null + update_icon() + /obj/item/gun/examine(mob/user) ..() if(get_dist(src, user) > 1) @@ -756,6 +786,7 @@ update_icon() update_held_icon() + /obj/item/gun/proc/wield() wielded = TRUE update_firing_delays() @@ -766,14 +797,17 @@ update_icon() update_held_icon() +#define LYING_DOWN_FIRE_DELAY_AND_RECOIL_STAT_MULTIPLIER 0.9 //If the mob is intentionally lying down, apply this as a bonus to the fire delay and recoil +#define LYING_DOWN_ACCURACY_STAT_MULTIPLIER 1.1 //If the mob is intentionally lying down, apply this as a bonus to accuracy + /obj/item/gun/proc/update_firing_delays() if(wielded) if(fire_delay_wielded) - fire_delay = fire_delay_wielded + fire_delay = usr.lying_is_intentional ? (fire_delay_wielded * LYING_DOWN_FIRE_DELAY_AND_RECOIL_STAT_MULTIPLIER) : fire_delay_wielded if(recoil_wielded) - recoil = recoil_wielded + recoil = usr.lying_is_intentional ? (recoil_wielded * LYING_DOWN_FIRE_DELAY_AND_RECOIL_STAT_MULTIPLIER) : recoil_wielded if(accuracy_wielded) - accuracy = accuracy_wielded + accuracy = usr.lying_is_intentional ? (accuracy_wielded * LYING_DOWN_ACCURACY_STAT_MULTIPLIER) : accuracy_wielded else if(fire_delay_wielded) fire_delay = initial(fire_delay) @@ -782,6 +816,9 @@ if(accuracy_wielded) accuracy = initial(accuracy) +#undef LYING_DOWN_FIRE_DELAY_AND_RECOIL_STAT_MULTIPLIER +#undef LYING_DOWN_ACCURACY_STAT_MULTIPLIER + /obj/item/gun/mob_can_equip(mob/user, slot, disable_warning, ignore_blocked) //Cannot equip wielded items. if(wielded) @@ -865,6 +902,8 @@ QDEL_NULL(pin) if(bayonet) QDEL_NULL(bayonet) + if(istype(suppressor)) + QDEL_NULL(suppressor) return ..() @@ -894,15 +933,21 @@ /obj/item/gun/attackby(var/obj/item/I, var/mob/user) if(istype(I, /obj/item/material/knife/bayonet)) if(!can_bayonet) + balloon_alert(user, "\the [I.name] doesn't fit") return ..() + if(user.l_hand != bayonet && user.r_hand != bayonet) + balloon_alert(user, "not in hand") + return + if(bayonet) - to_chat(user, SPAN_WARNING("There is a bayonet attached to \the [src] already!")) + balloon_alert(user, "\the [src] already has a bayonet") return TRUE user.drop_from_inventory(I,src) bayonet = I - to_chat(user, SPAN_NOTICE("You attach \the [I] to the front of \the [src].")) + balloon_alert(user, "[I.name] attached") + w_class += I.w_class update_icon() return TRUE @@ -911,24 +956,29 @@ if(istype(I, /obj/item/ammo_display)) if(!can_ammo_display) - to_chat(user, SPAN_WARNING("\The [I] cannot attach to \the [src].")) + balloon_alert(user, "\the [I.name] doesn't fit") return TRUE + if(user.l_hand != ammo_display && user.r_hand != ammo_display) + balloon_alert(user, "not in hand") + return if(ammo_display) - to_chat(user, SPAN_WARNING("\The [src] already has a holographic ammo display.")) + balloon_alert(user, "\the [src] already has an ammo display") return TRUE if(displays_maptext) - to_chat(user, SPAN_WARNING("\The [src] is already displaying its ammo count.")) + balloon_alert(user, "\the [src] is already displaying its ammo count") return TRUE user.drop_from_inventory(I, src) ammo_display = I displays_maptext = TRUE - to_chat(user, SPAN_NOTICE("You attach \the [I] to \the [src].")) + balloon_alert(user, "[I.name] attached") + w_class += I.w_class return TRUE if(I.iscrowbar() && bayonet) to_chat(user, SPAN_NOTICE("You detach \the [bayonet] from \the [src].")) bayonet.forceMove(get_turf(src)) user.put_in_hands(bayonet) + w_class -= bayonet.w_class bayonet = null update_icon() return TRUE @@ -937,6 +987,7 @@ to_chat(user, SPAN_NOTICE("You wrench the ammo display loose from \the [src].")) ammo_display.forceMove(get_turf(src)) user.put_in_hands(ammo_display) + w_class -= ammo_display.w_class ammo_display = null displays_maptext = FALSE maptext = "" diff --git a/code/modules/projectiles/guns/energy/modular.dm b/code/modules/projectiles/guns/energy/modular.dm index 6ef555b8f7c..ff22caf4381 100644 --- a/code/modules/projectiles/guns/energy/modular.dm +++ b/code/modules/projectiles/guns/energy/modular.dm @@ -144,7 +144,7 @@ for(var/obj/item/laser_components/modifier/modifier in gun_mods) switch(modifier.mod_type) if(MOD_SILENCE) - silenced = 1 + suppressed = TRUE if(MOD_NUCLEAR_CHARGE) self_recharge = 1 criticality *= 2 diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index f0253419621..cfca1b13b6e 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -47,7 +47,8 @@ origin_tech = list(TECH_COMBAT = 2, TECH_MAGNET = 2, TECH_ILLEGAL = 5) matter = list(DEFAULT_WALL_MATERIAL = 2000) slot_flags = SLOT_BELT - silenced = 1 + suppressed = TRUE + can_unsuppress = FALSE fire_sound = 'sound/weapons/Genhit.ogg' projectile_type = /obj/item/projectile/energy/bolt max_shots = 5 diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 3859a5fb03e..02029935457 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -27,6 +27,11 @@ var/unjam_cooldown = 0 //Gives the unjammer some time after spamming unjam to not eject their mag var/jam_chance = 0 //Chance it jams on fire + ///Pixel offset for the suppressor overlay on the x axis. + var/suppressor_x_offset + ///Pixel offset for the suppressor overlay on the y axis. + var/suppressor_y_offset + //TODO generalize ammo icon states for guns //var/magazine_states = 0 //var/list/icon_keys = list() //keys @@ -49,6 +54,16 @@ QDEL_NULL_LIST(loaded) . = ..() +/obj/item/gun/projectile/update_icon() + ..() + if(suppressed) + var/mutable_appearance/MA = mutable_appearance('icons/obj/guns/suppressor.dmi', "suppressor") + if(suppressor_x_offset) + MA.pixel_x = suppressor_x_offset + if(suppressor_y_offset) + MA.pixel_y = suppressor_y_offset + underlays += MA + /obj/item/gun/projectile/consume_next_projectile() if(jam_num) return FALSE @@ -212,9 +227,26 @@ update_maptext() update_icon() -/obj/item/gun/projectile/attackby(obj/item/A, mob/user) +/obj/item/gun/projectile/attackby(obj/item/I, mob/user) . = ..() - load_ammo(A, user) + if(.) + return + load_ammo(I, user) + if(istype(I, /obj/item/suppressor)) + var/obj/item/suppressor/S = I + if(!can_suppress) + balloon_alert(user, "\the [S.name] doesn't fit") + return + if(user.l_hand != suppressor && user.r_hand != suppressor) + balloon_alert(user, "not in hand") + return + if(suppressed) + balloon_alert(user, "already has a suppressor") + return + user.drop_from_inventory(suppressor, src) + balloon_alert(user, "[S.name] attached") + install_suppressor(S) + return /obj/item/gun/projectile/toggle_firing_mode(mob/user) if(jam_num) @@ -261,6 +293,8 @@ to_chat(user, "It looks jammed.") if(ammo_magazine) to_chat(user, "It has \a [ammo_magazine] loaded.") + if(suppressed) + to_chat(user, "It has a suppressor attached.") to_chat(user, "Has [get_ammo()] round\s remaining.") return @@ -296,3 +330,26 @@ else . += "No magazine inserted.
" . += ..(FALSE) + +///Installs a new suppressor, assumes that the suppressor is already in the contents of src +/obj/item/gun/projectile/proc/install_suppressor(obj/item/suppressor/S) + suppressed = TRUE + w_class += S.w_class //Add our weight class to the item's weight class + suppressor = S + update_icon() + +/obj/item/gun/projectile/clear_suppressor() + if(!can_unsuppress) + return + if(istype(suppressor)) + w_class -= suppressor.w_class + return ..() + +/obj/item/gun/projectile/AltClick(mob/user) + if(use_check_and_message(user)) + return + if(suppressed && can_unsuppress) + balloon_alert(user, "[suppressor.name] removed") + user.put_in_hands(suppressor) + clear_suppressor() + return ..() diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index 2462a321e71..378b5453b88 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -16,6 +16,8 @@ burst_delay = 2 sel_mode = 1 fire_delay = ROF_SMG + can_suppress = TRUE + suppressor_x_offset = 8 firemodes = list( list(mode_name="semiauto", can_autofire=0, burst=1, fire_delay=ROF_SMG), @@ -40,6 +42,9 @@ caliber = ".45" origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 2, TECH_ILLEGAL = 8) ammo_type = /obj/item/ammo_casing/c45 + suppressed = FALSE + can_suppress = TRUE + suppressor_x_offset = 10 /obj/item/gun/projectile/automatic/mini_uzi/update_icon() ..() @@ -65,6 +70,9 @@ allowed_magazines = list(/obj/item/ammo_magazine/a10mm) auto_eject = 1 auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg' + suppressed = FALSE + can_suppress = TRUE + suppressor_x_offset = 11 /obj/item/gun/projectile/automatic/c20r/update_icon() ..() @@ -80,6 +88,7 @@ icon = 'icons/obj/guns/sol_smg.dmi' icon_state = "vityaz" item_state = "vityaz" + suppressor_x_offset = 10 /obj/item/gun/projectile/automatic/c20r/sol/update_icon() ..() @@ -100,6 +109,9 @@ load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/mc9mmt/rubber allowed_magazines = list(/obj/item/ammo_magazine/mc9mmt) + can_suppress = TRUE + suppressor_x_offset = 10 + suppressor_y_offset = -1 /obj/item/gun/projectile/automatic/wt550/lethal magazine_type = /obj/item/ammo_magazine/mc9mmt @@ -133,6 +145,7 @@ fire_delay = ROF_RIFLE is_wieldable = TRUE + can_suppress = FALSE firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=ROF_RIFLE), @@ -529,6 +542,10 @@ allowed_magazines = list(/obj/item/ammo_magazine/submachinemag, /obj/item/ammo_magazine/submachinedrum) fire_sound = 'sound/weapons/gunshot/gunshot_tommygun.ogg' + can_suppress = TRUE + suppressor_x_offset = 10 + suppressor_y_offset = -1 + /obj/item/gun/projectile/automatic/tommygun/update_icon() ..() icon_state = (ammo_magazine)? "tommygun" : "tommygun-empty" @@ -566,6 +583,8 @@ auto_eject = 1 auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg' + can_suppress = FALSE + firemodes = list( list(mode_name="single coil", burst = 1), list(mode_name="dual coil", burst = 2, move_delay = 1, accuracy = list(-2,-3), dispersion = list(20)) @@ -589,6 +608,8 @@ auto_eject = 1 auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg' + can_suppress = FALSE + is_wieldable = TRUE firemodes = list( diff --git a/code/modules/projectiles/guns/projectile/dartgun.dm b/code/modules/projectiles/guns/projectile/dartgun.dm index b41a9ea028d..4452c4102bd 100644 --- a/code/modules/projectiles/guns/projectile/dartgun.dm +++ b/code/modules/projectiles/guns/projectile/dartgun.dm @@ -52,7 +52,8 @@ fire_sound_text = "a metallic click" accuracy = 1 recoil = 0 - silenced = 1 + suppressed = TRUE + can_unsuppress = FALSE load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/chemdart auto_eject = 0 diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index ff19c03a70b..f7e83cca274 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -198,9 +198,9 @@ icon_state = "c05r-e" /obj/item/gun/projectile/silenced - name = "silenced pistol" + name = "suppressed pistol" desc = "A small, quiet, easily concealable gun." - desc_extended = "Created as a disposable and concealable weapon, the Mrrazhakulii suppressed pistol is a firearm with a silencer integrated as part of its barrel. \ + desc_extended = "Created as a disposable and concealable weapon, the Mrrazhakulii suppressed pistol is a firearm with a suppressor integrated as part of its barrel. \ Carried by guerrilla forces and spies, those guns are used in assassination and subterfuge operations. Due to using cheap and available materials, such as \ recycled iron and tires, countless of those pistols were distributed among cells and ALA soldiers." icon = 'icons/obj/guns/silenced_pistol.dmi' @@ -211,7 +211,8 @@ accuracy = 1 offhand_accuracy = 1 caliber = ".45" - silenced = 1 + suppressed = TRUE + can_unsuppress = FALSE origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ILLEGAL = 8) load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/c45m @@ -295,14 +296,15 @@ accuracy = 1 offhand_accuracy = 2 caliber = "9mm" - silenced = 0 + suppressed = FALSE + can_suppress = TRUE origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ILLEGAL = 2) fire_sound = 'sound/weapons/gunshot/gunshot_pistol.ogg' load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/mc9mm allowed_magazines = list(/obj/item/ammo_magazine/mc9mm) - var/can_silence = TRUE fire_delay = ROF_PISTOL + suppressor_x_offset = 5 /obj/item/gun/projectile/pistol/flash name = "9mm signal pistol" @@ -316,7 +318,7 @@ icon = 'icons/obj/guns/detgun.dmi' icon_state = "detgun" item_state = "detgun" - can_silence = FALSE + can_suppress = FALSE /obj/item/gun/projectile/pistol/detective/update_icon() ..() @@ -338,56 +340,12 @@ name = input to_chat(usr, "You name the gun [input]. Say hello to your new friend.") -/obj/item/gun/projectile/pistol/attack_hand(mob/user as mob) - if(user.get_inactive_hand() == src) - if(silenced && can_silence) - if(user.l_hand != src && user.r_hand != src) - ..() - return - to_chat(user, "You unscrew [silenced] from [src].") - user.put_in_hands(silenced) - silenced = 0 - w_class = ITEMSIZE_SMALL - update_icon() - return - ..() - -/obj/item/gun/projectile/pistol/attackby(obj/item/I as obj, mob/user as mob) - if(istype(I, /obj/item/silencer) && can_silence) - if(user.l_hand != src && user.r_hand != src) //if we're not in his hands - to_chat(user, "You'll need [src] in your hands to do that.") - return - user.drop_from_inventory(I,src) - to_chat(user, "You screw [I] onto [src].") - silenced = I //dodgy? - w_class = ITEMSIZE_NORMAL - update_icon() - return - ..() - /obj/item/gun/projectile/pistol/update_icon() ..() - if(silenced) - icon_state = "pistol-silencer" - else - icon_state = "pistol" - -/obj/item/gun/projectile/pistol/update_icon() - ..() - if(silenced) - icon_state = "pistol-silencer" - else - icon_state = "pistol" + icon_state = "pistol" if(!(ammo_magazine && ammo_magazine.stored_ammo.len)) icon_state = "[icon_state]-e" -/obj/item/silencer - name = "silencer" - desc = "A silencer" - icon = 'icons/obj/guns/pistol.dmi' - icon_state = "silencer" - w_class = ITEMSIZE_SMALL - /obj/item/gun/projectile/pirate name = "zip gun" desc = "Little more than a barrel, handle, and firing mechanism, cheap makeshift firearms like this one are not uncommon in frontier systems." @@ -447,7 +405,9 @@ icon = 'icons/obj/guns/sol_pistol.dmi' icon_state = "m8" item_state = "m8" - can_silence = FALSE + can_suppress = TRUE + suppressor_x_offset = 9 + suppressor_y_offset = 3 /obj/item/gun/projectile/pistol/sol/update_icon() ..() @@ -462,7 +422,7 @@ icon = 'icons/obj/guns/adhomian_pistol.dmi' icon_state = "adhomian_pistol" item_state = "adhomian_pistol" - can_silence = FALSE + can_suppress = FALSE desc_extended = "A mass produced pistol issued to People's Republic officers, government officials and low-ranking Party members. Known for their simple, cheap and reliable \ design, this weapon is produced by nearly all weapon factories in the Republic. The Adar'Mazy is also found in the hands of Adhomai Liberation Army soldiers and commanders." @@ -484,7 +444,7 @@ icon_state = "k2557-loaded" item_state = "k2557-loaded" contained_sprite = TRUE - can_silence = FALSE + can_suppress = FALSE w_class = ITEMSIZE_NORMAL load_method = MAGAZINE handle_casings = EJECT_CASINGS diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm index 00a9e89cda6..f368fad6f8e 100644 --- a/code/modules/projectiles/guns/projectile/sniper.dm +++ b/code/modules/projectiles/guns/projectile/sniper.dm @@ -152,7 +152,8 @@ origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2) caliber = "PPS" recoil = 1 - silenced = 1 + suppressed = TRUE + can_unsuppress = FALSE fire_sound = 'sound/weapons/gunshot/gunshot_light.ogg' max_shells = 4 ammo_type = null diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index a6509195a1f..e28063c705f 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -16,7 +16,7 @@ var/def_zone = "" //Aiming at var/hit_zone // The place that actually got hit var/mob/firer = null//Who shot it - var/silenced = FALSE //Attack message + var/suppressed = FALSE //Attack message var/shot_from = "" // name of the object which shot us @@ -174,7 +174,7 @@ /obj/item/projectile/proc/launch_from_gun(atom/target, target_zone, mob/user, params, angle_override, forced_spread, obj/item/gun/launcher) shot_from = launcher.name - silenced = launcher.silenced + suppressed = launcher.suppressed if(launcher.iff_capable && user) iff = get_iff_from_user(user) @@ -206,7 +206,7 @@ switch(result) if(PROJECTILE_FORCE_MISS) if(!point_blank) - if(!silenced) + if(!suppressed) target_mob.visible_message("\The [src] misses [target_mob] narrowly!") playsound(target_mob, /singleton/sound_category/bulletflyby_sound, 50, 1) return FALSE @@ -217,7 +217,7 @@ var/impacted_organ = target_mob.get_organ_name_from_zone(def_zone) //hit messages - if(silenced) + if(suppressed) to_chat(target_mob, "You've been hit in the [impacted_organ] by \a [src]!") else target_mob.visible_message("\The [target_mob] is hit by \a [src] in the [impacted_organ]!", "You are hit by \a [src] in the [impacted_organ]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter @@ -621,7 +621,7 @@ /obj/item/projectile/proc/generate_muzzle_flash(duration = 3) if(duration <= 0) return - if(!muzzle_type || silenced) + if(!muzzle_type || suppressed) return var/datum/point/p = trajectory var/atom/movable/thing = new muzzle_type @@ -639,7 +639,7 @@ if(tracer_type) for(var/datum/point/p in beam_segments) generate_tracer_between_points(p, beam_segments[p], tracer_type, color, duration) - if(muzzle_type && !silenced) + if(muzzle_type && !suppressed) var/datum/point/p = beam_segments[1] var/atom/movable/thing = new muzzle_type p.move_atom_to_src(thing) diff --git a/code/modules/projectiles/suppressor.dm b/code/modules/projectiles/suppressor.dm new file mode 100644 index 00000000000..36a482c4b83 --- /dev/null +++ b/code/modules/projectiles/suppressor.dm @@ -0,0 +1,8 @@ +/obj/item/suppressor + name = "suppressor" + desc = "A suppressor" + desc_info = "Suppressors can be attached to weapons to reduce their sound. Click on a weapon adjacent to you or in your hand to attach it. Alt-Click the weapon to remove it." + icon = 'icons/obj/guns/suppressor.dmi' + icon_state = "suppressor_item" + origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 3) + w_class = ITEMSIZE_SMALL diff --git a/html/changelog.html b/html/changelog.html index 1ceb1ec572f..eabc671bb1a 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -35,6 +35,69 @@ -->
+

05 September 2023

+

CampinKiller24 updated:

+ +

FluffyGhost updated:

+ +

GeneralCamo updated:

+ + +

04 September 2023

+

CampinKiller24 updated:

+ +

GeneralCamo updated:

+ +

Noble Row updated:

+ + +

03 September 2023

+

FluffyGhost updated:

+ +

GeneralCamo updated:

+ +

RustingWithYou updated:

+ +

SleepyGemmy updated:

+ +

02 September 2023

Blundir updated: