/* === Item Click Call Sequences === These are the default click code call sequences used when clicking on stuff with an item. Atoms: mob/ClickOn() calls the item's resolve_attackby() proc. item/resolve_attackby() calls the target atom's attackby() proc. Mobs: mob/living/attackby() after checking for surgery, calls the item's attack() proc. item/attack() generates attack logs, sets click cooldown and calls the mob's attacked_with_item() proc. If you override this, consider whether you need to set a click cooldown, play attack animations, and generate logs yourself. mob/attacked_with_item() should then do mob-type specific stuff (like determining hit/miss, handling shields, etc) and then possibly call the item's apply_hit_effect() proc to actually apply the effects of being hit. Item Hit Effects: item/apply_hit_effect() can be overriden to do whatever you want. However "standard" physical damage based weapons should make use of the target mob's hit_with_weapon() proc to avoid code duplication. This includes items that may sometimes act as a standard weapon in addition to having other effects (e.g. stunbatons on harm intent). */ // 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) return // Called at the start of resolve_attackby(), before the actual attack. /obj/item/proc/pre_attack(atom/a, mob/user) return //I would prefer to rename this to attack(), but that would involve touching hundreds of files. /obj/item/proc/resolve_attackby(atom/A, mob/user, params, attack_modifier = 1) pre_attack(A, user) if(!(flags & NOPRINT)) add_fingerprint(user) return A.attackby(src, user, params, attack_modifier) // No comment /atom/proc/attackby(obj/item/W, mob/user, params, attack_modifier) return /atom/movable/attackby(obj/item/W, mob/user, params, attack_modifier) if(!(W.flags & NOBLUDGEON)) visible_message("[src] has been hit by [user] with [W].") /mob/living/attackby(obj/item/I, mob/user, params, attack_modifier) if(!ismob(user)) return 0 if(can_operate(src) && I.do_surgery(src,user)) if(I.can_do_surgery(src,user)) return 1 else return 0 if(attempt_vr(src,"vore_attackby",args)) return return I.attack(src, user, user.zone_sel.selecting, attack_modifier) // Used to get how fast a mob should attack, and influences click delay. // This is just for inheritence. /mob/proc/get_attack_speed() return DEFAULT_ATTACK_COOLDOWN // Same as above but actually does useful things. // W is the item being used in the attack, if any. modifier is if the attack should be longer or shorter than usual, for whatever reason. /mob/living/get_attack_speed(var/obj/item/W) var/speed = base_attack_cooldown if(W && istype(W)) speed = W.attackspeed for(var/datum/modifier/M in modifiers) if(!isnull(M.attack_speed_percent)) speed *= M.attack_speed_percent return speed // 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 //I would prefer to rename this attack_as_weapon(), but that would involve touching hundreds of files. /obj/item/proc/attack(mob/living/M, mob/living/user, var/target_zone, var/attack_modifier) if(!force || (flags & NOBLUDGEON)) return 0 if(M == user && user.a_intent != INTENT_HARM) return 0 ///////////////////////// user.lastattacked = M M.lastattacker = user if(!no_attack_log) add_attack_logs(user,M,"attacked with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])") ///////////////////////// user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) var/hit_zone = M.resolve_item_attack(src, user, target_zone) if(hit_zone) apply_hit_effect(M, user, hit_zone, attack_modifier) return 1 //Called when a weapon is used to make a successful melee attack on a mob. Returns the blocked result /obj/item/proc/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone, attack_modifier = 1) user.break_cloak() if(hitsound) playsound(loc, hitsound, 50, 1, -1) var/power = force for(var/datum/modifier/M in user.modifiers) if(!isnull(M.outgoing_melee_damage_percent)) power *= M.outgoing_melee_damage_percent if(HULK in user.mutations) power *= 2 power *= attack_modifier return target.hit_with_weapon(src, user, power, hit_zone)