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 @@
-->