/** *This is the proc that handles the order of an item_attack. *The order of procs called is: *tool_act on the target. If it returns TRUE, the chain will be stopped. *pre_attack() on src. If this returns TRUE, the chain will be stopped. *attackby on the target. If it returns TRUE, the chain will be stopped. *and lastly *afterattack. The return value does not matter. */ /obj/item/proc/melee_attack_chain(mob/user, atom/target, params) if(item_flags & NO_ATTACK_CHAIN_SOFT_STAMCRIT) if(isliving(user)) var/mob/living/L = user if(L.getStaminaLoss() >= STAMINA_SOFTCRIT) to_chat(L, "You are too exhausted to swing [src]!") return if(tool_behaviour && target.tool_act(user, src, tool_behaviour)) return if(pre_attack(target, user, params)) return if(target.attackby(src,user, params)) return if(QDELETED(src) || QDELETED(target)) return afterattack(target, user, TRUE, params) // 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 TRUE return FALSE //return TRUE 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) return I.attack(src, user) /obj/item/proc/attack(mob/living/M, mob/living/user) if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK) return 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, "You're too exhausted.") // CIT CHANGE - ditto return // CIT CHANGE - ditto if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, "You don't want to harm other living beings!") 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()*0.8)//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, "You're too exhausted.") // 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("[user] has hit [src] with [I]!", 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) //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 if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration)) return FALSE send_item_attack_message(I, user) if(I.force) apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW)) if(prob(33)) I.add_mob_blood(src) var/turf/location = get_turf(src) if(iscarbon(src)) 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("[attack_message]",\ "[attack_message]", 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