Merge pull request #11820 from kevinz000/shield_bashing

Shield bashing
This commit is contained in:
Lin
2020-04-17 20:45:40 +00:00
committed by GitHub
7 changed files with 177 additions and 10 deletions
+18
View File
@@ -0,0 +1,18 @@
/// Transparent, let beams pass
#define SHIELD_TRANSPARENT (1<<0)
/// Can shield bash
#define SHIELD_CAN_BASH (1<<1)
/// Shield bash knockdown on wall hit
#define SHIELD_BASH_WALL_KNOCKDOWN (1<<2)
/// Shield bash always knockdown
#define SHIELD_BASH_ALWAYS_KNOCKDOWN (1<<3)
/// Shield bash disarm on wall hit
#define SHIELD_BASH_WALL_DISARM (1<<4)
/// Shield bash always disarm
#define SHIELD_BASH_ALWAYS_DISARM (1<<5)
/// You can shieldbash target someone on the ground for ground slam
#define SHIELD_BASH_GROUND_SLAM (1<<6)
/// Shield bashing someone on the ground will disarm
#define SHIELD_BASH_GROUND_SLAM_DISARM (1<<7)
#define SHIELD_FLAGS_DEFAULT (SHIELD_CAN_BASH | SHIELD_BASH_WALL_KNOCKDOWN | SHIELD_BASH_WALL_DISARM | SHIELD_BASH_GROUND_SLAM)
+10
View File
@@ -250,6 +250,16 @@ GLOBAL_LIST_INIT(bitfields, list(
"COMBAT_FLAG_INTENTIONALLY_RESTING" = COMBAT_FLAG_INTENTIONALLY_RESTING,
"COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST
),
"shield_flags" = list(
"SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT,
"SHIELD_CAN_BASH" = SHIELD_CAN_BASH,
"SHIELD_BASH_WALL_KNOCKDOWN" = SHIELD_BASH_WALL_KNOCKDOWN,
"SHIELD_BASH_ALWAYS_KNOCKDOWN" = SHIELD_BASH_ALWAYS_KNOCKDOWN,
"SHIELD_BASH_WALL_DISARM" = SHIELD_BASH_WALL_DISARM,
"SHIELD_BASH_ALWAYS_DISARM" = SHIELD_BASH_ALWAYS_DISARM,
"SHIELD_BASH_GROUND_SLAM" = SHIELD_BASH_GROUND_SLAM,
"SHIELD_BASH_GROUND_SLAM_DISARM" = SHIELD_BASH_GROUND_SLAM_DISARM
),
"storage_flags" = list(
"STORAGE_LIMIT_MAX_ITEMS" = STORAGE_LIMIT_MAX_ITEMS,
"STORAGE_LIMIT_MAX_W_CLASS" = STORAGE_LIMIT_MAX_W_CLASS,
+147 -7
View File
@@ -3,11 +3,151 @@
icon = 'icons/obj/items_and_weapons.dmi'
block_chance = 50
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70)
var/transparent = FALSE // makes beam projectiles pass through the shield
/// Shield flags
var/shield_flags = SHIELD_FLAGS_DEFAULT
/// Last shieldbash world.time
var/last_shieldbash = 0
/// Shieldbashing cooldown
var/shieldbash_cooldown = 5 SECONDS
/// Shieldbashing stamina cost
var/shieldbash_stamcost = 7.5
/// Shieldbashing knockback
var/shieldbash_knockback = 2
/// Shield bashing brute damage
var/shieldbash_brutedamage = 5
/// Shield bashing stamina damage
var/shieldbash_stamdmg = 15
/// Shield bashing stagger duration
var/shieldbash_stagger_duration = 3.5 SECONDS
/// Shield bashing push distance
var/shieldbash_push_distance = 1
/obj/item/shield/examine(mob/user)
. = ..()
if(shield_flags & SHIELD_CAN_BASH)
. += "<span class='notice'>Right click on combat mode attack with [src] to shield bash!</span>"
if(shield_flags & SHIELD_BASH_GROUND_SLAM)
. += "<span class='notice'>Directly rightclicking on a downed target with [src] will slam them instead of bashing.</span>"
/obj/item/shield/proc/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance)
return TRUE
/obj/item/shield/alt_pre_attack(atom/A, mob/living/user, params)
user_shieldbash(user, A, user.a_intent != INTENT_HARM)
return TRUE
/obj/item/shield/altafterattack(atom/target, mob/user, proximity_flag, click_parameters)
user_shieldbash(user, target, user.a_intent != INTENT_HARM)
return TRUE
/obj/item/shield/proc/do_shieldbash_effect(mob/living/user, dir, harmful)
var/px = 0
var/py = 0
switch(dir)
if(NORTH)
py = 12
if(SOUTH)
py = -12
if(EAST)
px = 12
if(WEST)
px = -12
var/oldpx = user.pixel_x
var/oldpy = user.pixel_y
animate(user, pixel_x = px, pixel_y = py, time = 3, easing = SINE_EASING | EASE_OUT, flags = ANIMATION_END_NOW)
animate(user, pixel_x = oldpx, pixel_y = oldpy, time = 3)
user.visible_message("<span class='warning'>[user] [harmful? "charges forwards with" : "sweeps"] [src]!</span>")
var/obj/effect/temp_visual/dir_setting/shield_bash/effect = new(user.loc, dir)
animate(effect, alpha = 0, pixel_x = px + 4, pixel_y = py + 4, time = 3)
/obj/item/shield/proc/bash_target(mob/living/user, mob/living/target, bashdir, harmful)
if(!(target.status_flags & CANKNOCKDOWN) || HAS_TRAIT(src, TRAIT_STUNIMMUNE)) // should probably add stun absorption check at some point I guess..
// unified stun absorption system when lol
target.visible_message("<span class='warning'>[user] slams [target] with [src], but [target] doesn't falter!</span>", "<span class='userdanger'>[user] slams you with [src], but it barely fazes you!</span>")
return FALSE
var/target_downed = !CHECK_MOBILITY(target, MOBILITY_STAND)
var/wallhit = FALSE
var/turf/target_current_turf = get_turf(target)
if(harmful)
target.visible_message("<span class='warning'>[target_downed? "[user] slams [src] into [target]" : "[user] bashes [target] with [src]"]!</span>",
"<span class='warning'>[target_downed? "[user] slams [src] into you" : "[user] bashes you with [src]"]!</span>")
else
target.visible_message("<span class='warning'>[user] shoves [target] with [src]!</span>",
"<span class='warning'>[user] shoves you with [src]!</span>")
for(var/i in 1 to harmful? shieldbash_knockback : shieldbash_push_distance)
var/turf/new_turf = get_step(target, bashdir)
var/mob/living/carbon/human/H = locate() in new_turf
if(H && harmful)
H.visible_message("<span class='warning'>[target] is sent crashing into [H]!</span>",
"<span class='userdanger'>[target] is sent crashing into you!</span>")
H.KnockToFloor()
wallhit = TRUE
break
else
step(target, bashdir)
if(get_turf(target) == target_current_turf)
wallhit = TRUE
break
else
target_current_turf = get_turf(target)
var/disarming = (target_downed && (shield_flags & SHIELD_BASH_GROUND_SLAM_DISARM)) || (shield_flags & SHIELD_BASH_ALWAYS_DISARM) || (wallhit && (shield_flags & SHIELD_BASH_WALL_DISARM))
var/knockdown = !target_downed && ((shield_flags & SHIELD_BASH_ALWAYS_KNOCKDOWN) || (wallhit && (shield_flags & SHIELD_BASH_WALL_KNOCKDOWN)))
if(shieldbash_stagger_duration || knockdown)
target.visible_message("<span class='warning'>[target] is knocked [knockdown? "to the floor" : "off balanace"]!</span>",
"<span class='userdanger'>You are knocked [knockdown? "to the floor" : "off balanace"]!</span>")
if(knockdown)
target.KnockToFloor(disarming)
else if(disarming)
target.drop_all_held_items()
if(harmful)
target.apply_damage(shieldbash_stamdmg, STAMINA, BODY_ZONE_CHEST)
target.apply_damage(shieldbash_brutedamage, BRUTE, BODY_ZONE_CHEST)
target.Stagger(shieldbash_stagger_duration)
return TRUE
/obj/item/shield/proc/user_shieldbash(mob/living/user, atom/target, harmful)
if(!(shield_flags & SHIELD_CAN_BASH))
to_chat(user, "<span class='warning'>[src] can't be used to shield bash!</span>")
return FALSE
if(world.time < last_shieldbash + shieldbash_cooldown)
to_chat(user, "<span class='warning'>You can't bash with [src] again so soon!</span>")
return FALSE
if(isliving(target)) //GROUND SLAAAM
if(!(shield_flags & SHIELD_BASH_GROUND_SLAM))
to_chat(user, "<span class='warning'>You can't ground slam with [src]!</span>")
return FALSE
bash_target(user, target, NONE, harmful)
user.do_attack_animation(target, used_item = src)
playsound(src, harmful? "swing_hit" : 'sound/weapons/thudswoosh.ogg', 75, 1)
last_shieldbash = world.time
user.adjustStaminaLossBuffered(shieldbash_stamcost)
return 1
// Directional sweep!
last_shieldbash = world.time
user.adjustStaminaLossBuffered(shieldbash_stamcost)
// Since we are in combat mode, we can probably safely use the user's dir instead of getting their mouse pointing cardinal dir.
var/bashdir = user.dir
do_shieldbash_effect(user, bashdir, harmful)
var/list/checking = list(get_step(user, user.dir), get_step(user, turn(user.dir, 45)), get_step(user, turn(user.dir, -45)))
var/list/victims = list()
for(var/i in checking)
var/turf/T = i
for(var/mob/living/L in T.contents)
victims += L
if(length(victims))
for(var/i in victims)
bash_target(user, i, bashdir, harmful)
playsound(src, harmful? "swing_hit" : 'sound/weapons/thudswoosh.ogg', 75, 1)
else
playsound(src, 'sound/weapons/punchmiss.ogg', 75, 1)
return length(victims)
/obj/effect/temp_visual/dir_setting/shield_bash
icon = 'icons/effects/96x96_attack_sweep.dmi'
icon_state = "shield_bash"
duration = 3
/obj/item/shield/riot
name = "riot shield"
desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder."
@@ -23,13 +163,13 @@
custom_materials = list(/datum/material/glass=7500, /datum/material/iron=1000)
attack_verb = list("shoved", "bashed")
var/cooldown = 0 //shield bash cooldown. based on world.time
transparent = TRUE
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_TRANSPARENT
max_integrity = 75
/obj/item/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(ismovableatom(object))
var/atom/movable/AM = object
if(transparent && (AM.pass_flags & PASSGLASS))
if(CHECK_BITFIELD(shield_flags, SHIELD_TRANSPARENT) && (AM.pass_flags & PASSGLASS))
return BLOCK_NONE
if(attack_type & ATTACK_TYPE_THROWN)
final_block_chance += 30
@@ -88,7 +228,7 @@
item_state = "roman_shield"
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
transparent = FALSE
shield_flags = SHIELD_FLAGS_DEFAULT
max_integrity = 65
/obj/item/shield/riot/roman/fake
@@ -111,7 +251,7 @@
custom_materials = null
resistance_flags = FLAMMABLE
block_chance = 30
transparent = FALSE
shield_flags = SHIELD_FLAGS_DEFAULT
max_integrity = 55
/obj/item/shield/riot/buckler/shatter(mob/living/carbon/human/owner)
@@ -238,7 +378,7 @@
throwforce = 15 //Massive pice of metal
w_class = WEIGHT_CLASS_HUGE
item_flags = SLOWS_WHILE_IN_HAND
transparent = FALSE
shield_flags = SHIELD_FLAGS_DEFAULT
/obj/item/shield/riot/implant
name = "riot tower shield"
@@ -248,7 +388,7 @@
icon = 'icons/obj/items_and_weapons.dmi'
block_chance = 30 //May be big but hard to move around to block.
slowdown = 1
transparent = FALSE
shield_flags = SHIELD_FLAGS_DEFAULT
item_flags = SLOWS_WHILE_IN_HAND
/obj/item/shield/riot/implant/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
-2
View File
@@ -206,8 +206,6 @@
newtonian_move(get_dir(target, src))
thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, move_force, random_turn)
/mob/living/carbon/restrained(ignore_grab)
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
@@ -103,7 +103,7 @@ Difficulty: Hard
if(.)
SSshuttle.shuttle_purchase_requirements_met |= "bubblegum"
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A)
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(charging)
return
..()
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

+1
View File
@@ -123,6 +123,7 @@
#include "code\__DEFINES\dcs\flags.dm"
#include "code\__DEFINES\dcs\helpers.dm"
#include "code\__DEFINES\dcs\signals.dm"
#include "code\__DEFINES\flags\shields.dm"
#include "code\__HELPERS\_cit_helpers.dm"
#include "code\__HELPERS\_lists.dm"
#include "code\__HELPERS\_logging.dm"