mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 23:27:34 +01:00
## 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>
771 lines
27 KiB
Plaintext
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,
|
|
)
|