mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-22 15:05:11 +00:00
## About The Pull Request Converts slapcrafting into a component! The component is added on to an ingredient (presumably the main ingredient) with a list of recipes attached. If you interact an ingredient (if no ignredients, a tool) with it, you will start crafting the recipe. If there's multiple, pick between them with a radial menu. Opening on draft as there's just a liiiiil bit left to do. The actual wired rod was left for last. ## Why It's Good For The Game Slapcrafting is simply better and more accessible and less laggy than menu crafting. By making it a component we can attach it to things in which it'd make sense to while stopping unintended weirdness that might arise from this being global. Additionally the way examine lets you see crafting recipes opens up visibility for those, which allows new players to learn about them in a intuitive manner. ## Changelog 🆑 refactor: Turned slapcrafting into a component! You can examine compatible items to see what recipes they can be used in, and what the ingredients for them are. For example, spears and the head-on-spear crafting recipe. /🆑
343 lines
12 KiB
Plaintext
343 lines
12 KiB
Plaintext
#define BATON_BASH_COOLDOWN (3 SECONDS)
|
|
|
|
/obj/item/shield
|
|
name = "shield"
|
|
icon = 'icons/obj/weapons/shields.dmi'
|
|
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
|
block_chance = 50
|
|
slot_flags = ITEM_SLOT_BACK
|
|
force = 10
|
|
throwforce = 5
|
|
throw_speed = 2
|
|
throw_range = 3
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
attack_verb_continuous = list("shoves", "bashes")
|
|
attack_verb_simple = list("shove", "bash")
|
|
armor_type = /datum/armor/item_shield
|
|
block_sound = 'sound/weapons/block_shield.ogg'
|
|
/// makes beam projectiles pass through the shield
|
|
var/transparent = FALSE
|
|
/// if the shield will break by sustaining damage
|
|
var/breakable_by_damage = TRUE
|
|
/// what the shield leaves behind when it breaks
|
|
var/shield_break_leftover = /obj/item/stack/sheet/mineral/wood
|
|
/// sound the shield makes when it breaks
|
|
var/shield_break_sound = 'sound/effects/bang.ogg'
|
|
/// baton bash cooldown
|
|
COOLDOWN_DECLARE(baton_bash)
|
|
|
|
/datum/armor/item_shield
|
|
melee = 50
|
|
bullet = 50
|
|
laser = 50
|
|
bomb = 30
|
|
fire = 80
|
|
acid = 70
|
|
|
|
/obj/item/shield/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(transparent && (hitby.pass_flags & PASSGLASS))
|
|
return FALSE
|
|
if(attack_type == THROWN_PROJECTILE_ATTACK)
|
|
final_block_chance += 30
|
|
if(attack_type == LEAP_ATTACK)
|
|
final_block_chance = 100
|
|
. = ..()
|
|
if(.)
|
|
on_shield_block(owner, hitby, attack_text, damage, attack_type, damage_type)
|
|
|
|
/obj/item/shield/examine(mob/user)
|
|
. = ..()
|
|
var/healthpercent = round((atom_integrity/max_integrity) * 100, 1)
|
|
switch(healthpercent)
|
|
if(50 to 99)
|
|
. += span_info("It looks slightly damaged.")
|
|
if(25 to 50)
|
|
. += span_info("It appears heavily damaged.")
|
|
if(0 to 25)
|
|
. += span_warning("It's falling apart!")
|
|
|
|
/obj/item/shield/proc/shatter(mob/living/carbon/human/owner)
|
|
playsound(owner, shield_break_sound, 50)
|
|
new shield_break_leftover(get_turf(src))
|
|
|
|
/obj/item/shield/proc/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
|
|
if(!breakable_by_damage || (damage_type != BRUTE && damage_type != BURN))
|
|
return TRUE
|
|
if (atom_integrity <= damage)
|
|
var/turf/owner_turf = get_turf(owner)
|
|
owner_turf.visible_message(span_warning("[hitby] destroys [src]!"))
|
|
shatter(owner)
|
|
qdel(src)
|
|
return FALSE
|
|
take_damage(damage)
|
|
return TRUE
|
|
|
|
/obj/item/shield/buckler
|
|
name = "wooden buckler"
|
|
desc = "A medieval wooden buckler."
|
|
icon_state = "buckler"
|
|
inhand_icon_state = "buckler"
|
|
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 10)
|
|
resistance_flags = FLAMMABLE
|
|
block_chance = 30
|
|
max_integrity = 55
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
|
|
/obj/item/shield/roman
|
|
name = "\improper Roman shield"
|
|
desc = "Bears an inscription on the inside: <i>\"Romanes venio domus\"</i>."
|
|
icon_state = "roman_shield"
|
|
inhand_icon_state = "roman_shield"
|
|
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 4.25)
|
|
max_integrity = 65
|
|
shield_break_sound = 'sound/effects/grillehit.ogg'
|
|
shield_break_leftover = /obj/item/stack/sheet/iron
|
|
|
|
/obj/item/shield/roman/fake
|
|
desc = "Bears an inscription on the inside: <i>\"Romanes venio domus\"</i>. It appears to be a bit flimsy."
|
|
block_chance = 0
|
|
armor_type = /datum/armor/none
|
|
max_integrity = 30
|
|
|
|
/obj/item/shield/riot
|
|
name = "riot shield"
|
|
desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder."
|
|
icon_state = "riot"
|
|
inhand_icon_state = "riot"
|
|
custom_materials = list(/datum/material/glass= SHEET_MATERIAL_AMOUNT * 3.75, /datum/material/iron= HALF_SHEET_MATERIAL_AMOUNT)
|
|
transparent = TRUE
|
|
max_integrity = 75
|
|
shield_break_sound = 'sound/effects/glassbr3.ogg'
|
|
shield_break_leftover = /obj/item/shard
|
|
|
|
/obj/item/shield/riot/Initialize(mapload)
|
|
. = ..()
|
|
var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/strobeshield)
|
|
|
|
AddComponent(
|
|
/datum/component/slapcrafting,\
|
|
slapcraft_recipes = slapcraft_recipe_list,\
|
|
)
|
|
|
|
/obj/item/shield/riot/attackby(obj/item/attackby_item, mob/user, params)
|
|
if(istype(attackby_item, /obj/item/melee/baton))
|
|
if(!COOLDOWN_FINISHED(src, baton_bash))
|
|
return
|
|
user.visible_message(span_warning("[user] bashes [src] with [attackby_item]!"))
|
|
playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, TRUE)
|
|
COOLDOWN_START(src, baton_bash, BATON_BASH_COOLDOWN)
|
|
return
|
|
if(istype(attackby_item, /obj/item/stack/sheet/mineral/titanium))
|
|
if (atom_integrity >= max_integrity)
|
|
to_chat(user, span_warning("[src] is already in perfect condition."))
|
|
return
|
|
var/obj/item/stack/sheet/mineral/titanium/titanium_sheet = attackby_item
|
|
titanium_sheet.use(1)
|
|
atom_integrity = max_integrity
|
|
to_chat(user, span_notice("You repair [src] with [titanium_sheet]."))
|
|
return
|
|
return ..()
|
|
|
|
/obj/item/shield/riot/flash
|
|
name = "strobe shield"
|
|
desc = "A shield with a built in, high intensity light capable of blinding and disorienting suspects. Takes regular handheld flashes as bulbs."
|
|
icon_state = "flashshield"
|
|
inhand_icon_state = "flashshield"
|
|
var/obj/item/assembly/flash/handheld/embedded_flash = /obj/item/assembly/flash/handheld
|
|
|
|
/obj/item/shield/riot/flash/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/update_icon_updates_onmob)
|
|
if(embedded_flash)
|
|
embedded_flash = new(src)
|
|
embedded_flash.set_light_flags(embedded_flash.light_flags | LIGHT_ATTACHED)
|
|
update_appearance(UPDATE_ICON)
|
|
|
|
/obj/item/shield/riot/flash/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
|
if(istype(arrived, /obj/item/assembly/flash/handheld))
|
|
embedded_flash = arrived
|
|
embedded_flash.set_light_flags(embedded_flash.light_flags | LIGHT_ATTACHED)
|
|
update_appearance(UPDATE_ICON)
|
|
return ..()
|
|
|
|
/obj/item/shield/riot/flash/Exited(atom/movable/gone, direction)
|
|
if(gone == embedded_flash)
|
|
embedded_flash.set_light_flags(embedded_flash.light_flags & ~LIGHT_ATTACHED)
|
|
embedded_flash = null
|
|
update_appearance(UPDATE_ICON)
|
|
return ..()
|
|
|
|
/obj/item/shield/riot/flash/vv_edit_var(vname, vval)
|
|
. = ..()
|
|
if(vname == NAMEOF(src, embedded_flash))
|
|
update_appearance(UPDATE_ICON)
|
|
|
|
/obj/item/shield/riot/flash/Destroy(force)
|
|
QDEL_NULL(embedded_flash)
|
|
return ..()
|
|
|
|
/obj/item/shield/riot/flash/attack(mob/living/target_mob, mob/user)
|
|
flash_away(user, target_mob)
|
|
|
|
/obj/item/shield/riot/flash/attack_self(mob/living/carbon/user)
|
|
flash_away(user)
|
|
|
|
/obj/item/shield/riot/flash/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
|
. = ..()
|
|
if(.)
|
|
flash_away(owner)
|
|
|
|
///Handles calls for the actual flash object + plays the flashing animations.
|
|
/obj/item/shield/riot/flash/proc/flash_away(mob/owner, mob/target, animation_only)
|
|
if(QDELETED(embedded_flash) || (embedded_flash.burnt_out && !animation_only))
|
|
return
|
|
var/flick = animation_only ? TRUE : (target ? embedded_flash.attack(target, owner) : embedded_flash.AOE_flash(user = owner))
|
|
if(!flick && !embedded_flash.burnt_out)
|
|
return
|
|
flick("flashshield_flash", src)
|
|
inhand_icon_state = "flashshield_flash"
|
|
owner?.update_held_items()
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_appearance)), 0.5 SECONDS, (TIMER_UNIQUE|TIMER_OVERRIDE)) //.5 second delay so the inhands sprite finishes its anim since inhands don't support flick().
|
|
|
|
/obj/item/shield/riot/flash/attackby(obj/item/attackby_item, mob/user)
|
|
if(istype(attackby_item, /obj/item/assembly/flash/handheld))
|
|
var/obj/item/assembly/flash/handheld/flash = attackby_item
|
|
if(flash.burnt_out)
|
|
to_chat(user, span_warning("No sense replacing it with a broken bulb!"))
|
|
return
|
|
else
|
|
to_chat(user, span_notice("You begin to replace the bulb..."))
|
|
if(do_after(user, 20, target = user))
|
|
if(QDELETED(flash) || flash.burnt_out)
|
|
return
|
|
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
|
qdel(embedded_flash)
|
|
flash.forceMove(src)
|
|
return
|
|
return ..()
|
|
|
|
/obj/item/shield/riot/flash/emp_act(severity)
|
|
. = ..()
|
|
if(QDELETED(embedded_flash) || embedded_flash.burnt_out)
|
|
return
|
|
embedded_flash.emp_act(severity)
|
|
if(embedded_flash.burnt_out) // a little hacky but no good way to check otherwise.
|
|
flash_away((ismob(loc) ? loc : null), animation_only = TRUE)
|
|
|
|
/obj/item/shield/riot/flash/update_icon_state()
|
|
if(QDELETED(embedded_flash) || embedded_flash.burnt_out)
|
|
icon_state = "riot"
|
|
inhand_icon_state = "riot"
|
|
else
|
|
icon_state = "flashshield"
|
|
inhand_icon_state = "flashshield"
|
|
return ..()
|
|
|
|
/obj/item/shield/riot/flash/examine(mob/user)
|
|
. = ..()
|
|
if (embedded_flash?.burnt_out)
|
|
. += span_info("The mounted bulb has burnt out. You can try replacing it with a new <b>flash</b>.")
|
|
|
|
/obj/item/shield/energy
|
|
name = "energy combat shield"
|
|
desc = "A shield that reflects almost all energy projectiles, but is useless against physical attacks. It can be retracted, expanded, and stored anywhere."
|
|
icon_state = "eshield"
|
|
inhand_icon_state = "eshield"
|
|
w_class = WEIGHT_CLASS_TINY
|
|
attack_verb_continuous = list("shoves", "bashes")
|
|
attack_verb_simple = list("shove", "bash")
|
|
throw_range = 5
|
|
force = 3
|
|
throwforce = 3
|
|
throw_speed = 3
|
|
breakable_by_damage = FALSE
|
|
block_sound = 'sound/weapons/block_blade.ogg'
|
|
/// Force of the shield when active.
|
|
var/active_force = 10
|
|
/// Throwforce of the shield when active.
|
|
var/active_throwforce = 8
|
|
/// Throwspeed of ethe shield when active.
|
|
var/active_throw_speed = 2
|
|
/// Whether clumsy people can transform this without side effects.
|
|
var/can_clumsy_use = FALSE
|
|
|
|
/obj/item/shield/energy/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent( \
|
|
/datum/component/transforming, \
|
|
force_on = active_force, \
|
|
throwforce_on = active_throwforce, \
|
|
throw_speed_on = active_throw_speed, \
|
|
hitsound_on = hitsound, \
|
|
clumsy_check = !can_clumsy_use, \
|
|
)
|
|
RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
|
|
|
|
/obj/item/shield/energy/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)
|
|
return FALSE
|
|
|
|
/obj/item/shield/energy/IsReflect()
|
|
return HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE)
|
|
|
|
/*
|
|
* Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
|
|
*/
|
|
/obj/item/shield/energy/proc/on_transform(obj/item/source, mob/user, active)
|
|
SIGNAL_HANDLER
|
|
|
|
if(user)
|
|
balloon_alert(user, active ? "activated" : "deactivated")
|
|
playsound(src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, TRUE)
|
|
return COMPONENT_NO_DEFAULT_MESSAGE
|
|
|
|
/obj/item/shield/riot/tele
|
|
name = "telescopic shield"
|
|
desc = "An advanced riot shield made of lightweight materials that collapses for easy storage."
|
|
icon_state = "teleriot"
|
|
inhand_icon_state = "teleriot"
|
|
worn_icon_state = "teleriot"
|
|
custom_materials = list(/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT * 3.6, /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 3.6, /datum/material/silver = SMALL_MATERIAL_AMOUNT * 2.7, /datum/material/titanium = SMALL_MATERIAL_AMOUNT * 1.8)
|
|
slot_flags = null
|
|
force = 3
|
|
throwforce = 3
|
|
throw_speed = 3
|
|
throw_range = 4
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
|
|
/obj/item/shield/riot/tele/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent( \
|
|
/datum/component/transforming, \
|
|
force_on = 8, \
|
|
throwforce_on = 5, \
|
|
throw_speed_on = 2, \
|
|
hitsound_on = hitsound, \
|
|
w_class_on = WEIGHT_CLASS_BULKY, \
|
|
attack_verb_continuous_on = list("smacks", "strikes", "cracks", "beats"), \
|
|
attack_verb_simple_on = list("smack", "strike", "crack", "beat"), \
|
|
)
|
|
|
|
RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
|
|
|
|
/obj/item/shield/riot/tele/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(HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE))
|
|
return ..()
|
|
return FALSE
|
|
|
|
/**
|
|
* Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
|
|
*
|
|
* Allows it to be placed on back slot when active.
|
|
*/
|
|
/obj/item/shield/riot/tele/proc/on_transform(obj/item/source, mob/user, active)
|
|
SIGNAL_HANDLER
|
|
|
|
slot_flags = active ? ITEM_SLOT_BACK : null
|
|
if(user)
|
|
balloon_alert(user, active ? "extended" : "collapsed")
|
|
playsound(src, 'sound/weapons/batonextend.ogg', 50, TRUE)
|
|
return COMPONENT_NO_DEFAULT_MESSAGE
|
|
|
|
#undef BATON_BASH_COOLDOWN
|