Refactors various item attack() implementations

Replaced some attack() overrides with apply_hit_effect() or other attack
procs where appropriate.
Removed the attack() override from reagent_containers.
This commit is contained in:
mwerezak
2015-07-25 21:43:49 -04:00
parent 6ceffaacb5
commit 068d02c28c
22 changed files with 141 additions and 230 deletions

View File

@@ -3,16 +3,17 @@
/obj/item/proc/attack_self(mob/user)
return
/obj/item/proc/resolve_attackby(atom/A, mob/source)
add_fingerprint(source)
return A.attackby(src,source)
//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)
add_fingerprint(user)
return A.attackby(src, user)
// No comment
/atom/proc/attackby(obj/item/W, mob/user)
return
/atom/movable/attackby(obj/item/W, mob/user)
if(!(W.flags&NOBLUDGEON))
if(!(W.flags & NOBLUDGEON))
visible_message("<span class='danger'>[src] has been hit by [user] with [W].</span>")
/mob/living/attackby(obj/item/I, mob/user)
@@ -20,7 +21,6 @@
return 0
if(can_operate(src) && do_surgery(src,user,I)) //Surgery
return 1
if(istype(I))
return I.attack(src, user, user.zone_sel.selecting)
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
@@ -28,9 +28,8 @@
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
return
/obj/item/proc/attack(mob/living/M, mob/living/user, def_zone)
if(!istype(M))
return 0
//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)
if(!force || (flags & NOBLUDGEON))
return 0
@@ -46,7 +45,10 @@
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.do_attack_animation(M)
M.attacked_with_item(src, user, def_zone)
var/hit_zone = M.resolve_item_attack(src, user, target_zone)
if(hit_zone)
apply_hit_effect(M, user, hit_zone)
return 1

View File

@@ -6,23 +6,31 @@
w_class = 4
force = 30
throwforce = 10
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
/obj/item/weapon/melee/cultblade/cultify()
return
/obj/item/weapon/melee/cultblade/attack(mob/living/target as mob, mob/living/carbon/human/user as mob)
/obj/item/weapon/melee/cultblade/attack(mob/living/M, mob/living/user, var/target_zone)
if(iscultist(user))
playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
return ..()
var/zone = (user.hand ? "l_arm":"r_arm")
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/external/affecting = H.get_organ(zone)
user << "<span class='warning'>An unexplicable force rips through your [affecting.name], tearing the sword from your grasp!</span>"
else
user.Paralyse(5)
user << "<span class='warning'>An unexplicable force powerfully repels the sword from [target]!</span>"
var/organ = ((user.hand ? "l_":"r_") + "arm")
var/obj/item/organ/external/affecting = user.get_organ(organ)
if(affecting.take_damage(rand(force/2, force))) //random amount of damage between half of the blade's force and the full force of the blade.
user.UpdateDamageIcon()
return
user << "<span class='warning'>An unexplicable force rips through you, tearing the sword from your grasp!</span>"
//random amount of damage between half of the blade's force and the full force of the blade.
user.apply_damage(rand(force/2, force), BRUTE, zone, 0)
user.Weaken(5)
user.drop_from_inventory(src)
throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), throw_speed)
return 1
/obj/item/weapon/melee/cultblade/pickup(mob/living/user as mob)
if(!iscultist(user))

View File

@@ -31,8 +31,8 @@
last_used = world.time
times_used = max(0,round(times_used)) //sanity
/obj/item/device/flash/attack(mob/living/M as mob, mob/user as mob)
//attack_as_weapon
/obj/item/device/flash/attack(mob/living/M, mob/living/user, var/target_zone)
if(!user || !M) return //sanity
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been flashed (attempt) with [src.name] by [user.name] ([user.ckey])</font>")
@@ -183,7 +183,8 @@
icon_state = "sflash"
origin_tech = list(TECH_MAGNET = 2, TECH_COMBAT = 1)
/obj/item/device/flash/synthetic/attack(mob/living/M as mob, mob/user as mob)
//attack_as_weapon
/obj/item/device/flash/synthetic/attack(mob/living/M, mob/living/user, var/target_zone)
..()
if(!broken)
broken = 1

View File

@@ -10,31 +10,20 @@
icon = 'icons/obj/decals.dmi'
icon_state = "shock"
/obj/item/borg/stun/attack(var/mob/living/M, var/mob/living/silicon/robot/user)
if(!istype(M))
return
// How the Hell.
/obj/item/borg/stun/apply_hit_effect(mob/living/M, mob/living/silicon/robot/user, var/hit_zone)
if(!istype(user))
var/mob/living/temp = user
if(istype(temp))
temp.drop_from_inventory(src)
qdel(src)
return
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been attacked with [src.name] by [user.name] ([user.ckey])</font>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] to attack [M.name] ([M.ckey])</font>")
msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
if(!user.cell || !user.cell.checked_use(1250)) //Slightly more than a baton.
user.visible_message("<span class='danger'>\The [user] has prodded \the [M] with its arm!</span>")
return
if (M.stuttering < 5)
M.stuttering = 5
M.stun_effect_act(0, 70, check_zone(user.zone_sel.selecting), src)
user.visible_message("<span class='danger'>\The [user] has prodded \the [M] with \a [src]!</span>")
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
M.apply_effect(5, STUTTER)
M.stun_effect_act(0, 70, check_zone(hit_zone), src)
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.forcesay(hit_appends)

View File

@@ -38,7 +38,8 @@
target.clean_blood()
return
/obj/item/weapon/soap/attack(mob/target as mob, mob/user as mob)
//attack_as_weapon
/obj/item/weapon/soap/attack(mob/living/target, mob/living/user, var/target_zone)
if(target && user && ishuman(target) && ishuman(user) && !target.stat && !user.stat && user.zone_sel &&user.zone_sel.selecting == "mouth" )
user.visible_message("<span class='danger'>\The [user] washes \the [target]'s mouth out with soap!</span>")
return

View File

@@ -61,7 +61,7 @@
qdel(src)
/obj/item/weapon/a_gift/attack_self(mob/M as mob)
var/gift_type = pick(/obj/item/weapon/sord,
var/gift_type = pick(
/obj/item/weapon/storage/wallet,
/obj/item/weapon/storage/photo_album,
/obj/item/weapon/storage/box/snappops,
@@ -80,7 +80,6 @@
/obj/item/weapon/bikehorn,
/obj/item/weapon/beach_ball,
/obj/item/weapon/beach_ball/holoball,
/obj/item/weapon/banhammer,
/obj/item/toy/balloon,
/obj/item/toy/blink,
/obj/item/toy/crossbow,

View File

@@ -108,6 +108,7 @@
/obj/item/weapon/material/kitchen/rollingpin/attack(mob/living/M as mob, mob/living/user as mob)
if ((CLUMSY in user.mutations) && prob(50))
user << "<span class='warning'>The [src] slips out of your hand and hits your head.</span>"
user.drop_from_inventory(src)
user.take_organ_damage(10)
user.Paralyse(2)
return

View File

@@ -64,9 +64,7 @@
processing_objects -= src
..()
/obj/item/weapon/material/attack()
if(!..())
return
/obj/item/weapon/material/apply_hit_effect()
if(!unbreakable)
if(material.is_brittle())
health = 0

View File

@@ -44,7 +44,6 @@
icon = 'icons/obj/weapons.dmi'
icon_state = "hoe"
item_state = "hoe"
flags = CONDUCT | NOBLUDGEON
force_divisor = 0.25 // 5 with weight 20 (steel)
thrown_force_divisor = 0.25 // as above
w_class = 2

View File

@@ -97,71 +97,55 @@
user << "<span class='warning'>[src] is out of charge.</span>"
add_fingerprint(user)
/obj/item/weapon/melee/baton/attack(mob/M, mob/user)
if(status && (CLUMSY in user.mutations) && prob(50))
user << "<span class='danger'>You accidentally hit yourself with the [src]!</span>"
user.Weaken(30)
deductcharge(hitcost)
return
return ..()
if(isrobot(M))
/obj/item/weapon/melee/baton/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
if(isrobot(target))
..()
return
var/agony = agonyforce
var/stun = stunforce
var/mob/living/L = M
var/obj/item/organ/external/affecting = null
if(ishuman(target))
var/mob/living/carbon/human/H = target
affecting = H.get_organ(hit_zone)
var/target_zone = check_zone(user.zone_sel.selecting)
if(user.a_intent == I_HURT)
if (!..()) //item/attack() does it's own messaging and logs
return 0 // item/attack() will return 1 if they hit, 0 if they missed.
agony *= 0.5 //whacking someone causes a much poorer contact than prodding them.
..()
//whacking someone causes a much poorer electrical contact than deliberately prodding them.
agony *= 0.5
stun *= 0.5
//we can't really extract the actual hit zone from ..(), unfortunately. Just act like they attacked the area they intended to.
else if(!status)
if(affecting)
target.visible_message("<span class='warning'>[target] has been prodded in the [affecting.name] with [src] by [user]. Luckily it was off.</span>")
else
//copied from human_defense.dm - human defence code should really be refactored some time.
if (ishuman(L))
user.lastattacked = L //are these used at all, if we have logs?
L.lastattacker = user
if (user != L) // Attacking yourself can't miss
target_zone = get_zone_with_miss_chance(user.zone_sel.selecting, L)
if(!target_zone)
L.visible_message("<span class='danger'>\The [user] misses [L] with \the [src]!</span>")
return 0
var/mob/living/carbon/human/H = L
var/obj/item/organ/external/affecting = H.get_organ(target_zone)
if (affecting)
if(!status)
L.visible_message("<span class='warning'>[L] has been prodded in the [affecting.name] with [src] by [user]. Luckily it was off.</span>")
return 1
target.visible_message("<span class='warning'>[target] has been prodded with [src] by [user]. Luckily it was off.</span>")
else
H.visible_message("<span class='danger'>[L] has been prodded in the [affecting.name] with [src] by [user]!</span>")
if(affecting)
target.visible_message("<span class='danger'>[target] has been prodded in the [affecting.name] with [src] by [user]!</span>")
else
if(!status)
L.visible_message("<span class='warning'>[L] has been prodded with [src] by [user]. Luckily it was off.</span>")
return 1
else
L.visible_message("<span class='danger'>[L] has been prodded with [src] by [user]!</span>")
target.visible_message("<span class='danger'>[target] has been prodded with [src] by [user]!</span>")
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
//stun effects
L.stun_effect_act(stun, agony, target_zone, src)
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
msg_admin_attack("[key_name(user)] stunned [key_name(L)] with the [src].")
if(status)
target.stun_effect_act(stun, agony, hit_zone, src)
msg_admin_attack("[key_name(user)] stunned [key_name(target)] with the [src].")
deductcharge(hitcost)
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(ishuman(target))
var/mob/living/carbon/human/H = target
H.forcesay(hit_appends)
return 1
/obj/item/weapon/melee/baton/emp_act(severity)
if(bcell)
bcell.emp_act(severity) //let's not duplicate code everywhere if we don't have to please.

View File

@@ -1,17 +1,9 @@
/* Weapons
* Contains:
* Banhammer
* Sword
* Classic Baton
*/
/*
* Banhammer
*/
/obj/item/weapon/banhammer/attack(mob/M as mob, mob/user as mob)
M << "<font color='red'><b> You have been banned FOR NO REISIN by [user]</b></font>"
user << "<font color='red'> You have <b>BANNED</b> [M]</font>"
/*
* Classic Baton
*/

View File

@@ -1,18 +1,3 @@
/obj/item/weapon/banhammer
desc = "banhammer"
name = "banhammer"
icon = 'icons/obj/items.dmi'
icon_state = "toyhammer"
slot_flags = SLOT_BELT
throwforce = 0
w_class = 2.0
throw_speed = 7
throw_range = 15
attack_verb = list("banned")
suicide_act(mob/user)
viewers(user) << "<span class='danger'>[user] is hitting \himself with the [src.name]! It looks like \he's trying to ban \himself from life.</span>"
return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS)
/obj/item/weapon/nullrod
name = "null rod"
@@ -68,27 +53,6 @@
user << "<span class='notice'>You hit the floor with the [src].</span>"
call(/obj/effect/rune/proc/revealrunes)(src)
/obj/item/weapon/sord
name = "\improper SORD"
desc = "This thing is so unspeakably shitty you are having a hard time even holding it."
icon_state = "sord"
item_state = "sord"
slot_flags = SLOT_BELT
force = 2
throwforce = 1
sharp = 1
edge = 1
w_class = 3
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
suicide_act(mob/user)
viewers(user) << "<span class='danger'>[user] is impaling \himself with the [src.name]! It looks like \he's trying to commit suicide.</span>"
return(BRUTELOSS)
/obj/item/weapon/sord/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
return ..()
/obj/item/weapon/energy_net
name = "energy net"
desc = "It's a net made of green energy."

View File

@@ -263,9 +263,6 @@
return 1
return 0
/obj/item/weapon/holo/esword/attack(target as mob, mob/user as mob)
..()
/obj/item/weapon/holo/esword/New()
item_color = pick("red","blue","green","purple")

View File

@@ -234,35 +234,14 @@
return
..()
/obj/item/weapon/reagent_containers/food/snacks/grown/attack(var/mob/living/carbon/M, var/mob/user, var/def_zone)
if(user == M)
return ..()
if(user.a_intent == I_HURT)
if(!istype(M))
return 0
if(!force || (flags & NOBLUDGEON))
return 0
/////////////////////////
user.lastattacked = M
M.lastattacker = user
if(!no_attack_log)
user.attack_log += "\[[time_stamp()]\]<font color='red'> Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
/////////////////////////
user.do_attack_animation(M)
M.attacked_with_item(src, user, def_zone)
/obj/item/weapon/reagent_containers/food/snacks/grown/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
..()
if(seed && seed.get_trait(TRAIT_STINGS))
if(!reagents || reagents.total_volume <= 0)
return
reagents.remove_any(rand(1,3))
seed.thrown_at(src,M)
seed.thrown_at(src, target)
sleep(-1)
if(!src)
return
@@ -272,12 +251,6 @@
user.drop_from_inventory(src)
qdel(src)
add_fingerprint(user)
return 1
else
..()
/obj/item/weapon/reagent_containers/food/snacks/grown/attack_self(mob/user as mob)
if(!seed)

View File

@@ -48,20 +48,6 @@
toxicity = 8
pest_kill_str = 7
/obj/item/weapon/material/minihoe // -- Numbers
name = "mini hoe"
desc = "It's used for removing weeds or scratching your back."
icon = 'icons/obj/weapons.dmi'
icon_state = "hoe"
item_state = "hoe"
flags = CONDUCT | NOBLUDGEON
force = 5.0
throwforce = 7.0
w_class = 2.0
matter = list(DEFAULT_WALL_MATERIAL = 50)
attack_verb = list("slashed", "sliced", "cut", "clawed")
// *************************************
// Weedkiller defines for hydroponics
// *************************************

View File

@@ -1,8 +1,8 @@
//Called when the mob is hit with an item in combat.
/mob/living/carbon/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
/mob/living/carbon/resolve_item_attack(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
if(check_attack_throat(I, user))
return
return null
..()
/mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)

View File

@@ -145,20 +145,18 @@ emp_act
O.emp_act(severity)
..()
/mob/living/carbon/human/attacked_with_item(obj/item/I, mob/living/user, var/target_zone)
if(!I || !user)
return
/mob/living/carbon/human/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
if(check_attack_throat(I, user))
return
return null
var/hit_zone = target_zone
if(user != src) // Attacking yourself can't miss
hit_zone = get_zone_with_miss_chance(target_zone, src)
if(user == src) // Attacking yourself can't miss
return target_zone
var/hit_zone = get_zone_with_miss_chance(target_zone, src)
if(!hit_zone)
visible_message("<span class='danger'>\The [user] misses [src] with \the [I]!</span>")
return
return null
if(check_shields(I.force, I, user, target_zone, "the [I.name]"))
return
@@ -166,9 +164,9 @@ emp_act
var/obj/item/organ/external/affecting = get_organ(hit_zone)
if (!affecting || (affecting.status & ORGAN_DESTROYED) || affecting.is_stump())
user << "<span class='danger'>They are missing that limb!</span>"
return
return null
I.apply_hit_effect(src, user, target_zone)
return hit_zone
/mob/living/carbon/human/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
var/obj/item/organ/external/affecting = get_organ(hit_zone)

View File

@@ -32,10 +32,11 @@ var/const/MAX_ACTIVE_TIME = 400
..()
/obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob)
/obj/item/clothing/mask/facehugger/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
..()
user.drop_from_inventory(src)
Attach(M)
if(hit_zone == "head")
Attach(target)
/obj/item/clothing/mask/facehugger/New()
if(config.aliens_allowed)

View File

@@ -111,9 +111,33 @@
O.emp_act(severity)
..()
/*
//Whereas attackby() handles the general case of using items on mobs, this handles the specific case of attacking a mob with an item as a weapon.
/mob/living/proc/attacked_with_item(obj/item/I, mob/living/user, var/target_zone)
I.apply_hit_effect(src, user, target_zone)
if(!istype(user))
return 0
/////////////////////////
user.lastattacked = M
M.lastattacker = user
if(!no_attack_log)
user.attack_log += "\[[time_stamp()]\]<font color='red'> Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
/////////////////////////
user.do_attack_animation(M)
var/hit_zone = resolve_hit_zone(I, user, target_zone)
if(hit_zone)
I.apply_hit_effect(src, user, hit_zone)
return 1
*/
/mob/living/proc/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
return target_zone
//Called when the mob is hit with an item in combat.
/mob/living/proc/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)

View File

@@ -131,7 +131,7 @@
return 0
else
attacked_with_item(O, user)
O.attack(src, user, user.zone_sel.selecting)
/mob/living/simple_animal/spiderbot/emag_act(var/remaining_charges, var/mob/user)
if (emagged)

View File

@@ -286,12 +286,12 @@
if(istype(O, /obj/item/weapon/material/knife) || istype(O, /obj/item/weapon/material/knife/butch))
harvest(user)
else
attacked_with_item(O, user, user.zone_sel.selecting)
/mob/living/simple_animal/attacked_with_item(obj/item/O, mob/living/user, var/target_zone)
if(!O.force)
visible_message("<span class='notice'>[user] gently taps [src] with \the [O].</span>")
return
else
O.attack(src, user, user.zone_sel.selecting)
/mob/living/simple_animal/hit_with_weapon(obj/item/O, mob/living/user, var/effective_force, var/hit_zone)
if(O.force > resistance)
var/damage = O.force
@@ -302,10 +302,9 @@
purge = 3
adjustBruteLoss(damage)
else
usr << "<span class='danger'>This weapon is ineffective, it does no damage.</span>"
user << "<span class='danger'>This weapon is ineffective, it does no damage.</span>"
visible_message("<span class='danger'>\The [src] has been attacked with \the [O] by [user].</span>")
user.do_attack_animation(src)
/mob/living/simple_animal/movement_delay()
var/tally = 0 //Incase I need to add stuff other than "speed" later

View File

@@ -25,11 +25,6 @@
/obj/item/weapon/reagent_containers/attack_self(mob/user as mob)
return
/obj/item/weapon/reagent_containers/attack(mob/M as mob, mob/user as mob, def_zone)
if(can_operate(M))//Checks if mob is lying down on table for surgery
if(do_surgery(M, user, src))
return
/obj/item/weapon/reagent_containers/afterattack(obj/target, mob/user, flag)
return