mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-10 15:45:05 +01:00
13814fb55b
## About The Pull Request Closes #96062 ## Changelog 🆑 fix: Fixed materials runtiming whenever thrown by something other than a mob /🆑
211 lines
9.1 KiB
Plaintext
211 lines
9.1 KiB
Plaintext
// Generic slots for weapons
|
|
|
|
/// Generic main/parent type for all weapon heads
|
|
/datum/material_slot/weapon_head
|
|
name = "weapon head"
|
|
requirement_type = /datum/material_requirement/solid_material
|
|
|
|
/datum/material_slot/weapon_head/on_applied(obj/item/target, datum/material/material, amount, multiplier)
|
|
// Weapon head controls strength and conductivity
|
|
if (!(target.material_flags & MATERIAL_EFFECTS))
|
|
return FALSE
|
|
|
|
// Effect signals
|
|
RegisterSignal(target, COMSIG_MOVABLE_IMPACT, PROC_REF(on_throw_impact))
|
|
RegisterSignal(target, COMSIG_MOVABLE_IMPACT_ZONE, PROC_REF(on_throw_impact_living))
|
|
RegisterSignal(target, COMSIG_ITEM_ATTACK, PROC_REF(on_item_attack))
|
|
RegisterSignal(target, COMSIG_ITEM_ATTACK_ATOM, PROC_REF(on_item_attack))
|
|
RegisterSignal(target, COMSIG_ITEM_ATTACK_ZONE, PROC_REF(on_item_attack_living))
|
|
|
|
if (!(target.material_flags & MATERIAL_AFFECT_STATISTICS))
|
|
return FALSE
|
|
|
|
// Damage
|
|
target.change_material_strength(material, amount, multiplier)
|
|
|
|
// Conductivity
|
|
var/conductivity = material.get_property(MATERIAL_ELECTRICAL)
|
|
var/siemens_modifier = round(max(0, conductivity - 1) ** 1.18 * 0.15, 0.01)
|
|
var/siemens_mult = 1 + (siemens_modifier - 1) * multiplier
|
|
target.siemens_coefficient *= max(0, siemens_mult)
|
|
|
|
if (target.siemens_coefficient == 0)
|
|
target.obj_flags &= ~CONDUCTS_ELECTRICITY
|
|
|
|
/datum/material_slot/weapon_head/on_removed(obj/item/target, datum/material/material, amount, multiplier)
|
|
var/static/list/interaction_signals = list(
|
|
COMSIG_MOVABLE_IMPACT,
|
|
COMSIG_MOVABLE_IMPACT_ZONE,
|
|
COMSIG_ITEM_ATTACK,
|
|
COMSIG_ITEM_ATTACK_ATOM,
|
|
COMSIG_ITEM_ATTACK_ZONE,
|
|
)
|
|
UnregisterSignal(target, interaction_signals)
|
|
|
|
if (!(target.material_flags & MATERIAL_AFFECT_STATISTICS) || !(target.material_flags & MATERIAL_EFFECTS))
|
|
return FALSE
|
|
|
|
// Damage
|
|
target.change_material_strength(material, amount, multiplier, remove = TRUE)
|
|
|
|
// Conductivity
|
|
var/conductivity = material.get_property(MATERIAL_ELECTRICAL)
|
|
var/siemens_modifier = round(max(0, conductivity - 1) ** 1.18 * 0.15, 0.01)
|
|
var/siemens_mult = 1 + (siemens_modifier - 1) * multiplier
|
|
if (siemens_mult > 0)
|
|
target.siemens_coefficient /= siemens_mult
|
|
|
|
if (target.siemens_coefficient > 0 && (initial(target.obj_flags) & CONDUCTS_ELECTRICITY) && !(target.obj_flags & CONDUCTS_ELECTRICITY))
|
|
target.obj_flags |= CONDUCTS_ELECTRICITY
|
|
|
|
/datum/material_slot/weapon_head/proc/on_throw_impact(obj/item/source, atom/hit_atom, datum/thrownthing/throwing_datum, caught)
|
|
SIGNAL_HANDLER
|
|
if (!caught && !isliving(hit_atom))
|
|
affect_throw_impact(source, hit_atom, astype(throwing_datum.thrower?.resolve(), /mob/living))
|
|
|
|
/datum/material_slot/weapon_head/proc/on_item_attack(obj/item/source, atom/movable/target, mob/living/user)
|
|
SIGNAL_HANDLER
|
|
// Living mobs use a different signal
|
|
if (!isliving(target))
|
|
affect_target(source, target, user)
|
|
|
|
/datum/material_slot/weapon_head/proc/on_item_attack_living(obj/item/source, mob/living/target, mob/living/user, def_zone)
|
|
SIGNAL_HANDLER
|
|
|
|
var/skin_contact = body_zone2cover_flags(def_zone)
|
|
for (var/obj/item/worn_item in target.get_equipped_items(INCLUDE_ABSTRACT))
|
|
skin_contact &= ~worn_item.body_parts_covered
|
|
if (!skin_contact)
|
|
break
|
|
|
|
affect_target(source, target, user, def_zone, !!skin_contact)
|
|
|
|
/datum/material_slot/weapon_head/proc/on_throw_impact_living(obj/item/source, mob/living/target, def_zone, blocked, datum/thrownthing/throwing_datum)
|
|
SIGNAL_HANDLER
|
|
|
|
var/skin_contact = body_zone2cover_flags(def_zone)
|
|
for (var/obj/item/worn_item in target.get_equipped_items(INCLUDE_ABSTRACT))
|
|
skin_contact &= ~worn_item.body_parts_covered
|
|
if (!skin_contact)
|
|
break
|
|
|
|
affect_throw_impact(source, target, astype(throwing_datum.thrower?.resolve(), /mob/living), def_zone, !!skin_contact)
|
|
|
|
/datum/material_slot/weapon_head/proc/affect_target(obj/item/source, atom/target, mob/living/user, def_zone, skin_contact = TRUE)
|
|
var/datum/material/source_mat = source.get_material_from_slot(type)
|
|
SEND_SIGNAL(source_mat, COMSIG_MATERIAL_EFFECT_HIT, source, target, user, def_zone, skin_contact)
|
|
|
|
/datum/material_slot/weapon_head/proc/affect_throw_impact(obj/item/source, atom/target, mob/living/user, def_zone, skin_contact = TRUE)
|
|
var/datum/material/source_mat = source.get_material_from_slot(type)
|
|
SEND_SIGNAL(source_mat, COMSIG_MATERIAL_EFFECT_THROW_IMPACT, source, target, user, def_zone, skin_contact)
|
|
|
|
/// Main type for all weapon handles
|
|
/datum/material_slot/handle
|
|
name = "handle"
|
|
requirement_type = /datum/material_requirement/solid_material
|
|
|
|
/datum/material_slot/handle/on_applied(obj/item/target, datum/material/material, amount, multiplier)
|
|
// Handle controls integrity, armor, conductivity and wieldiness stats-wise
|
|
if (!(target.material_flags & MATERIAL_EFFECTS))
|
|
return FALSE
|
|
|
|
// Effect signals
|
|
RegisterSignal(target, COMSIG_MOVABLE_IMPACT, PROC_REF(on_throw_impact))
|
|
RegisterSignal(target, COMSIG_ITEM_ATTACK, PROC_REF(on_item_attack))
|
|
RegisterSignal(target, COMSIG_ITEM_ATTACK_ATOM, PROC_REF(on_item_attack))
|
|
RegisterSignal(target, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_item_attack_self))
|
|
|
|
if (!(target.material_flags & MATERIAL_AFFECT_STATISTICS))
|
|
return FALSE
|
|
|
|
// Armor/integrity
|
|
var/integrity_mod = material.get_property(MATERIAL_INTEGRITY)
|
|
target.modify_max_integrity(ceil(target.max_integrity * integrity_mod))
|
|
var/list/armor_mods = material.get_armor_modifiers(multiplier)
|
|
target.set_armor(target.get_armor().generate_new_with_multipliers(armor_mods))
|
|
|
|
// Conductivity
|
|
var/conductivity = material.get_property(MATERIAL_ELECTRICAL)
|
|
var/siemens_modifier = round(max(0, conductivity - 1) ** 1.18 * 0.15, 0.01)
|
|
var/siemens_mult = 1 + (siemens_modifier - 1) * multiplier
|
|
target.siemens_coefficient *= max(0, siemens_mult)
|
|
|
|
if (target.siemens_coefficient == 0)
|
|
target.obj_flags &= ~CONDUCTS_ELECTRICITY
|
|
|
|
// Wielding
|
|
var/density = material.get_property(MATERIAL_DENSITY)
|
|
var/hardness = material.get_property(MATERIAL_HARDNESS)
|
|
// Can be faster/slower by 2 dcs
|
|
target.attack_speed += MATERIAL_PROPERTY_DIVERGENCE(density, 4, 6) * 0.5 * multiplier
|
|
target.throw_range += ((hardness - 4) - (density - 4) * 2) * multiplier
|
|
return FALSE
|
|
|
|
/datum/material_slot/handle/on_removed(obj/item/target, datum/material/material, amount, multiplier)
|
|
UnregisterSignal(target, list(COMSIG_MOVABLE_IMPACT, COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_ATOM, COMSIG_ITEM_ATTACK_SELF))
|
|
|
|
if (!(target.material_flags & MATERIAL_AFFECT_STATISTICS) || !(target.material_flags & MATERIAL_EFFECTS))
|
|
return FALSE
|
|
|
|
// Armor/integrity
|
|
var/integrity_mod = material.get_property(MATERIAL_INTEGRITY)
|
|
|
|
target.modify_max_integrity(ceil(target.max_integrity * integrity_mod))
|
|
var/list/armor_mods = material.get_armor_modifiers(multiplier)
|
|
for (var/armor_type, value in armor_mods)
|
|
if (value != 0) // Needs to be restored to initial values in finalize effects, sorry
|
|
armor_mods[armor_type] = 1 / value
|
|
target.set_armor(target.get_armor().generate_new_with_multipliers(armor_mods))
|
|
|
|
// Conductivity
|
|
var/conductivity = material.get_property(MATERIAL_ELECTRICAL)
|
|
var/siemens_modifier = round(max(0, conductivity - 1) ** 1.18 * 0.15, 0.01)
|
|
var/siemens_mult = 1 + (siemens_modifier - 1) * multiplier
|
|
if (siemens_mult > 0)
|
|
target.siemens_coefficient /= siemens_mult
|
|
|
|
if (target.siemens_coefficient > 0 && (initial(target.obj_flags) & CONDUCTS_ELECTRICITY) && !(target.obj_flags & CONDUCTS_ELECTRICITY))
|
|
target.obj_flags |= CONDUCTS_ELECTRICITY
|
|
|
|
// Wielding
|
|
var/density = material.get_property(MATERIAL_DENSITY)
|
|
var/hardness = material.get_property(MATERIAL_HARDNESS)
|
|
target.attack_speed -= MATERIAL_PROPERTY_DIVERGENCE(density, 4, 6) * 0.5 * multiplier
|
|
target.throw_range -= ((hardness - 4) - (density - 4) * 2) * multiplier
|
|
return FALSE
|
|
|
|
/datum/material_slot/handle/proc/on_item_attack(obj/item/source, atom/movable/target, mob/living/user)
|
|
SIGNAL_HANDLER
|
|
affect_user(source, user, user)
|
|
|
|
/datum/material_slot/handle/proc/on_item_attack_self(obj/item/source, mob/living/user)
|
|
SIGNAL_HANDLER
|
|
affect_user(source, user, user)
|
|
|
|
/datum/material_slot/handle/proc/on_throw_impact(obj/item/source, atom/hit_atom, datum/thrownthing/throwing_datum, caught)
|
|
SIGNAL_HANDLER
|
|
if (caught)
|
|
affect_user(source, hit_atom, astype(throwing_datum.thrower?.resolve(), /mob/living))
|
|
|
|
/datum/material_slot/handle/proc/affect_user(obj/item/source, mob/living/user, mob/living/initiator)
|
|
var/datum/material/source_mat = source.get_material_from_slot(type)
|
|
var/arm_dir = IS_LEFT_INDEX(user.active_hand_index) ? BODY_ZONE_L_ARM : BODY_ZONE_R_ARM
|
|
if (!ishuman(user))
|
|
SEND_SIGNAL(source_mat, COMSIG_MATERIAL_EFFECT_TOUCH, source, user, initiator, arm_dir, TRUE)
|
|
return
|
|
|
|
var/mob/living/carbon/human/as_human = user
|
|
var/obj/item/bodypart/hand = as_human.has_hand_for_held_index(as_human.get_held_index_of_item(source))
|
|
if (!hand) // ???
|
|
SEND_SIGNAL(source_mat, COMSIG_MATERIAL_EFFECT_TOUCH, source, user, initiator, arm_dir, FALSE) // ...no hand, no skin contact?
|
|
return
|
|
|
|
var/list/obj/item/hand_covers = as_human.get_clothing_on_part(hand)
|
|
var/hand_covered = FALSE
|
|
for (var/obj/item/worn_item in hand_covers)
|
|
if (worn_item.body_parts_covered & HANDS)
|
|
hand_covered = TRUE
|
|
break
|
|
|
|
SEND_SIGNAL(source_mat, COMSIG_MATERIAL_EFFECT_TOUCH, source, user, initiator, hand.body_zone, !hand_covered)
|