Ports weapons cleaving and reaching features from polaris (#3969)

-axes, chainswords and longswords can now cleave, hitting targets around the user, ported from polaris
-added support for melee weapons that can hit targets two titles away, as well ported from polaris
This commit is contained in:
Alberyk
2017-12-23 17:12:06 -02:00
committed by Erki
parent 5c78e4fc08
commit eb80d3ec68
8 changed files with 105 additions and 8 deletions

View File

@@ -125,7 +125,7 @@
// A is a turf or is on a turf, or in something on a turf (pen in a box); but not something in something on a turf (pen in a box in a backpack)
sdepth = A.storage_depth_turf()
if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1))
if(A.Adjacent(src)) // see adjacent.dm
if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach)) ) // see adjacent.dm
setMoveCooldown(5)
if(W)

View File

@@ -23,8 +23,13 @@ avoid code duplication. This includes items that may sometimes act as a standard
/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)
pre_attack(A, user)
add_fingerprint(user)
return A.attackby(src, user)

View File

@@ -77,6 +77,9 @@
var/charge_failure_message = " cannot be recharged."
var/cleaving = FALSE
var/reach = 1 // Length of tiles it can reach, 1 is adjacent.
/obj/item/Destroy()
if(ismob(loc))
var/mob/m = loc
@@ -731,3 +734,34 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
M.update_inv_pockets()
if (slot_s_store)
M.update_inv_s_store()
// Attacks mobs that are adjacent to the target and user.
/obj/item/proc/cleave(var/mob/living/user, var/mob/living/target)
if(cleaving)
return // We're busy.
cleaving = TRUE
var/hit_mobs = 0
for(var/mob/living/SA in orange(get_turf(target), 1))
if(SA.stat == DEAD) // Don't beat a dead horse.
continue
if(SA == user) // Don't hit ourselves. Simple mobs shouldn't be able to do this but that might change later to be able to hit all mob/living-s.
continue
if(SA == target) // We (presumably) already hit the target before cleave() was called. orange() should prevent this but just to be safe...
continue
if(!SA.Adjacent(user) || !SA.Adjacent(target)) // Cleaving only hits mobs near the target mob and user.
continue
if(resolve_attackby(SA, user)) // Hit them with the weapon. This won't cause recursive cleaving due to the cleaving variable being set to true.
hit_mobs++
if(hit_mobs)
to_chat(user, "<span class='danger'>You used \the [src] to attack [hit_mobs] other target\s!</span>")
cleaving = FALSE
// Used for non-adjacent melee attacks with specific weapons capable of reaching more than one tile.
// This uses changeling range string A* but for this purpose its also applicable.
/obj/item/proc/attack_can_reach(var/atom/us, var/atom/them, var/range)
if(us.Adjacent(them))
return TRUE // Already adjacent.
if(AStar(get_turf(us), get_turf(them), /turf/proc/AdjacentTurfsRanged, /turf/proc/Distance, max_nodes=25, max_node_depth=range))
return TRUE
return FALSE

View File

@@ -37,6 +37,7 @@
contained_sprite = 1
slot_flags = SLOT_BELT
attack_verb = list("attacked", "stabbed", "prodded", "poked", "lunged")
sharp = 0
/obj/item/weapon/material/sword/longsword
name = "longsword"
@@ -45,6 +46,11 @@
item_state = "claymore"
slot_flags = SLOT_BELT | SLOT_BACK
/obj/item/weapon/material/sword/longsword/pre_attack(var/mob/living/target, var/mob/living/user)
if(istype(target))
cleave(user, target)
..()
/obj/item/weapon/material/sword/trench
name = "trench knife"
desc = "A military knife used to slash and stab enemies in close quarters."
@@ -77,6 +83,11 @@
attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut")
applies_material_colour = 0
/obj/item/weapon/material/sword/axe/pre_attack(var/mob/living/target, var/mob/living/user)
if(istype(target))
cleave(user, target)
..()
/obj/item/weapon/material/sword/khopesh
name = "khopesh"
desc = "An ancient sword shapped like a sickle."

View File

@@ -160,7 +160,7 @@
if (ismob(loc))
var/mob/living/our_mob = loc
our_mob.remove_from_mob(src)
qdel(src)
/obj/item/weapon/material/twohanded/offhand/update_icon()
@@ -197,6 +197,11 @@
var/obj/effect/plant/P = A
P.die_off()
/obj/item/weapon/material/twohanded/fireaxe/pre_attack(var/mob/living/target, var/mob/living/user)
if(istype(target))
cleave(user, target)
..()
//spears, bay edition
/obj/item/weapon/material/twohanded/spear
icon_state = "spearglass0"
@@ -211,7 +216,7 @@
thrown_force_divisor = 1.5 // 20 when thrown with weight 15 (glass)
throw_speed = 3
edge = 1
sharp = 1
sharp = 0
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "poked", "jabbed", "torn", "gored")
default_material = "glass"

View File

@@ -47,11 +47,10 @@
slot_flags = initial(slot_flags)
user.regenerate_icons()
/*
/obj/item/weapon/melee/chainsword/suicide_act(mob/user)
viewers(user) << "<span class='danger'>[user] is slicing \himself apart with the [src.name]! It looks like \he's trying to commit suicide.</span>"
return (BRUTELOSS|OXYLOSS)
*/
/obj/item/weapon/melee/chainsword/pre_attack(var/mob/living/target, var/mob/living/user)
if(istype(target) && active)
cleave(user, target)
..()
//This is essentially a crowbar and a baseball bat in one.
/obj/item/weapon/melee/hammer

View File

@@ -342,3 +342,41 @@ var/const/enterloopsanity = 100
return
above.ChangeTurf(/turf/simulated/open)
/turf/proc/AdjacentTurfsRanged()
var/static/list/allowed = typecacheof(list(
/obj/structure/table,
/obj/structure/closet,
/obj/machinery/constructable_frame,
/obj/structure/target_stake,
/obj/structure/cable,
/obj/structure/disposalpipe,
/obj/machinery,
/mob
))
var/L[] = new()
for(var/turf/simulated/t in oview(src,1))
var/add = 1
if(t.density)
add = 0
if(add && LinkBlocked(src,t))
add = 0
if(add && TurfBlockedNonWindow(t))
add = 0
for(var/obj/O in t)
if(!O.density)
add = 1
break
if(istype(O, /obj/machinery/door))
//not sure why this doesn't fire on LinkBlocked()
add = 0
break
if(is_type_in_typecache(O, allowed))
add = 1
break
if(!add)
break
if(add)
L.Add(t)
return L