Files
6508994fdf Cabbage's Armory (#5757)
## Main Additions and Modifications
This PR adds in a quite a few new things.
### Overview
**WT-550 "Enhancements"** - made available via research. These
modifications retain the full-auto capability of the WT-550 to varying
degrees. Additionally a compressed WT550 magazine is available via
research. It contains 40 weaker bullets compared to the normal
magazine's 20. It is only allowed to contain compressed bullets to avoid
cheesing, and requires bluespace to fabricate. It is designed as a
sustained dps ammunition as opposed to a high dps ammunition
**WT-550-B** - Shoots in bursts with decent recoil and slightly higher
dps.
**WT-550-C** - Shoots slower but has a higher damage and projectile
velocity along with a scope.
**Sawn-off WT-550** - Is smaller but has egregious recoil and spread.
**.38 BR** - A simple but slightly less powerful alternative to the
NT-38 battle rifle. Craftable via a kit obtained from research.
**Stunstaff** - A weapon that is available via crafting and functions as
an alternative to a baton and riot shield. A heroic variant exists
within the code but the recipe can only be learned from a book that
sometimes spawns in the armory contraband closet.
**Advanced Energy SMG** - A hybrid of a disabler SMG, laser carbine, and
advanced energy gun. Does exactly what you think it does. Obtainable via
crafting.
**Stingballer** - A rifle that rapidly shoots stingballs. Direct damage
is lesser than a stingbang. Purchasable from cargo.
**Security Juggernaut Suit** - A heavily armoured suit that severely
cripples your mobility in exchange for very high protection. Crafting
kit is printable from a technode.
**Horizon Beam Rifle** - Damage is now 110 with 35 armor piercing, and a
demo mod of 2. Upon contact with walls, it destroys them like how a
pulse laser does.

### Crafting
WT-550 weapons can all be made with just the gun and the kit.
The sawn-off WT550 can be made by taking a saw to the WT550.
The .38 BR requires an NT-38 battle rifle along with a multitool and a
screwdriver.
The Advanced Energy SMG requires a disabler smg, laser carbine, and an
advanced energy gun.
The Stunstaff requires two security batons, some plasteel and some
cable, along with a welder and wrench.
The Heroic Stunstaff requires some other ingredients.
The Security Juggernaut suit requires a full toolbox of tools as well as
the armor plates, a full coil of cable, a pair of magboots, a swat
helmet, a swat suit, and two seclites.
Stingbangs can be prepared into stingball canisters with a screwdriver
and some wirecutters. Each contains 25 rounds are are used to fill the
stingballer.

### Cargo
**Stingballer** - Armory crate - Contains one stingballer. - 4500
credits.
**Grenade Launcher** - Armory crate - Contains one grenade launcher and
a box of flashbangs. - 15000 credits.
**Kiboko Grenade Launcher** - Armory crate - Contains one Kiboko grenade
launcher. - 7500 credits.

### R&D
The **"Ballisitic Research"** technode has been removed and dragon's
breath shells have been moved to the illegal technology node. The node
remains within the code though if more exotic ammunition is developed
and requires an additional research node for it.
New **"Advanced Ballistics"** technode contains the part kits for the
WT-550 modifications and NT-BR simplification kit and requires Exotic
Ammunition to research.
New **"Advanced Armor"** technode contains the Security Juggernaut
Plates and requires Riot Suppression and Gas Compression to research.

### Code
Adds to the buckling system where if something has TRAIT_NO_BUCKLE, it
cannot be buckled at all.
Adds to the vehicle system where if something has TRAIT_NO_VEHICLE, it
will be flung off the vehicle it attempts to move the vehicle
themselves.
Adds to the chair system where if something has TRAIT_NO_VEHICLE, it
will destroy the chair.
Adds to the movement system where if something has TRAIT_LARGE_CLOTHES,
TRAIT_BULKY_CLOTHES, or TRAIT_HUGE_CLOTHES, it will incur a 3, 4, and 5
move speed multiplier when pulling that thing. If anyone can help me do
this more modular, please reach out, I have no clue how.
Edits the equipment slowdown system to properly apply a special slowdown
that cannot be negated by anything. Requires the TRUE_IMMUTABLE_SLOW
bubber_obj_flag to be present. IMMUTABLE_SLOW is still required for red
potion immunity.

### Other Misc. Changes
The WT-551 has been effectively rendered impossible to get. This
decision stems from the fact that the WT-550 and the WT-551 were
functionally identical when used in-game. Instances of the 551 have been
replaced with the 550.
Skyrat's renaming of /tg/ bullets has been completely removed. Some
descriptions have been kept and altered because they were kinda neat.
.460 Ceres -> .45
.416 Stabilis -> .50 BMG
8mm Usurpator -> 4.6x30mm
.454 Trucidator -> .50 Action Express
.277 Aestus -> .223

## Statistics For New Additions
**Stunstaff**
<img width="32" height="32" alt="image"
src="https://github.com/user-attachments/assets/0e1c2a1a-20ba-47a9-91f1-e63ca11b5e43"
/>
- Two-handed, bulky. Fits on the back and an armor vest.
- 65 stamina damage
- 20 stun armour penetration
- 14 force
- 8 throw force
- 50 block chance
- 20 effective block vs tackles
- 10 effective block vs projectiles

**Heroic Stunstaff**
- 24 stamina damage
- 0.5 second stun
- 4 times the cell charge consumption
- No cooldown between stuns
- 35 stun armor penetration
- 15 force
- 10 throw force
- 75% throw stun chance
- Can be thrown like a boomerang
- 75 block chance
- 30 effective block vs tackles
- 50 effective block vs projectiles

**WT-550-B**
<img width="32" height="32" alt="image"
src="https://github.com/user-attachments/assets/56fea4dd-9b0c-4e06-93a7-b0389f3d32c9"
/>
- Bulky sized, small weapon weight, dual wielding.
- 2 round burst every 0.5 seconds
- 0.25 recoil
- 3 spread
- Can be suppressed

**WT-550-C**
<img width="48" height="32" alt="image"
src="https://github.com/user-attachments/assets/bd80570d-3e70-463d-8b6b-7cefcb1d54e6"
/>
- Bulky sized, heavy weapon weight, no dual wielding.
- Half fire rate of normal WT (0.6 compared to 0.3)
- 1.5x damage multiplier
- 1.5x projectile speed multiplier
- +5 projectile wound bonus
- Can be Suppressed
- Mediocre Scope

**Sawn-off WT-550**
<img width="32" height="32" alt="image"
src="https://github.com/user-attachments/assets/6d786022-2d93-42da-9dcc-fe6dfadbbce1"
/>
- Normal sized, light weapon weight, dual wielding
- 10 spread
- 20 dual wielded spread
- Sawn-off recoil (high)

**Compressed WT-550 magazine**
- 40 capacity
- 12 damage (20 for normal rounds)

**Stingballer**
<img width="32" height="32" alt="image"
src="https://github.com/user-attachments/assets/de30bda5-9e0b-44da-8097-ca9827d3d8c8"
/>
- Bulky sized, normal weapon weight, no dual wielding.
- 8 rounds per second
- 7.5 spread
- 50 round capacity
- 1.5 damage
- 4 stamina damage
- Embed chance at close range
- Bouncy projectile
- Low effective range

**.38 Battle Rifle**
<img width="48" height="32" alt="image"
src="https://github.com/user-attachments/assets/24a9a257-97fe-4313-ba39-93d17230f1b4"
/>
- Overall same statistics as the NT-38 Battle Rifle except for
- 1.0x damage multiplier (compared to 1.2x)
- 1.0x projectile speed multiplier (compared to 1.2x)
- 25.0% faster rate of fire (1.5 compared to 2)
- No degradation mechanics
- No scope

**Advanced Energy SMG**
<img width="32" height="32" alt="image"
src="https://github.com/user-attachments/assets/2671009a-a994-4054-92ff-4db2959501e8"
/>
- Bulky Size, no dual wielding.
- 0.8x damage multiplier (12 on kill, 12 on disable)
- 1.2x projectile speed multiplier
- 40 shots on kill, 40 shots on disable
- Charges about half as fast as the regular advanced energy gun.
- Same fire rate as the disabler SMG
- 2 spread

**Security Juggernaut Suit**
<img width="32" height="32" alt="image"
src="https://github.com/user-attachments/assets/5de0a084-4a07-4d8f-88a3-d9996de41010"
/>
- Built in helmet
- Helmet protects head from flashes, loud noises, impacts and
pepperspray
- Full temperature and pressure protection
- Helmet has powerful flashlight mounted
- Takes 12 seconds to put on, 15 to put on someone else
- Slows you down everywhere
- Slows you down when in-hand
- Slows down someone who's dragging you
- Prevents aggressive grabs against you when worn
- Prevents combat-mode pushing against you when worn
- Prevents shove knockdowns when worn
- Prevents gravity effects when worn
- Prevents buckling when worn
- Cannot be red potion'd.
- Does NOT protect against batons or knockdown.

Current Armor values:
- melee = 80
- bullet = 80
- laser = 70
- energy = 60
- bomb = 100
- bio = 100
- fire = 100
- acid = 100
- wound = 30

## Why It's Good For The Game

This PR adds in quite a few items that fill certain role archetypes
within security while allowing them to still use equipment that security
would already have.

## Proof Of Testing

Testing overall has been completed.

Testing left to do:
- [x] Cargo Orders

## Changelog
🆑
add: Added a bunch of alternative additional weapon and equipment
upgrade options to security, allowing a little bit of difference in the
late-game arsenal or general armament.
add: Adds the WT-550-B and WT-550-C, upgrades to the classic autorifle.
add: The WT550 can now also be sawn-off.
add: Adds the Stingballer, a close range weapon that rapidly shoots
stingballs.
add: Adds the Stunstaff, an aura-farming alternative to the classic
baton and shield.
add: Adds the Advanced Energy SMG, an a modified AEG that gains
rapid-fire capabilites.
add: Adds the Security Juggernaut suit, an impossibly slow suit that
hinders your movement but has some of the best armour you'll ever see.
add: Adds the .38 battle rifle, a simplified NT-38 Battle Rifle. Lacks
the combat improvements, but does not degrade.
balance: The Horizon Beam Rifle's performance has been tweaked. Damage
is now 110, with 35 armor penetration and a demolition mod of 2, as well
as the ability to destroy walls like pulse rifles.
add: The Kiboko and pneumatic grenade launcher can be bought from cargo
now.
del: The WT-551 has be completely removed and replaced with the WT-550
del: Any instances of Skyrat's ammunition naming system have been wiped.
Please report any inconsistencies you may find.
/🆑

---------

Co-authored-by: Cabbage <supredoode@gmail.com>
Co-authored-by: Mathilde <146444134+ibexgoetia@users.noreply.github.com>
Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
2026-07-19 12:24:29 -07:00

771 lines
27 KiB
Plaintext

/obj/structure/chair
name = "chair"
desc = "You sit in this. Either by will or force."
icon = 'icons/obj/chairs.dmi'
icon_state = "chair"
anchored = TRUE
can_buckle = TRUE
buckle_lying = 0 //you sit in a chair, not lay
resistance_flags = NONE
max_integrity = 100
integrity_failure = 0.1
custom_materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT)
layer = OBJ_LAYER
interaction_flags_mouse_drop = ALLOW_RESTING
var/buildstacktype = /obj/item/stack/sheet/iron
var/buildstackamount = 1
var/item_chair = /obj/item/chair // if null it can't be picked up
///How much sitting on this chair influences fishing difficulty
var/fishing_modifier = -5
var/has_armrest = FALSE
/obj/structure/chair/Initialize(mapload)
. = ..()
if(prob(0.2))
name = "tactical [name]"
fishing_modifier -= 8
MakeRotate()
if(can_buckle && fishing_modifier)
AddElement(/datum/element/adjust_fishing_difficulty, fishing_modifier)
/obj/structure/chair/buckle_feedback(mob/living/being_buckled, mob/buckler)
if(HAS_TRAIT(being_buckled, TRAIT_RESTRAINED))
return ..()
if(being_buckled == buckler)
being_buckled.visible_message(
span_notice("[buckler] sits down on [src]."),
span_notice("You sit down on [src]."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
else
being_buckled.visible_message(
span_notice("[buckler] sits [being_buckled] down on [src]."),
span_notice("[buckler] sits you down on [src]."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
/obj/structure/chair/unbuckle_feedback(mob/living/being_unbuckled, mob/unbuckler)
if(HAS_TRAIT(being_unbuckled, TRAIT_RESTRAINED))
return ..()
if(being_unbuckled == unbuckler)
being_unbuckled.visible_message(
span_notice("[unbuckler] stands up from [src]."),
span_notice("You stand up from [src]."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
else
being_unbuckled.visible_message(
span_notice("[unbuckler] stands [being_unbuckled] up from [src]."),
span_notice("[unbuckler] stands you up from [src]."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
/obj/structure/chair/examine(mob/user)
. = ..()
. += span_notice("It's held together by a couple of <b>bolts</b>.")
if(!has_buckled_mobs() && can_buckle)
. += span_notice("While standing on [src], drag and drop your sprite onto [src] to buckle to it.")
///This proc adds the rotate component, overwrite this if you for some reason want to change some specific args.
/obj/structure/chair/proc/MakeRotate()
AddElement(/datum/element/simple_rotation, ROTATION_IGNORE_ANCHORED|ROTATION_GHOSTS_ALLOWED)
/obj/structure/chair/Destroy()
SSjob.latejoin_trackers -= src //These may be here due to the arrivals shuttle
return ..()
/obj/structure/chair/atom_deconstruct(disassembled)
if(buildstacktype)
new buildstacktype(loc,buildstackamount)
else
for(var/datum/material/mat as anything in custom_materials)
new mat.sheet_type(loc, FLOOR(custom_materials[mat] / SHEET_MATERIAL_AMOUNT, 1))
/obj/structure/chair/attack_paw(mob/user, list/modifiers)
return attack_hand(user, modifiers)
/obj/structure/chair/narsie_act()
var/obj/structure/chair/wood/W = new/obj/structure/chair/wood(get_turf(src))
W.setDir(dir)
qdel(src)
/obj/structure/chair/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
if(istype(W, /obj/item/assembly/shock_kit) && !HAS_TRAIT(src, TRAIT_ELECTRIFIED_BUCKLE))
electrify_self(W, user)
return
. = ..()
/obj/structure/chair/update_overlays()
. = ..()
if (!has_buckled_mobs())
return
var/mutable_appearance/armrest = mutable_appearance(icon, "[icon_state]_armrest", ABOVE_MOB_LAYER, src, appearance_flags = KEEP_APART)
var/mutable_appearance/armrest_blocker = emissive_blocker(icon, "[icon_state]_armrest", src, ABOVE_MOB_LAYER)
if (cached_color_filter)
armrest = filter_appearance_recursive(armrest, cached_color_filter)
. += armrest
. += armrest_blocker
///allows each chair to request the electrified_buckle component with overlays that dont look ridiculous
/obj/structure/chair/proc/electrify_self(obj/item/assembly/shock_kit/input_shock_kit, mob/user, list/overlays_from_child_procs)
SHOULD_CALL_PARENT(TRUE)
if(!user.temporarilyRemoveItemFromInventory(input_shock_kit))
return
if(!overlays_from_child_procs || overlays_from_child_procs.len == 0)
var/mutable_appearance/echair_overlay = mutable_appearance('icons/obj/chairs.dmi', "echair_over", OBJ_LAYER, src, appearance_flags = KEEP_APART)
AddComponent(/datum/component/electrified_buckle, (SHOCK_REQUIREMENT_ITEM | SHOCK_REQUIREMENT_LIVE_CABLE | SHOCK_REQUIREMENT_SIGNAL_RECEIVED_TOGGLE), input_shock_kit, list(echair_overlay), FALSE)
else
AddComponent(/datum/component/electrified_buckle, (SHOCK_REQUIREMENT_ITEM | SHOCK_REQUIREMENT_LIVE_CABLE | SHOCK_REQUIREMENT_SIGNAL_RECEIVED_TOGGLE), input_shock_kit, overlays_from_child_procs, FALSE)
if(HAS_TRAIT(src, TRAIT_ELECTRIFIED_BUCKLE))
to_chat(user, span_notice("You connect the shock kit to \the [src], electrifying it "))
else
user.put_in_active_hand(input_shock_kit)
to_chat(user, span_notice("You cannot fit the shock kit onto \the [src]!"))
/obj/structure/chair/wrench_act_secondary(mob/living/user, obj/item/weapon)
..()
weapon.play_tool_sound(src)
deconstruct(disassembled = TRUE)
return TRUE
/obj/structure/chair/attack_tk(mob/user)
if(!anchored || has_buckled_mobs() || !isturf(user.loc))
return ..()
setDir(turn(dir,-90))
return COMPONENT_CANCEL_ATTACK_CHAIN
/obj/structure/chair/proc/handle_rotation(direction)
handle_layer()
if(has_buckled_mobs())
for(var/m in buckled_mobs)
var/mob/living/buckled_mob = m
buckled_mob.setDir(direction)
/obj/structure/chair/proc/handle_layer()
if(has_buckled_mobs() && dir == NORTH)
layer = ABOVE_MOB_LAYER
else
layer = OBJ_LAYER
/obj/structure/chair/post_buckle_mob(mob/living/M)
. = ..()
handle_layer()
//SKYRAT EDIT ADDITION
if(HAS_TRAIT(M, TRAIT_OVERSIZED) || HAS_TRAIT(M, TRAIT_NO_VEHICLE))
visible_message(span_warning("[src] buckles under the weight of [M] causing it to break!"))
playsound(src, 'modular_skyrat/modules/oversized/sound/chair_break.ogg', 70, TRUE)
deconstruct()
//SKYRAT EDIT END
if (has_armrest)
update_appearance()
/obj/structure/chair/post_unbuckle_mob()
. = ..()
handle_layer()
if (has_armrest)
update_appearance()
/obj/structure/chair/setDir(newdir)
..()
handle_rotation(newdir)
// Chair types
///Material chair
/obj/structure/chair/greyscale
material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
item_chair = /obj/item/chair/greyscale
buildstacktype = null //Custom mats handle this
/obj/structure/chair/wood
icon_state = "wooden_chair"
name = "wooden chair"
desc = "Old is never too old to not be in fashion."
resistance_flags = FLAMMABLE
max_integrity = 40
buildstacktype = /obj/item/stack/sheet/mineral/wood
buildstackamount = 3
item_chair = /obj/item/chair/wood
fishing_modifier = -6
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 3)
/obj/structure/chair/wood/narsie_act()
return
/obj/structure/chair/wood/wings
icon_state = "wooden_chair_wings"
item_chair = /obj/item/chair/wood/wings
/obj/structure/chair/comfy
name = "comfy chair"
desc = "It looks comfy."
icon_state = "comfychair"
color = rgb(255, 255, 255)
resistance_flags = FLAMMABLE
max_integrity = 70
buildstackamount = 2
item_chair = null
fishing_modifier = -7
has_armrest = TRUE
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2)
/obj/structure/chair/comfy/brown
color = rgb(70, 47, 28)
/obj/structure/chair/comfy/beige
color = rgb(240, 238, 198)
/obj/structure/chair/comfy/teal
color = rgb(117, 214, 214)
/obj/structure/chair/comfy/black
color = rgb(61, 60, 56)
/obj/structure/chair/comfy/lime
color = rgb(193, 248, 104)
/obj/structure/chair/comfy/shuttle
name = "shuttle seat"
desc = "A comfortable, secure seat. It has a more sturdy looking buckling system, for smoother flights."
icon_state = "shuttle_chair"
buildstacktype = /obj/item/stack/sheet/mineral/titanium
buckle_sound = SFX_SEATBELT_BUCKLE
unbuckle_sound = SFX_SEATBELT_UNBUCKLE
resistance_flags = FIRE_PROOF
max_integrity = 120
custom_materials = list(/datum/material/titanium = SHEET_MATERIAL_AMOUNT * 2)
/obj/structure/chair/comfy/shuttle/Initialize(mapload)
. = ..()
update_appearance()
/obj/structure/chair/comfy/shuttle/electrify_self(obj/item/assembly/shock_kit/input_shock_kit, mob/user, list/overlays_from_child_procs)
if(!overlays_from_child_procs)
var/mutable_appearance/echair_overlay = mutable_appearance('icons/obj/chairs.dmi', "echair_over", OBJ_LAYER, src, appearance_flags = KEEP_APART)
echair_overlay.pixel_x = -1
overlays_from_child_procs = list(echair_overlay)
. = ..()
/obj/structure/chair/comfy/shuttle/buckle_feedback(mob/living/being_buckled, mob/buckler)
if(being_buckled == buckler)
being_buckled.visible_message(
span_notice("[buckler] sits down on [src], pulling the overhead restraint down to secure [buckler.p_them()]self."),
span_notice("You sit down on [src], pulling the overhead restraint down to secure yourself."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
else
being_buckled.visible_message(
span_notice("[buckler] sits [being_buckled] down on [src], pulling the overhead restraint down to secure [buckler.p_them()]."),
span_notice("[buckler] sits you down on [src], pulling the overhead restraint down to secure you."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
/obj/structure/chair/comfy/shuttle/unbuckle_feedback(mob/living/being_unbuckled, mob/unbuckler)
if(being_unbuckled == unbuckler)
being_unbuckled.visible_message(
span_notice("[unbuckler] flips the overhead restraint up, standing up from [src]."),
span_notice("You flip the overhead restraint up, standing up from [src]."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
else
being_unbuckled.visible_message(
span_notice("[unbuckler] flips the overhead restraint up, standing [being_unbuckled] up from [src]."),
span_notice("[unbuckler] flips the overhead restraint up, standing you up from [src]."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
/obj/structure/chair/comfy/shuttle/update_overlays()
. = ..()
if(has_buckled_mobs())
. += mutable_appearance(icon, "[icon_state]_down_front", ABOVE_MOB_LAYER + 0.01)
. += mutable_appearance(icon, "[icon_state]_down_behind", src.layer + 0.01)
else
. += mutable_appearance(icon, "[icon_state]_up", src.layer + 0.01)
/obj/structure/chair/comfy/shuttle/tactical
name = "tactical chair"
/obj/structure/chair/comfy/carp
name = "carpskin chair"
desc = "A luxurious chair, the many purple scales reflect the light in a most pleasing manner."
icon_state = "carp_chair"
buildstacktype = /obj/item/stack/sheet/animalhide/carp
fishing_modifier = -12
custom_materials = null
/obj/structure/chair/office
name = "office chair"
anchored = FALSE
buildstackamount = 5
item_chair = null
fishing_modifier = -6
icon_state = "officechair_dark"
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 5)
/obj/structure/chair/office/Initialize(mapload)
. = ..()
AddElement(/datum/element/noisy_movement)
/obj/structure/chair/office/electrify_self(obj/item/assembly/shock_kit/input_shock_kit, mob/user, list/overlays_from_child_procs)
if(!overlays_from_child_procs)
var/mutable_appearance/echair_overlay = mutable_appearance('icons/obj/chairs.dmi', "echair_over", OBJ_LAYER, src, appearance_flags = KEEP_APART)
echair_overlay.pixel_x = -1
overlays_from_child_procs = list(echair_overlay)
. = ..()
/obj/structure/chair/office/tactical
name = "tactical swivel chair"
fishing_modifier = -10
/obj/structure/chair/office/light
name = "office chair"
icon_state = "officechair_white"
//Stool
/obj/structure/chair/stool
name = "stool"
desc = "Apply butt."
icon_state = "stool"
buildstackamount = 1
item_chair = /obj/item/chair/stool
max_integrity = 300
/obj/structure/chair/stool/post_buckle_mob(mob/living/Mob)
Mob.add_offsets(type, z_add = 4)
. = ..()
/obj/structure/chair/stool/post_unbuckle_mob(mob/living/Mob)
Mob.remove_offsets(type)
MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool, 0)
/obj/structure/chair/stool/narsie_act()
return
/obj/structure/chair/mouse_drop_dragged(atom/over_object, mob/user, src_location, over_location, params)
if(!isliving(user) || over_object != user)
return
if(!item_chair || has_buckled_mobs())
return
if(flags_1 & HOLOGRAM_1)
to_chat(user, span_notice("You try to pick up \the [src], but it fades away!"))
qdel(src)
return
user.visible_message(span_notice("[user] grabs \the [src.name]."), span_notice("You grab \the [src.name]."))
var/obj/item/chair_item = new item_chair(loc)
chair_item.set_custom_materials(custom_materials)
TransferComponents(chair_item)
chair_item.update_integrity(get_integrity())
user.put_in_hands(chair_item)
qdel(src)
/obj/structure/chair/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE)
return ..()
/obj/structure/chair/stool/bar
name = "bar stool"
desc = "It has some unsavory stains on it..."
icon_state = "bar"
item_chair = /obj/item/chair/stool/bar
/obj/structure/chair/stool/bar/post_buckle_mob(mob/living/Mob)
. = ..()
Mob.add_offsets(type, z_add = 7)
MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0)
/obj/structure/chair/stool/bamboo
name = "bamboo stool"
desc = "A makeshift bamboo stool with a rustic look."
icon_state = "bamboo_stool"
resistance_flags = FLAMMABLE
max_integrity = 40
buildstacktype = /obj/item/stack/sheet/mineral/bamboo
buildstackamount = 2
item_chair = /obj/item/chair/stool/bamboo
custom_materials = list(/datum/material/bamboo = SHEET_MATERIAL_AMOUNT * 2)
/obj/item/chair
name = "chair"
desc = "Bar brawl essential."
icon = 'icons/obj/chairs.dmi'
icon_state = "chair_toppled"
inhand_icon_state = "chair"
icon_angle = 180
lefthand_file = 'icons/mob/inhands/items/chairs_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items/chairs_righthand.dmi'
w_class = WEIGHT_CLASS_HUGE
force = 8
throwforce = 10
demolition_mod = 1.25
throw_range = 3
max_integrity = 100
hitsound = 'sound/items/trayhit/trayhit1.ogg'
hit_reaction_chance = 50
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT)
item_flags = SKIP_FANTASY_ON_SPAWN
// Duration of daze inflicted when the chair is smashed against someone from behind.
var/daze_amount = 3 SECONDS
// What structure type does this chair become when placed?
var/obj/structure/chair/origin_type = /obj/structure/chair
/obj/item/chair/Initialize(mapload)
. = ..()
AddElement(/datum/element/cuffable_item)
/obj/item/chair/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] begins hitting [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
playsound(src,hitsound,50,TRUE)
return BRUTELOSS
/obj/item/chair/narsie_act()
var/obj/item/chair/wood/W = new/obj/item/chair/wood(get_turf(src))
W.setDir(dir)
qdel(src)
/obj/item/chair/attack_self(mob/user)
plant(user)
/obj/item/chair/proc/plant(mob/user)
var/turf/turf = user.loc
if(!istype(turf) || isgroundlessturf(turf))
to_chat(user, span_warning("You need ground to plant this on!"))
return
if(!user.dropItemToGround(src))
to_chat(user, span_warning("[src] is stuck to your hand!"))
return
if(flags_1 & HOLOGRAM_1)
to_chat(user, span_notice("You try to place down \the [src], but it fades away!"))
qdel(src)
return
for(var/obj/object in turf)
if(istype(object, /obj/structure/chair))
to_chat(user, span_warning("There is already a chair here!"))
return
if(object.density && !(object.flags_1 & ON_BORDER_1))
to_chat(user, span_warning("There is already something here!"))
return
user.visible_message(span_notice("[user] rights \the [src.name]."), span_notice("You right \the [name]."))
var/obj/structure/chair/chair = new origin_type(turf)
chair.set_custom_materials(custom_materials)
TransferComponents(chair)
chair.setDir(user.dir)
chair.update_integrity(get_integrity())
qdel(src)
/obj/item/chair/proc/smash(mob/living/user)
var/stack_type = initial(origin_type.buildstacktype)
if(!stack_type)
return
var/remaining_mats = initial(origin_type.buildstackamount)
remaining_mats-- //Part of the chair was rendered completely unusable. It magically disappears. Maybe make some dirt?
if(remaining_mats)
for(var/M=1 to remaining_mats)
new stack_type(get_turf(loc))
else if(custom_materials[SSmaterials.get_material(/datum/material/iron)])
new /obj/item/stack/rods(get_turf(loc), 2)
qdel(src)
/obj/item/chair/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
if(attack_type == UNARMED_ATTACK && prob(hit_reaction_chance) || attack_type == LEAP_ATTACK && prob(hit_reaction_chance))
owner.visible_message(span_danger("[owner] fends off [attack_text] with [src]!"))
if(take_chair_damage(damage, damage_type, MELEE)) // Our chair takes our incoming damage for us, which can result in it smashing.
smash(owner)
return TRUE
return FALSE
/obj/item/chair/afterattack(atom/target, mob/user, list/modifiers, list/attack_modifiers)
if(!ishuman(target))
return
var/mob/living/carbon/human/give_this_fucker_the_chair = target
// Here we determine if our attack is against a vulnerable target
var/vulnerable_hit = check_behind(user, give_this_fucker_the_chair)
// If our attack is against a vulnerable target, we do additional damage to the chair
var/damage_to_inflict = vulnerable_hit ? (force * 5) : (force * 2.5)
if(!take_chair_damage(damage_to_inflict, damtype, MELEE)) // If we would do enough damage to bring our chair's integrity to 0, we instead go past the check to smash it against our target
return
user.visible_message(span_danger("[user] smashes [src] to pieces against [give_this_fucker_the_chair]"))
if(!HAS_TRAIT(give_this_fucker_the_chair, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED))
if(vulnerable_hit || give_this_fucker_the_chair.get_timed_status_effect_duration(/datum/status_effect/staggered))
give_this_fucker_the_chair.Knockdown(2 SECONDS, daze_amount = daze_amount)
if(give_this_fucker_the_chair.health < give_this_fucker_the_chair.maxHealth*0.5)
give_this_fucker_the_chair.adjust_confusion(10 SECONDS)
smash(user)
/obj/item/chair/proc/take_chair_damage(damage_to_inflict, damage_type, armor_flag)
if(damage_to_inflict >= atom_integrity)
return TRUE
take_damage(damage_to_inflict, damage_type, armor_flag)
return FALSE
/obj/item/chair/greyscale
material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
origin_type = /obj/structure/chair/greyscale
/obj/item/chair/stool
name = "stool"
icon_state = "stool_toppled"
inhand_icon_state = "stool"
origin_type = /obj/structure/chair/stool
max_integrity = 300 //It's too sturdy.
/obj/item/chair/stool/bar
name = "bar stool"
icon_state = "bar_toppled"
inhand_icon_state = "stool_bar"
origin_type = /obj/structure/chair/stool/bar
/obj/item/chair/stool/bamboo
name = "bamboo stool"
icon_state = "bamboo_stool"
inhand_icon_state = "stool_bamboo"
hitsound = 'sound/items/weapons/genhit1.ogg'
origin_type = /obj/structure/chair/stool/bamboo
max_integrity = 40 //Submissive and breakable unlike the chad iron stool
daze_amount = 0 //Not hard enough to cause them to become dazed
custom_materials = list(/datum/material/bamboo = SHEET_MATERIAL_AMOUNT * 2)
/obj/item/chair/stool/narsie_act()
return //sturdy enough to ignore a god
/obj/item/chair/wood
name = "wooden chair"
icon_state = "wooden_chair_toppled"
inhand_icon_state = "woodenchair"
resistance_flags = FLAMMABLE
max_integrity = 40
hitsound = 'sound/items/weapons/genhit1.ogg'
origin_type = /obj/structure/chair/wood
custom_materials = null
daze_amount = 0
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 3)
/obj/item/chair/wood/narsie_act()
return
/obj/item/chair/wood/wings
icon_state = "wooden_chair_wings_toppled"
origin_type = /obj/structure/chair/wood/wings
/obj/structure/chair/old
name = "strange chair"
desc = "You sit in this. Either by will or force. Looks REALLY uncomfortable."
icon_state = "chairold"
item_chair = null
fishing_modifier = 4
/obj/structure/chair/bronze
name = "brass chair"
desc = "A spinny chair made of bronze. It has little cogs for wheels!"
anchored = FALSE
icon_state = "brass_chair"
buildstacktype = /obj/item/stack/sheet/bronze
buildstackamount = 1
item_chair = null
fishing_modifier = -13 //the pinnacle of Ratvarian technology.
has_armrest = TRUE
custom_materials = list(/datum/material/bronze = SHEET_MATERIAL_AMOUNT)
/// Total rotations made
var/turns = 0
/obj/structure/chair/bronze/Initialize(mapload)
. = ..()
AddElement(/datum/element/noisy_movement, 'sound/machines/clockcult/integration_cog_install.ogg', 50)
/obj/structure/chair/bronze/Destroy()
STOP_PROCESSING(SSfastprocess, src)
. = ..()
/obj/structure/chair/bronze/process()
setDir(turn(dir,-90))
playsound(src, 'sound/effects/servostep.ogg', 50, FALSE)
turns++
if(turns >= 8)
STOP_PROCESSING(SSfastprocess, src)
/obj/structure/chair/bronze/MakeRotate()
return
/obj/structure/chair/bronze/click_alt(mob/user)
turns = 0
if(!(datum_flags & DF_ISPROCESSING))
user.visible_message(span_notice("[user] spins [src] around, and the last vestiges of Ratvarian technology keeps it spinning FOREVER."), \
span_notice("Automated spinny chairs. The pinnacle of ancient Ratvarian technology."))
START_PROCESSING(SSfastprocess, src)
else
user.visible_message(span_notice("[user] stops [src]'s uncontrollable spinning."), \
span_notice("You grab [src] and stop its wild spinning."))
STOP_PROCESSING(SSfastprocess, src)
return CLICK_ACTION_SUCCESS
/obj/structure/chair/mime
name = "invisible chair"
desc = "The mime needs to sit down and shut up."
anchored = FALSE
icon_state = null
buildstacktype = null
item_chair = null
obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION
alpha = 0
fishing_modifier = -21 //it only lives for 25 seconds, so we make them worth it.
custom_materials = null
/obj/structure/chair/mime/Initialize(mapload)
. = ..()
AddElement(/datum/element/tool_blocker, TOOL_WRENCH, TOOL_ACT_SECONDARY)
/obj/structure/chair/mime/post_buckle_mob(mob/living/M)
M.add_offsets(type, z_add = 5)
/obj/structure/chair/mime/post_unbuckle_mob(mob/living/M)
M.remove_offsets(type)
/obj/structure/chair/plastic
icon_state = "plastic_chair"
name = "folding plastic chair"
desc = "No matter how much you squirm, it'll still be uncomfortable."
resistance_flags = FLAMMABLE
max_integrity = 70
custom_materials = list(/datum/material/plastic = SHEET_MATERIAL_AMOUNT * 2)
buildstacktype = /obj/item/stack/sheet/plastic
buildstackamount = 2
item_chair = /obj/item/chair/plastic
fishing_modifier = -10
/obj/structure/chair/plastic/post_buckle_mob(mob/living/Mob)
Mob.add_offsets(type, z_add = 2)
. = ..()
if(iscarbon(Mob))
INVOKE_ASYNC(src, PROC_REF(snap_check), Mob)
/obj/structure/chair/plastic/post_unbuckle_mob(mob/living/Mob)
Mob.remove_offsets(type)
/obj/structure/chair/plastic/proc/snap_check(mob/living/carbon/Mob)
if (Mob.nutrition >= NUTRITION_LEVEL_FAT)
to_chat(Mob, span_warning("The chair begins to pop and crack, you're too heavy!"))
if(do_after(Mob, 6 SECONDS, progress = FALSE))
Mob.visible_message(span_notice("The plastic chair snaps under [Mob]'s weight!"))
new /obj/effect/decal/cleanable/plastic(loc)
qdel(src)
/obj/item/chair/plastic
name = "folding plastic chair"
desc = "Somehow, you can always find one under the wrestling ring."
icon = 'icons/obj/chairs.dmi'
icon_state = "folded_chair"
inhand_icon_state = "folded_chair"
lefthand_file = 'icons/mob/inhands/items/chairs_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items/chairs_righthand.dmi'
w_class = WEIGHT_CLASS_NORMAL
force = 7
throw_range = 5 //Lighter Weight --> Flies Farther.
custom_materials = list(/datum/material/plastic = SHEET_MATERIAL_AMOUNT * 2)
max_integrity = 70
daze_amount = 0
origin_type = /obj/structure/chair/plastic
/obj/structure/chair/musical
name = "musical chair"
desc = "You listen to this. Either by will or by force."
item_chair = /obj/item/chair/musical
particles = new /particles/musical_notes
/obj/item/chair/musical
name = "musical chair"
desc = "Oh, so this is like the fucked up Monopoly rules where there are no rules and you can pick up and place the musical chairs as you please."
particles = new /particles/musical_notes
origin_type = /obj/structure/chair/musical
/obj/structure/handrail
name = "handrail"
desc = "Hold on tight!"
icon = 'icons/obj/handrail.dmi'
icon_state = "handrail"
anchored = TRUE
can_buckle = TRUE
buckle_lying = NO_BUCKLE_LYING
resistance_flags = FIRE_PROOF
max_integrity = 50
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT)
layer = OBJ_LAYER
/obj/structure/handrail/attack_hand(mob/living/user, list/modifiers)
return ..() || mouse_buckle_handling(user, user)
/obj/structure/handrail/is_user_buckle_possible(mob/living/target, mob/user, check_loc = TRUE)
return ..() && user == target && !HAS_TRAIT(target, TRAIT_HANDS_BLOCKED)
/obj/structure/handrail/post_buckle_mob(mob/living/buckled_mob)
RegisterSignal(buckled_mob, SIGNAL_ADDTRAIT(TRAIT_HANDS_BLOCKED), PROC_REF(stop_buckle))
var/z_offset = 0
var/w_offset = 0
if(dir & NORTH)
z_offset = -4
else if(dir & SOUTH)
z_offset = 8
if(dir & EAST)
w_offset = -8
else if(dir & WEST)
w_offset = 8
buckled_mob.add_offsets(type, z_add = z_offset, w_add = w_offset)
/obj/structure/handrail/post_unbuckle_mob(mob/living/unbuckled_mob)
UnregisterSignal(unbuckled_mob, SIGNAL_ADDTRAIT(TRAIT_HANDS_BLOCKED))
unbuckled_mob.remove_offsets(type)
/obj/structure/handrail/proc/stop_buckle(mob/living/source, ...)
SIGNAL_HANDLER
source.visible_message(
span_warning("[source] loses [source.p_their()] grip on [src]!"),
span_warning("You lose your grip on [src]!"),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
vision_distance = COMBAT_MESSAGE_RANGE,
)
unbuckle_mob(source, TRUE, TRUE)
/obj/structure/handrail/buckle_feedback(mob/living/being_buckled, mob/buckler)
buckler.visible_message(
span_notice("[buckler] grabs [src] tight, keeping [buckler.p_them()]self upright."),
span_notice("You grab [src] tight, keeping yourself upright."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
vision_distance = COMBAT_MESSAGE_RANGE,
)
/obj/structure/handrail/unbuckle_feedback(mob/living/being_unbuckled, mob/unbuckler)
if(being_unbuckled == unbuckler)
being_unbuckled.visible_message(
span_notice("[unbuckler] lets go of [src]."),
span_notice("You let go of [src]."),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
vision_distance = COMBAT_MESSAGE_RANGE,
)
else
being_unbuckled.visible_message(
span_warning("[unbuckler] forces [being_unbuckled] to let go of [src]!"),
span_warning("[unbuckler] forces you to let go of [src]!"),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
vision_distance = COMBAT_MESSAGE_RANGE,
)