Wearing armor reduces the blood loss you incur, no longer are you instantly deleted on blood. Dripping blood WILL kill you if you don't solve that issue, medical gauze has been tripled as a QoL for medical staff as a result.
186 lines
7.7 KiB
Plaintext
186 lines
7.7 KiB
Plaintext
|
|
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
|
|
if(!tool_attack_chain(user, target) && pre_attack(target, user, params))
|
|
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
|
|
var/resolved = target.attackby(src, user, params)
|
|
if(!resolved && target && !QDELETED(src))
|
|
afterattack(target, user, 1, params) // 1: clicking something Adjacent
|
|
|
|
|
|
//Checks if the item can work as a tool, calling the appropriate tool behavior on the target
|
|
/obj/item/proc/tool_attack_chain(mob/user, atom/target)
|
|
if(!tool_behaviour)
|
|
return FALSE
|
|
|
|
return target.tool_act(user, src, tool_behaviour)
|
|
|
|
|
|
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
|
|
/obj/item/proc/attack_self(mob/user)
|
|
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_NO_INTERACT)
|
|
return
|
|
interact(user)
|
|
|
|
/obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby!
|
|
if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_NO_ATTACK)
|
|
return FALSE
|
|
return TRUE //return FALSE to avoid calling attackby after this proc does stuff
|
|
|
|
// No comment
|
|
/atom/proc/attackby(obj/item/W, mob/user, params)
|
|
if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, params) & COMPONENT_NO_AFTERATTACK)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/attackby(obj/item/I, mob/living/user, params)
|
|
return ..() || ((obj_flags & CAN_BE_HIT) && I.attack_obj(src, user))
|
|
|
|
/mob/living/attackby(obj/item/I, mob/living/user, params)
|
|
if(..())
|
|
return TRUE
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
if(user.a_intent == INTENT_HARM && stat == DEAD && (butcher_results || guaranteed_butcher_results)) //can we butcher it?
|
|
GET_COMPONENT_FROM(butchering, /datum/component/butchering, I)
|
|
if(butchering && butchering.butchering_enabled)
|
|
to_chat(user, "<span class='notice'>You begin to butcher [src]...</span>")
|
|
playsound(loc, butchering.butcher_sound, 50, TRUE, -1)
|
|
if(do_mob(user, src, butchering.speed) && Adjacent(I))
|
|
butchering.Butcher(user, src)
|
|
return 1
|
|
else if(I.is_sharp() && !butchering) //give sharp objects butchering functionality, for consistency
|
|
I.AddComponent(/datum/component/butchering, 80 * I.toolspeed)
|
|
attackby(I, user, params) //call the attackby again to refresh and do the butchering check again
|
|
return
|
|
return I.attack(src, user)
|
|
|
|
|
|
/obj/item/proc/attack(mob/living/M, mob/living/user)
|
|
SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user)
|
|
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
|
|
if(item_flags & NOBLUDGEON)
|
|
return
|
|
|
|
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) // CIT CHANGE - makes it impossible to attack in stamina softcrit
|
|
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
|
|
return // CIT CHANGE - ditto
|
|
|
|
if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM))
|
|
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
|
|
return
|
|
|
|
if(!force)
|
|
playsound(loc, 'sound/weapons/tap.ogg', get_clamped_volume(), 1, -1)
|
|
else if(hitsound)
|
|
playsound(loc, hitsound, get_clamped_volume(), 1, -1)
|
|
|
|
M.lastattacker = user.real_name
|
|
M.lastattackerckey = user.ckey
|
|
|
|
user.do_attack_animation(M)
|
|
M.attacked_by(src, user)
|
|
|
|
log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
|
|
add_fingerprint(user)
|
|
|
|
user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes attacking things cause stamina loss
|
|
|
|
//the equivalent of the standard version of attack() but for object targets.
|
|
/obj/item/proc/attack_obj(obj/O, mob/living/user)
|
|
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ)
|
|
return
|
|
if(item_flags & NOBLUDGEON)
|
|
return
|
|
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) // CIT CHANGE - makes it impossible to attack in stamina softcrit
|
|
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
|
|
return // CIT CHANGE - ditto
|
|
user.adjustStaminaLossBuffered(getweight()*1.2)//CIT CHANGE - makes attacking things cause stamina loss
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
user.do_attack_animation(O)
|
|
O.attacked_by(src, user)
|
|
|
|
/atom/movable/proc/attacked_by()
|
|
return
|
|
|
|
/obj/attacked_by(obj/item/I, mob/living/user)
|
|
if(I.force)
|
|
visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
|
//only witnesses close by and the victim see a hit message.
|
|
log_combat(user, src, "attacked", I)
|
|
take_damage(I.force, I.damtype, "melee", 1)
|
|
|
|
/mob/living/attacked_by(obj/item/I, mob/living/user)
|
|
send_item_attack_message(I, user)
|
|
if(I.force)
|
|
//CIT CHANGES START HERE - combatmode and resting checks
|
|
var/totitemdamage = I.force
|
|
if(iscarbon(user))
|
|
var/mob/living/carbon/tempcarb = user
|
|
if(!tempcarb.combatmode)
|
|
totitemdamage *= 0.5
|
|
if(user.resting)
|
|
totitemdamage *= 0.5
|
|
//CIT CHANGES END HERE
|
|
apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage
|
|
if(I.damtype == BRUTE)
|
|
if(prob(33))
|
|
I.add_mob_blood(src)
|
|
var/turf/location = get_turf(src)
|
|
if(iscarbon(src))
|
|
if(ishuman(src))
|
|
var/mob/living/carbon/human/H = src
|
|
var/armorsave = H.getarmor(H, "melee")
|
|
if(armorsave >= 30) // armor is useful again!
|
|
H.bleed_rate += round((totitemdamage * 0.15)) // internal bleeding, took it on the joint, what have you.
|
|
else
|
|
H.bleed_rate += round((totitemdamage * 0.50)) //it's not a 1:1 deletion of blood, but it's worrysome enough that you should get treated asap
|
|
else
|
|
var/mob/living/carbon/C = src
|
|
C.bleed(totitemdamage)
|
|
else
|
|
add_splatter_floor(location)
|
|
if(totitemdamage >= 10 && get_dist(user, src) <= 1) //people with TK won't get smeared with blood
|
|
user.add_mob_blood(src)
|
|
return TRUE //successful attack
|
|
|
|
/mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user)
|
|
if(I.force < force_threshold || I.damtype == STAMINA)
|
|
playsound(loc, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1)
|
|
else
|
|
return ..()
|
|
|
|
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
|
|
// Click parameters is the params string from byond Click() code, see that documentation.
|
|
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
|
SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters)
|
|
SEND_SIGNAL(user, COMSIG_MOB_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters)
|
|
|
|
/obj/item/proc/get_clamped_volume()
|
|
if(w_class)
|
|
if(force)
|
|
return CLAMP((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
|
|
else
|
|
return CLAMP(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
|
|
|
|
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
|
|
var/message_verb = "attacked"
|
|
if(I.attack_verb && I.attack_verb.len)
|
|
message_verb = "[pick(I.attack_verb)]"
|
|
else if(!I.force)
|
|
return
|
|
var/message_hit_area = ""
|
|
if(hit_area)
|
|
message_hit_area = " in the [hit_area]"
|
|
var/attack_message = "[src] has been [message_verb][message_hit_area] with [I]."
|
|
if(user in viewers(src, null))
|
|
attack_message = "[user] has [message_verb] [src][message_hit_area] with [I]!"
|
|
visible_message("<span class='danger'>[attack_message]</span>",\
|
|
"<span class='userdanger'>[attack_message]</span>", null, COMBAT_MESSAGE_RANGE)
|
|
if(hit_area == BODY_ZONE_HEAD)
|
|
if(prob(2))
|
|
playsound(src, 'sound/weapons/dink.ogg', 30, 1)
|
|
return 1
|
|
|
|
/obj/item/proc/getweight()
|
|
return total_mass || w_class * 1.25
|
|
|