Files
Paradise/code/_onclick/item_attack.dm
Charlie 634f9c72f1 Vampire Rework. (#16476)
* vampire rework

* fixes and tweaks

* cleanup + tweaks

* grug stomp

* TGUI

* TGUI rebuild

* UID fix

* debugging cooldown fix

* first review changes

* subclass refactor

* tweaks + some sprites

* blackbox logging

* tweaks + grammar

* minor UI tweaks

* ability icon sprites.

* placeholder sprite warning fix

* melee mod code comment warning

* nullification rework

* final sprites!

* fixes

* sabre review pt 1

Co-authored-by: SabreML <57483089+SabreML@users.noreply.github.com>

* sabre review pt2

* sprites readd

* tgui rebuild

* removes traitor vampires

* fixes

* readds sprites

* runtime fixes

* hotfix

* more runtime fixes

* glare tweak. less confusing when the vampire is stunned.

* gargantua nerf

* minor tweaks.

* hemomancer nerfs

* bugfixes and cleanup

* I did a dumb

* couple of fixes

* confusion and shadow snare fixes

* hemomancer nerfs part 2 electric boogaloo

* TGUI rebuild

* fixes and easier events

* Umbrae tweaks

* gargantua tweak

* umbrae nerf 2 electric boogaloo. also var edit suggestion

* runtime fix

* buffs blood nutrition to be in line with its metabolic rate

* Henk stuff

Co-authored-by: Farie82 <farie82@users.noreply.github.com>

* more review changes

* final tweak

* affected request + runtime fix

* FUCK

* fat fucks

* darkness tweaks

* UMBRAE AAAAAAAAAAAAAHH

* force doors bugfix

* either git or I am drunk

* admin rejuv fix

* I CANNOT SPELL

* shitnt code

* steel review

* tgui rebuild

* mochi review

* vampire ability usage logging

Co-authored-by: SabreML <57483089+SabreML@users.noreply.github.com>
Co-authored-by: Farie82 <farie82@users.noreply.github.com>
2021-11-14 15:34:56 +01:00

166 lines
6.5 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
//Note that if tool_act returns TRUE, then the tool won't call attack_by.
/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
return
/obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby!
if(is_hot(src) && A.reagents && !ismob(A))
to_chat(user, "<span class='notice'>You heat [A] with [src].</span>")
A.reagents.temperature_reagents(is_hot(src))
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 ..() || (can_be_hit && I.attack_obj(src, user, params))
/mob/living/attackby(obj/item/I, mob/living/user, params)
user.changeNext_move(CLICK_CD_MELEE)
if(attempt_harvest(I, user))
return TRUE
return I.attack(src, user)
/obj/item/proc/attack(mob/living/M, mob/living/user, def_zone)
SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user)
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
if(flags & (NOBLUDGEON))
return FALSE
if(can_operate(M)) //Checks if mob is lying down on table for surgery
if(istype(src,/obj/item/robot_parts))//popup override for direct attach
if(!attempt_initiate_surgery(src, M, user,1))
return FALSE
else
return TRUE
if(istype(src,/obj/item/organ/external))
var/obj/item/organ/external/E = src
if(E.is_robotic()) // Robot limbs are less messy to attach
if(!attempt_initiate_surgery(src, M, user,1))
return FALSE
else
return TRUE
var/obj/item/organ/external/O = M.get_organ(user.zone_selected)
if((is_sharp(src) || (isscrewdriver(src) && O?.is_robotic())) && user.a_intent == INTENT_HELP)
if(!attempt_initiate_surgery(src, M, user))
return FALSE
else
return TRUE
if(force && 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
SEND_SIGNAL(M, COMSIG_ITEM_ATTACK)
add_attack_logs(user, M, "Attacked with [name] ([uppertext(user.a_intent)]) ([uppertext(damtype)])", (M.ckey && force > 0 && damtype != STAMINA) ? null : ATKLOG_ALMOSTALL)
if(hitsound)
playsound(loc, hitsound, get_clamped_volume(), TRUE, extrarange = stealthy_audio ? SILENCED_SOUND_EXTRARANGE : -1, falloff_distance = 0)
M.lastattacker = user.real_name
M.lastattackerckey = user.ckey
user.do_attack_animation(M)
. = M.attacked_by(src, user, def_zone)
add_fingerprint(user)
//the equivalent of the standard version of attack() but for object targets.
/obj/item/proc/attack_obj(obj/O, mob/living/user, params)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ)
return
if(flags & (NOBLUDGEON))
return
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)
var/damage = I.force
if(I.force)
user.visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", "<span class='danger'>You hit [src] with [I]!</span>")
if(ishuman(user))
var/mob/living/carbon/human/H = user
damage += H.physiology.melee_bonus
take_damage(damage, I.damtype, MELEE, 1)
/mob/living/attacked_by(obj/item/I, mob/living/user, def_zone)
send_item_attack_message(I, user)
if(I.force)
var/bonus_damage = 0
if(ishuman(user))
var/mob/living/carbon/human/H = user
bonus_damage = H.physiology.melee_bonus
apply_damage(I.force + bonus_damage, I.damtype, def_zone)
if(I.damtype == BRUTE)
if(prob(33))
I.add_mob_blood(src)
var/turf/location = get_turf(src)
add_splatter_floor(location)
if(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)
user.visible_message("<span class='warning'>[user] gently taps [src] with [I].</span>",\
"<span class='warning'>This weapon is ineffective, it does no damage!</span>")
else if(I.force < force_threshold || I.damtype == STAMINA)
visible_message("<span class='warning'>[I] bounces harmlessly off of [src].</span>",\
"<span class='warning'>[I] bounces harmlessly off of [src]!</span>")
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)
return
/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)
if(I.discrete)
return
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='combat danger'>[attack_message]</span>",\
"<span class='combat userdanger'>[attack_message]</span>")
return 1