mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-12 00:27:31 +01:00
684 lines
26 KiB
Plaintext
684 lines
26 KiB
Plaintext
#define SPEAR_CUSTOM_TIP_PREFIX "spearblank"
|
|
|
|
/obj/item/spear
|
|
name = "spear"
|
|
desc = "A haphazardly-constructed yet still deadly weapon of ancient design."
|
|
icon = 'icons/obj/weapons/spear.dmi'
|
|
icon_state = "spearglass0"
|
|
lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi'
|
|
icon_angle = -45
|
|
force = 10
|
|
reach = 2
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
slot_flags = ITEM_SLOT_BACK
|
|
throwforce = 20
|
|
throw_speed = 4
|
|
demolition_mod = 0.75 // Note: This is significant, as this needs to be low enough that any possible force adjustments from better spears does not go over airlock deflection. See AIRLOCK_DAMAGE_DEFLECTION_N.
|
|
embed_type = /datum/embedding/spear
|
|
armour_penetration = 5
|
|
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 0.65, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.15)
|
|
material_slots = list(/datum/material_slot/weapon_head/speartip = /datum/material/glass, /datum/material_slot/handle/spear = /datum/material/iron)
|
|
hitsound = 'sound/items/weapons/bladeslice.ogg'
|
|
attack_verb_continuous = list("attacks", "pokes", "jabs", "tears", "lacerates", "gores")
|
|
attack_verb_simple = list("attack", "poke", "jab", "tear", "lacerate", "gore")
|
|
sharpness = SHARP_POINTY
|
|
max_integrity = 200
|
|
armor_type = /datum/armor/item_spear
|
|
wound_bonus = -15
|
|
exposed_wound_bonus = 15
|
|
material_flags = MATERIAL_EFFECTS | MATERIAL_AFFECT_STATISTICS
|
|
/// The icon prefix for this flavor of spear
|
|
var/icon_prefix = "spearglass"
|
|
/// How much damage to do unwielded
|
|
var/force_unwielded = 10
|
|
/// How much damage to do wielded
|
|
var/force_wielded = 18
|
|
/// Whether or not hitting with this spear causes damage to the spear itself
|
|
var/improvised_construction = TRUE
|
|
/// What is left over when a spear breaks
|
|
var/spear_leftovers = /obj/item/stack/rods
|
|
/// What pike do we construct if someone kills themselves with us?
|
|
var/pike_type = /obj/structure/headpike
|
|
|
|
/datum/embedding/spear
|
|
impact_pain_mult = 2
|
|
remove_pain_mult = 4
|
|
jostle_chance = 2.5
|
|
|
|
/datum/armor/item_spear
|
|
fire = 50
|
|
acid = 30
|
|
|
|
/obj/item/spear/Initialize(mapload)
|
|
. = ..()
|
|
force = force_unwielded
|
|
//decent in a pinch, but pretty bad.
|
|
AddComponent(/datum/component/jousting, \
|
|
max_tile_charge = 9, \
|
|
min_tile_charge = 6, \
|
|
)
|
|
|
|
AddComponent(/datum/component/butchering, speed = 10 SECONDS, effectiveness = 30)
|
|
AddComponent(/datum/component/two_handed, \
|
|
force_unwielded = force_unwielded, \
|
|
force_wielded = force_wielded, \
|
|
icon_wielded = "[icon_prefix]1", \
|
|
wield_callback = CALLBACK(src, PROC_REF(on_wield)), \
|
|
unwield_callback = CALLBACK(src, PROC_REF(on_unwield)), \
|
|
)
|
|
add_headpike_component()
|
|
update_appearance()
|
|
|
|
// I dunno man
|
|
/obj/item/spear/proc/add_headpike_component()
|
|
var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/headpike)
|
|
|
|
AddElement(
|
|
/datum/element/slapcrafting,\
|
|
slapcraft_recipes = slapcraft_recipe_list,\
|
|
)
|
|
|
|
/obj/item/spear/update_icon_state()
|
|
icon_state = "[icon_prefix]0"
|
|
if (icon_prefix == SPEAR_CUSTOM_TIP_PREFIX)
|
|
worn_icon_state = "spearglass0"
|
|
else
|
|
worn_icon_state = null
|
|
return ..()
|
|
|
|
/obj/item/spear/suicide_act(mob/living/carbon/user)
|
|
user.visible_message(span_suicide("[user] begins to sword-swallow \the [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
|
|
if (!do_after(user, 4 SECONDS, target = src))
|
|
return SHAME
|
|
var/obj/item/bodypart/head/head = user.get_bodypart(BODY_ZONE_HEAD)
|
|
if (!head)
|
|
return BRUTELOSS // No head?
|
|
var/obj/structure/headpike/pike = new pike_type(drop_location())
|
|
if (!head.dismember(silent = FALSE, wounding_type = WOUND_PIERCE))
|
|
return BRUTELOSS // Guess your neck is too strong
|
|
head.forceMove(pike)
|
|
pike.victim = head
|
|
forceMove(pike)
|
|
pike.spear = src
|
|
pike.update_appearance(UPDATE_NAME | UPDATE_OVERLAYS)
|
|
return BRUTELOSS // Just in case they survived losing the head
|
|
|
|
/obj/item/spear/on_craft_completion(list/components, datum/crafting_recipe/current_recipe, atom/crafter)
|
|
var/obj/item/stack/rods/rod = locate() in components
|
|
if (rod)
|
|
spear_leftovers = rod.type
|
|
set_material_slot(/datum/material_slot/handle/spear, rod.get_master_material())
|
|
|
|
var/obj/item/shard/tip = locate() in components
|
|
if (!tip)
|
|
return ..()
|
|
|
|
var/datum/material/tip_material = tip.get_master_material()
|
|
set_material_slot(/datum/material_slot/weapon_head/speartip, tip_material)
|
|
return ..()
|
|
|
|
/obj/item/spear/set_material_slot(slot_type, new_material)
|
|
. = ..()
|
|
if (slot_type != /datum/material_slot/weapon_head/speartip)
|
|
return
|
|
|
|
if (istype(new_material, /datum/material))
|
|
var/datum/material/as_material = new_material
|
|
new_material = as_material.type
|
|
|
|
switch (new_material)
|
|
if (/datum/material/alloy/plasmaglass)
|
|
icon_prefix = "spearplasma"
|
|
if (/datum/material/alloy/titaniumglass)
|
|
icon_prefix = "speartitanium"
|
|
if (/datum/material/alloy/plastitaniumglass)
|
|
icon_prefix = "spearplastitanium"
|
|
else
|
|
icon_prefix = SPEAR_CUSTOM_TIP_PREFIX
|
|
|
|
AddComponent(/datum/component/two_handed, \
|
|
icon_wielded = "[icon_prefix]1", \
|
|
wield_callback = CALLBACK(src, PROC_REF(on_wield)), \
|
|
unwield_callback = CALLBACK(src, PROC_REF(on_unwield)), \
|
|
)
|
|
update_appearance()
|
|
|
|
/obj/item/spear/finalize_material_effects(list/materials)
|
|
. = ..()
|
|
update_appearance()
|
|
|
|
/obj/item/spear/update_overlays()
|
|
. = ..()
|
|
if (icon_prefix != SPEAR_CUSTOM_TIP_PREFIX)
|
|
return
|
|
var/datum/material/tip_material = get_master_material()
|
|
var/mutable_appearance/tip_overlay = mutable_appearance(icon, "speartip", appearance_flags = KEEP_APART | RESET_COLOR)
|
|
tip_overlay.color = tip_material.color
|
|
. += tip_overlay
|
|
|
|
/obj/item/spear/separate_worn_overlays(mutable_appearance/standing, mutable_appearance/draw_target, isinhands, icon_file)
|
|
. = ..()
|
|
if (icon_prefix != SPEAR_CUSTOM_TIP_PREFIX || !isinhands)
|
|
return
|
|
var/datum/material/tip_material = get_master_material()
|
|
var/mutable_appearance/tip_overlay = mutable_appearance(icon_file, "speartip[HAS_TRAIT(src, TRAIT_WIELDED)]", appearance_flags = RESET_COLOR)
|
|
tip_overlay.color = tip_material.color
|
|
. += tip_overlay
|
|
|
|
/obj/item/spear/get_master_material()
|
|
var/datum/material/tip_material = get_material_from_slot(/datum/material_slot/weapon_head/speartip)
|
|
if (!tip_material)
|
|
return ..()
|
|
return custom_materials[tip_material] ? tip_material : ..()
|
|
|
|
/obj/item/spear/afterattack(atom/target, mob/user, list/modifiers, list/attack_modifiers)
|
|
if(improvised_construction && !QDELETED(src))
|
|
take_damage(force / 2, sound_effect = FALSE)
|
|
|
|
/obj/item/spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
|
. = ..()
|
|
if (.) //spear was caught
|
|
return
|
|
if(improvised_construction && !QDELETED(src))
|
|
take_damage(throwforce / 2, sound_effect = FALSE)
|
|
|
|
/obj/item/spear/atom_destruction(damage_flag)
|
|
playsound(src, 'sound/effects/grillehit.ogg', 50)
|
|
new spear_leftovers(get_turf(src))
|
|
if(isliving(loc))
|
|
loc.balloon_alert(loc, "spear broken!")
|
|
return ..()
|
|
|
|
/obj/item/spear/get_material_prefixes(list/materials)
|
|
var/datum/material/material = get_material_from_slot(/datum/material_slot/weapon_head/speartip)
|
|
return material?.name
|
|
|
|
/obj/item/spear/proc/on_wield(obj/item/source, mob/living/carbon/user)
|
|
reach = 1
|
|
armour_penetration *= 2
|
|
|
|
/obj/item/spear/proc/on_unwield(obj/item/source, mob/living/carbon/user)
|
|
reach = 2
|
|
armour_penetration /= 2
|
|
|
|
/datum/material_slot/weapon_head/speartip
|
|
name = "tip"
|
|
material_amount = 1.75
|
|
|
|
/datum/material_slot/weapon_head/speartip/on_applied(obj/item/spear/target, datum/material/material, amount, multiplier)
|
|
. = ..()
|
|
if (!(target.material_flags & MATERIAL_AFFECT_STATISTICS))
|
|
return FALSE
|
|
|
|
var/density = material.get_property(MATERIAL_DENSITY)
|
|
var/hardness = material.get_property(MATERIAL_HARDNESS)
|
|
// If a spear is too hard its unwieldy, if it is too light it doesn't have enough weight behind it
|
|
var/material_effect = (hardness - 4) - max(0, density - 4) - max(0, 4 - density) * 2
|
|
target.wound_bonus += material_effect * 5
|
|
// These try to keep parity with titanium/plastitanium spears as armorpen boost was exclusive to them
|
|
target.armour_penetration += MATERIAL_PROPERTY_DIVERGENCE(hardness, 4, 6) * 5
|
|
target.exposed_wound_bonus += (MATERIAL_PROPERTY_DIVERGENCE(hardness, 4, 6) - (density - 4)) * 5
|
|
return FALSE
|
|
|
|
/datum/material_slot/weapon_head/spearhead/on_removed(obj/item/spear/target, datum/material/material, amount, multiplier)
|
|
. = ..()
|
|
if (!(target.material_flags & MATERIAL_AFFECT_STATISTICS))
|
|
return FALSE
|
|
|
|
var/density = material.get_property(MATERIAL_DENSITY)
|
|
var/hardness = material.get_property(MATERIAL_HARDNESS)
|
|
var/material_effect = (hardness - 4) - max(0, density - 4) - max(0, 4 - density) * 2
|
|
target.wound_bonus -= material_effect * 5
|
|
target.armour_penetration -= MATERIAL_PROPERTY_DIVERGENCE(hardness, 4, 6) * 5
|
|
target.exposed_wound_bonus -= (MATERIAL_PROPERTY_DIVERGENCE(hardness, 4, 6) - (density - 4)) * 5
|
|
return FALSE
|
|
|
|
/datum/material_slot/handle/spear
|
|
|
|
/datum/material_slot/handle/spear/on_applied(obj/item/target, datum/material/material, amount, multiplier)
|
|
. = ..()
|
|
if (!(target.material_flags & MATERIAL_AFFECT_STATISTICS))
|
|
return FALSE
|
|
|
|
var/density = material.get_property(MATERIAL_DENSITY)
|
|
var/hardness = material.get_property(MATERIAL_HARDNESS)
|
|
target.throw_range += (hardness - 4) - (density - 4) * 2
|
|
target.throw_speed += floor((hardness - 4) / 2) - (density - 4) * 2
|
|
return FALSE
|
|
|
|
/datum/material_slot/handle/spear/on_removed(obj/item/target, datum/material/material, amount, multiplier)
|
|
. = ..()
|
|
if (!(target.material_flags & MATERIAL_AFFECT_STATISTICS))
|
|
return FALSE
|
|
|
|
var/density = material.get_property(MATERIAL_DENSITY)
|
|
var/hardness = material.get_property(MATERIAL_HARDNESS)
|
|
target.throw_range -= (hardness - 4) - (density - 4) * 2
|
|
target.throw_speed -= floor((hardness - 4) / 2) - (density - 4) * 2
|
|
return FALSE
|
|
|
|
/obj/item/wireprod
|
|
name = "wireprod"
|
|
desc = "A metal rod with some wire attached to one of the ends, waiting for something sharp."
|
|
icon = 'icons/obj/weapons/spear.dmi'
|
|
icon_state = "wireprod"
|
|
inhand_icon_state = "spearblank0"
|
|
lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi'
|
|
icon_angle = -45
|
|
force = 5
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 0.65, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 1.5)
|
|
attack_verb_continuous = list("attacks", "pokes", "jabs", "tears", "lacerates", "gores")
|
|
attack_verb_simple = list("attack", "poke", "jab", "tear", "lacerate", "gore")
|
|
material_flags = MATERIAL_EFFECTS | MATERIAL_AFFECT_STATISTICS
|
|
|
|
/obj/item/wireprod/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
|
var/datum/material/shard_mat = null
|
|
if (istype(tool, /obj/item/shard))
|
|
shard_mat = tool.get_master_material()
|
|
else if (istype(tool, /obj/item/stack))
|
|
shard_mat = tool.get_master_material()
|
|
if (!(shard_mat.mat_flags & MATERIAL_CLASS_CRYSTAL))
|
|
shard_mat = null
|
|
|
|
if (!shard_mat)
|
|
return NONE
|
|
|
|
var/obj/item/spear/spear = new(drop_location())
|
|
var/datum/material/rod_material = get_master_material()
|
|
spear.material_flags |= MATERIAL_ADD_PREFIX
|
|
spear.set_material_slot(/datum/material_slot/handle/spear, get_master_material())
|
|
spear.set_material_slot(/datum/material_slot/weapon_head/speartip, shard_mat)
|
|
spear.set_custom_materials(list((rod_material) = custom_materials[rod_material], (shard_mat) = tool.custom_materials[shard_mat]))
|
|
to_chat(user, span_notice("You attach [tool] to [src]'s tip."))
|
|
|
|
if (istype(tool, /obj/item/stack))
|
|
var/obj/item/stack/stack = tool
|
|
stack.use(1)
|
|
else
|
|
qdel(tool)
|
|
|
|
var/was_holding = user.get_held_index_of_item(src)
|
|
qdel(src)
|
|
if (was_holding)
|
|
user.put_in_hands(spear)
|
|
|
|
#undef SPEAR_CUSTOM_TIP_PREFIX
|
|
|
|
/obj/item/spear/explosive
|
|
name = "explosive lance"
|
|
icon_state = "spearbomb0"
|
|
base_icon_state = "spearbomb"
|
|
icon_prefix = "spearbomb"
|
|
var/obj/item/grenade/explosive = null
|
|
/// What we cry out when we use this to bap someone
|
|
var/war_cry = "AAAAARGH!!!"
|
|
|
|
/obj/item/spear/explosive/Initialize(mapload)
|
|
. = ..()
|
|
set_explosive(new /obj/item/grenade/iedcasing/spawned()) //For admin-spawned explosive lances
|
|
|
|
/obj/item/spear/explosive/proc/set_explosive(obj/item/grenade/G)
|
|
if(explosive)
|
|
QDEL_NULL(explosive)
|
|
G.forceMove(src)
|
|
explosive = G
|
|
desc = "A makeshift spear with [G] attached to it"
|
|
|
|
/obj/item/spear/explosive/on_craft_completion(list/components, datum/crafting_recipe/current_recipe, atom/crafter)
|
|
var/obj/item/grenade/nade = locate() in components
|
|
if(nade)
|
|
var/obj/item/spear/lancePart = locate() in components
|
|
throwforce = lancePart.throwforce
|
|
icon_prefix = lancePart.icon_prefix
|
|
set_explosive(nade)
|
|
return ..()
|
|
|
|
/obj/item/spear/explosive/suicide_act(mob/living/carbon/user)
|
|
user.visible_message(span_suicide("[user] begins to sword-swallow \the [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
|
|
user.say("[war_cry]", forced="spear warcry")
|
|
explosive.forceMove(user)
|
|
explosive.detonate()
|
|
user.gib(DROP_ALL_REMAINS)
|
|
qdel(src)
|
|
return BRUTELOSS
|
|
|
|
/obj/item/spear/explosive/examine(mob/user)
|
|
. = ..()
|
|
. += span_notice("Alt-click to set your war cry.")
|
|
|
|
/obj/item/spear/explosive/click_alt(mob/user)
|
|
var/input = tgui_input_text(user, "What do you want your war cry to be? You will shout it when you hit someone in melee.", "War Cry", max_length = 50)
|
|
if(input)
|
|
war_cry = input
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
|
|
/obj/item/spear/explosive/afterattack(atom/movable/target, mob/user, list/modifiers, list/attack_modifiers)
|
|
if(!HAS_TRAIT(src, TRAIT_WIELDED) || !istype(target))
|
|
return
|
|
if(target.resistance_flags & INDESTRUCTIBLE) //due to the lich incident of 2021, embedding grenades inside of indestructible structures is forbidden
|
|
return
|
|
if(HAS_TRAIT(target, TRAIT_GODMODE))
|
|
return
|
|
if(iseffect(target)) //and no accidentally wasting your moment of glory on graffiti
|
|
return
|
|
user.say("[war_cry]", forced="spear warcry")
|
|
if(isliving(user))
|
|
var/mob/living/living_user = user
|
|
living_user.set_resting(new_resting = TRUE, silent = TRUE, instant = TRUE)
|
|
living_user.Move(get_turf(target))
|
|
explosive.forceMove(get_turf(living_user))
|
|
explosive.detonate(lanced_by=user)
|
|
if(!QDELETED(living_user))
|
|
living_user.set_resting(new_resting = FALSE, silent = TRUE, instant = TRUE)
|
|
qdel(src)
|
|
|
|
//GREY TIDE
|
|
/obj/item/spear/grey_tide
|
|
name = "\improper Grey Tide"
|
|
desc = "Recovered from the aftermath of a revolt aboard Defense Outpost Theta Aegis, in which a seemingly endless tide of Assistants caused heavy casualties among Nanotrasen military forces."
|
|
attack_verb_continuous = list("gores")
|
|
attack_verb_simple = list("gore")
|
|
force_unwielded = 15
|
|
force_wielded = 25
|
|
improvised_construction = FALSE
|
|
|
|
/obj/item/spear/grey_tide/afterattack(atom/movable/target, mob/living/user, list/modifiers, list/attack_modifiers)
|
|
user.add_ally("greytide([REF(user)])")
|
|
if(!isliving(target))
|
|
return
|
|
var/mob/living/stabbed = target
|
|
if(istype(stabbed, /mob/living/basic/illusion))
|
|
return
|
|
if(stabbed.stat == CONSCIOUS && prob(50))
|
|
var/mob/living/basic/illusion/fake_clone = new(user.loc)
|
|
fake_clone.full_setup(user, target_mob = stabbed, life = 10 SECONDS, hp = user.health / 2.5, damage = 12, replicate = 30)
|
|
|
|
//MILITARY
|
|
/obj/item/spear/military
|
|
icon_state = "military_spear0"
|
|
base_icon_state = "military_spear0"
|
|
icon_prefix = "military_spear"
|
|
name = "military javelin"
|
|
desc = "A stick with a seemingly blunt spearhead on its end. Looks like it might break bones easily."
|
|
attack_verb_continuous = list("attacks", "pokes", "jabs")
|
|
attack_verb_simple = list("attack", "poke", "jab")
|
|
throwforce = 30
|
|
demolition_mod = 1
|
|
wound_bonus = 5
|
|
exposed_wound_bonus = 25
|
|
throw_range = 9
|
|
throw_speed = 5
|
|
sharpness = NONE // we break bones instead of cutting flesh
|
|
improvised_construction = FALSE
|
|
pike_type = /obj/structure/headpike/military
|
|
|
|
/obj/item/spear/military/add_headpike_component()
|
|
var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/headpikemilitary)
|
|
|
|
AddElement(
|
|
/datum/element/slapcrafting,\
|
|
slapcraft_recipes = slapcraft_recipe_list,\
|
|
)
|
|
|
|
/*
|
|
* Anti-big monster spear
|
|
* "WHERES MY DRAGONATOR?!"
|
|
*/
|
|
/obj/item/spear/dragonator
|
|
name = "giantslayer spear"
|
|
desc = "An oversized multi-bladed spear designed to kill large hostile xenoforms such as space dragons or the creatures of Indecipheres. Capable of being launched from a ballista."
|
|
icon = 'icons/obj/weapons/48x.dmi'
|
|
icon_state = "speardragon0"
|
|
icon_prefix = "speardragon"
|
|
base_icon_state = "speardragon"
|
|
lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi'
|
|
demolition_mod = 0.5
|
|
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
|
material_flags = MATERIAL_EFFECTS
|
|
force = 13
|
|
throwforce = 23
|
|
throw_range = 9
|
|
throw_speed = 5
|
|
wound_bonus = 0
|
|
exposed_wound_bonus = 20
|
|
force_unwielded = 13
|
|
force_wielded = 21
|
|
armour_penetration = 15
|
|
improvised_construction = FALSE
|
|
custom_materials = list(
|
|
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 42,
|
|
/datum/material/alloy/plasteel = SHEET_MATERIAL_AMOUNT * 15,
|
|
/datum/material/titanium = SHEET_MATERIAL_AMOUNT * 5,
|
|
)
|
|
material_slots = list(/datum/material_slot/weapon_head/speartip = /datum/material/titanium, /datum/material_slot/handle/spear = /datum/material/alloy/plasteel)
|
|
|
|
/obj/item/spear/dragonator/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/bane, affected_biotypes = MOB_MINING, added_damage = 80) //For killing really big monsters.
|
|
|
|
/*
|
|
* Untreated Giantslayer , needs to be thrown into lava
|
|
*/
|
|
/obj/item/spear/dragonator_untreated
|
|
name = "unfired giantslayer spear"
|
|
desc = "A half-finished giantslayer spear, needs to be thrown in lava to forge the metals to a killing edge."
|
|
icon = 'icons/obj/weapons/48x.dmi'
|
|
icon_state = "speardragonraw0"
|
|
icon_prefix = "speardragonraw"
|
|
base_icon_state = "speardragonraw"
|
|
material_flags = MATERIAL_EFFECTS
|
|
demolition_mod = 0.5
|
|
wound_bonus = 0
|
|
exposed_wound_bonus = 0
|
|
force_unwielded = 5
|
|
force_wielded = 10
|
|
armour_penetration = 0
|
|
custom_materials = list(
|
|
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 42,
|
|
/datum/material/alloy/plasteel = SHEET_MATERIAL_AMOUNT * 15,
|
|
/datum/material/titanium = SHEET_MATERIAL_AMOUNT * 5,
|
|
)
|
|
material_slots = list(/datum/material_slot/weapon_head/speartip = /datum/material/titanium, /datum/material_slot/handle/spear = /datum/material/alloy/plasteel)
|
|
|
|
/obj/item/spear/dragonator_untreated/fire_act(exposed_temperature, exposed_volume)
|
|
var/obj/item/spear/dragonator/dragonator = new(loc)
|
|
dragonator.set_material_slots(material_slots)
|
|
dragonator.set_custom_materials(custom_materials.Copy())
|
|
playsound(dragonator.loc, 'sound/effects/magic/staff_change.ogg',5)
|
|
qdel(src)
|
|
|
|
/*
|
|
* Bone Spear
|
|
*/
|
|
/obj/item/spear/bonespear //Blatant imitation of spear, but made out of bone. Not valid for explosive modification.
|
|
name = "bone spear"
|
|
desc = "A haphazardly-constructed yet still deadly weapon. The pinnacle of modern technology."
|
|
icon_state = "bone_spear0"
|
|
base_icon_state = "bone_spear0"
|
|
icon_prefix = "bone_spear"
|
|
throwforce = 22
|
|
armour_penetration = 20 //Enhanced armor piercing
|
|
custom_materials = list(/datum/material/bone = SHEET_MATERIAL_AMOUNT * 4)
|
|
material_slots = list(/datum/material_slot/weapon_head/speartip = /datum/material/bone, /datum/material_slot/handle/spear = /datum/material/bone)
|
|
force_unwielded = 12
|
|
force_wielded = 20
|
|
spear_leftovers = /obj/item/stack/sheet/bone
|
|
pike_type = /obj/structure/headpike/bone
|
|
|
|
/obj/item/spear/bonespear/add_headpike_component()
|
|
var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/headpikebone)
|
|
|
|
AddElement(
|
|
/datum/element/slapcrafting,\
|
|
slapcraft_recipes = slapcraft_recipe_list,\
|
|
)
|
|
|
|
/*
|
|
* Bamboo Spear
|
|
*/
|
|
/obj/item/spear/bamboospear //Blatant imitation of spear, but all natural.
|
|
icon_state = "bamboo_spear0"
|
|
base_icon_state = "bamboo_spear0"
|
|
icon_prefix = "bamboo_spear"
|
|
name = "bamboo spear"
|
|
desc = "A haphazardly-constructed bamboo stick with a sharpened tip, ready to poke holes into unsuspecting people."
|
|
|
|
throwforce = 23 //Better to throw
|
|
custom_materials = list(/datum/material/bamboo = SHEET_MATERIAL_AMOUNT * 25)
|
|
material_slots = list(/datum/material_slot/weapon_head/speartip = /datum/material/bamboo, /datum/material_slot/handle/spear = /datum/material/bamboo)
|
|
spear_leftovers = /obj/item/stack/sheet/mineral/bamboo
|
|
pike_type = /obj/structure/headpike/bamboo
|
|
|
|
/obj/item/spear/bamboospear/add_headpike_component()
|
|
var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/headpikebamboo)
|
|
|
|
AddElement(
|
|
/datum/element/slapcrafting,\
|
|
slapcraft_recipes = slapcraft_recipe_list,\
|
|
)
|
|
|
|
/**
|
|
* Skybulge
|
|
*
|
|
* Gives a special ability that allows you to enter the skies an drop down upon a target.
|
|
* Other than that ability, is a default spear with extra throw force, but no embedding.
|
|
*/
|
|
/obj/item/spear/skybulge
|
|
name = "\improper Sky Bulge"
|
|
desc = "A legendary stick with a very pointy tip. Takes you to the skies!"
|
|
icon_state = "dragoonpole0"
|
|
icon_prefix = "dragoonpole"
|
|
attack_verb_continuous = list("attacks", "pokes", "jabs", "tears", "gores", "lances")
|
|
attack_verb_simple = list("attack", "poke", "jab", "tear", "gore", "lance")
|
|
throwforce = 24
|
|
embed_type = null //no embedding
|
|
material_flags = MATERIAL_EFFECTS
|
|
custom_materials = list(
|
|
/datum/material/diamond = HALF_SHEET_MATERIAL_AMOUNT,
|
|
/datum/material/alloy/plastitaniumglass = SHEET_MATERIAL_AMOUNT,
|
|
)
|
|
material_slots = list(/datum/material_slot/weapon_head/speartip = /datum/material/diamond, /datum/material_slot/handle/spear = /datum/material/alloy/plastitaniumglass)
|
|
action_slots = ITEM_SLOT_HANDS
|
|
actions_types = list(/datum/action/item_action/skybulge)
|
|
improvised_construction = FALSE
|
|
|
|
///The action button the spear gives, usable once a minute.
|
|
/datum/action/item_action/skybulge
|
|
name = "Dragoon Strike"
|
|
desc = "Jump up into the skies and fall down upon your opponents to deal double damage."
|
|
check_flags = parent_type::check_flags | AB_CHECK_IMMOBILE | AB_CHECK_PHASED
|
|
///Ref to the addtimer we have between jumping up and falling down, used to cancel early if you're incapacitated mid-jump.
|
|
var/jump_timer
|
|
///Cooldown time between jumps.
|
|
var/jump_cooldown_time = 1 MINUTES
|
|
/**
|
|
* boolean we set every time we jump, to know if we should take away the passflags we give,
|
|
* so we don't give/take when they have it from other sources (since we don't have traits, we have
|
|
* no way to tell which pass flags they get from what source.)
|
|
*/
|
|
var/gave_pass_flags = FALSE
|
|
|
|
/datum/action/item_action/skybulge/do_effect(trigger_flags)
|
|
if(!HAS_TRAIT(target, TRAIT_WIELDED))
|
|
owner.balloon_alert(owner, "not dual-wielded!")
|
|
return
|
|
var/time_left = S_TIMER_COOLDOWN_TIMELEFT(target, COOLDOWN_SKYBULGE_JUMP)
|
|
if(time_left)
|
|
owner.balloon_alert(owner, "[FLOOR(time_left * 0.1, 0.1)]s cooldown!")
|
|
return
|
|
//do after shows the progress bar as feedback, so nothing here.
|
|
if(LAZYACCESS(owner.do_afters, target))
|
|
return
|
|
|
|
owner.balloon_alert(owner, "charging up...")
|
|
ADD_TRAIT(target, TRAIT_NEEDS_TWO_HANDS, ACTION_TRAIT)
|
|
INVOKE_ASYNC(src, PROC_REF(jump_up))
|
|
|
|
///Sends the owner up in the air and calls them back down, calling land() for aftereffects.
|
|
/datum/action/item_action/skybulge/proc/jump_up()
|
|
if(!do_after(owner, 2 SECONDS, target = owner, timed_action_flags = IGNORE_USER_LOC_CHANGE))
|
|
REMOVE_TRAIT(target, TRAIT_NEEDS_TWO_HANDS, ACTION_TRAIT)
|
|
return
|
|
playsound(owner, 'sound/effects/footstep/heavy1.ogg', 50, 1)
|
|
S_TIMER_COOLDOWN_START(target, COOLDOWN_SKYBULGE_JUMP, jump_cooldown_time)
|
|
new /obj/effect/temp_visual/telegraphing/exclamation/following(get_turf(owner), 2.5 SECONDS, owner)
|
|
|
|
RegisterSignal(target, COMSIG_ITEM_ATTACK, PROC_REF(on_attack_during_jump))
|
|
ADD_TRAIT(target, TRAIT_NODROP, ACTION_TRAIT)
|
|
owner.add_traits(list(TRAIT_SILENT_FOOTSTEPS, TRAIT_MOVE_FLYING), ACTION_TRAIT)
|
|
|
|
if(owner.pass_flags & PASSTABLE)
|
|
gave_pass_flags = FALSE
|
|
else
|
|
gave_pass_flags = TRUE
|
|
owner.pass_flags |= PASSTABLE
|
|
|
|
owner.set_density(FALSE)
|
|
owner.layer = ABOVE_ALL_MOB_LAYER
|
|
|
|
animate(owner, pixel_y = owner.pixel_y + 60, time = (2 SECONDS), easing = CIRCULAR_EASING|EASE_OUT)
|
|
animate(pixel_y = initial(owner.pixel_y), time = (1 SECONDS), easing = CIRCULAR_EASING|EASE_IN)
|
|
|
|
jump_timer = addtimer(CALLBACK(src, PROC_REF(land), /*do_effects = */TRUE, /*mob_override = */owner), 3 SECONDS, TIMER_STOPPABLE)
|
|
|
|
/datum/action/item_action/skybulge/update_status_on_signal(datum/source, new_stat, old_stat)
|
|
if(!isnull(jump_timer) && !IsAvailable())
|
|
INVOKE_ASYNC(src, PROC_REF(land), /*do_effects = */FALSE, /*mob_override = */source)
|
|
deltimer(jump_timer)
|
|
return ..()
|
|
|
|
/**
|
|
* ## land()
|
|
*
|
|
* Called by jump_up, this is the post-jump effects, damaging objects and mobs it lands on.
|
|
* Args:
|
|
* do_effects - Whether we'll do the attacking effects of the land (damaging mobs & sound),
|
|
* we set this to false if we were forced out of the jump, they lost their ability to do the hit.
|
|
* mob_doing_effects - This is who we use for aftereffects, passing the mob using the ability, with owner as fallback.
|
|
* ourselves.
|
|
*/
|
|
/datum/action/item_action/skybulge/proc/land(do_effects = TRUE, mob/living/mob_doing_effects)
|
|
if(!mob_doing_effects)
|
|
mob_doing_effects = owner
|
|
var/turf/landed_on = get_turf(mob_doing_effects)
|
|
|
|
UnregisterSignal(target, COMSIG_ITEM_ATTACK)
|
|
target.remove_traits(list(TRAIT_NEEDS_TWO_HANDS, TRAIT_NODROP), ACTION_TRAIT)
|
|
mob_doing_effects.remove_traits(list(TRAIT_SILENT_FOOTSTEPS, TRAIT_MOVE_FLYING), ACTION_TRAIT)
|
|
if(gave_pass_flags)
|
|
mob_doing_effects.pass_flags &= ~PASSTABLE
|
|
mob_doing_effects.set_density(TRUE)
|
|
mob_doing_effects.layer = initial(mob_doing_effects.layer)
|
|
SET_PLANE(mob_doing_effects, initial(mob_doing_effects.plane), landed_on)
|
|
|
|
if(!do_effects)
|
|
return
|
|
|
|
playsound(mob_doing_effects, 'sound/effects/explosion/explosion1.ogg', 40, 1)
|
|
var/obj/item/skybulge_item = target
|
|
|
|
for(var/atom/thing as anything in landed_on)
|
|
if(thing == mob_doing_effects)
|
|
continue
|
|
|
|
if(isobj(thing))
|
|
thing.take_damage(150)
|
|
continue
|
|
|
|
if(isliving(thing))
|
|
skybulge_item.melee_attack_chain(owner, thing, list("[FORCE_MULTIPLIER]" = 2))
|
|
skybulge_item.attack(thing, owner)
|
|
var/mob/living/living_target = thing
|
|
living_target.SetKnockdown(1 SECONDS)
|
|
|
|
///Called when the person holding us is trying to attack something mid-jump.
|
|
///You're technically in mid-air, so block any attempts at getting extra hits in.
|
|
/datum/action/item_action/skybulge/proc/on_attack_during_jump(atom/source, mob/living/target_mob, mob/living/user, params)
|
|
SIGNAL_HANDLER
|
|
return COMPONENT_CANCEL_ATTACK_CHAIN
|