This commit is contained in:
kevinz000
2020-03-14 21:14:56 -07:00
parent cda2ace252
commit 1a061a5d3e
6 changed files with 117 additions and 38 deletions

View File

@@ -66,12 +66,17 @@
//slowdown when in softcrit
#define SOFTCRIT_ADD_SLOWDOWN 6
//Attack types for checking shields/hit reactions
#define MELEE_ATTACK 1
#define UNARMED_ATTACK 2
#define PROJECTILE_ATTACK 3
#define THROWN_PROJECTILE_ATTACK 4
#define LEAP_ATTACK 5
/// Attack types for check_block()/run_block(). Flags, combinable.
/// Attack was melee, whether or not armed.
#define ATTACK_TYPE_MELEE (1<<0)
/// Attack was with a gun or something that should count as a gun (but not if a gun shouldn't count for a gun, crazy right?)
#define ATTACK_TYPE_PROJECTILE (1<<1)
/// Attack was unarmed.. this usually means hand to hand combat.
#define ATTACK_TYPE_UNARMED (1<<2)
/// Attack was a thrown atom hitting the victim.
#define ATTACK_TYPE_THROWN (1<<3)
/// Attack was a bodyslam/leap/tackle. See: Xenomorph leap tackles.
#define ATTACK_TYPE_TACKLE (1<<4)
//attack visual effects
#define ATTACK_EFFECT_PUNCH "punch"
@@ -203,3 +208,24 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
#define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting.
#define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default.
#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs.
/// Bitflags for check_block() and handle_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS.
/// Attack was not blocked
#define BLOCK_NONE NONE
/// Attack was blocked, do not do damage. THIS FLAG MUST BE THERE FOR DAMAGE/EFFECT PREVENTION!
#define BLOCK_SUCCESS (1<<1)
/// The below are for "metadata" on "how" the attack was blocked.
/// Attack was and should be reflected (NOTE: the SHOULD here is important, as it says "the thing blocking isn't handling the reflecting for you so do it yourself"!)
#define BLOCK_SHOULD_REFLECT (1<<2)
/// Attack was manually redirected (including reflected) by any means by the defender. For when YOU are handling the reflection, rather than the thing hitting you. (see sleeping carp)
#define BLOCK_REDIRECTED (1<<3)
/// Attack was blocked by something like a shield.
#define BLOCK_PHYSICAL_EXTERNAL (1<<4)
/// Attack was blocked by something worn on you.
#define BLOCK_PHYSICAL_INTERNAL (1<<5)
/// Attack should pass through. Like SHOULD_REFLECT but for.. well, passing through harmlessly.
#define BLOCK_SHOULD_PASSTHROUGH (1<<6)
/// Attack outright missed because the target dodged. Should usually be combined with SHOULD_PASSTHROUGH or something (see martial arts)
#define BLOCK_TARGET_DODGED (1<<7)

View File

@@ -88,7 +88,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/toolspeed = 1
var/block_chance = 0
var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom
var/reach = 1 //In tiles, how far this weapon can reach; 1 for adjacent, which is default
//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot.
@@ -359,13 +358,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, args)
if(prob(final_block_chance))
owner.visible_message("<span class='danger'>[owner] blocks [attack_text] with [src]!</span>")
return 1
return 0
/obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language)
return ITALICS | REDUCE_RANGE
@@ -458,9 +450,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
/obj/item/proc/ui_action_click(mob/user, actiontype)
attack_self(user)
/obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit
return 0
/obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user)
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to harm [M]!</span>")

View File

@@ -88,13 +88,11 @@
if(!combatmode)
totitemdamage *= 1.5
//CIT CHANGES END HERE
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected)
#warn Implement passthrough/reflect/blocktypes.
if((user != src) && (run_block(I, totitemdamage, "the [I]", MELEE_ATTACK, I.armour_penetration, user, impacting_zone) & BLOCK_SUCCESS))
return FALSE
var/obj/item/bodypart/affecting
if(user == src)
affecting = get_bodypart(check_zone(user.zone_selected)) //we're self-mutilating! yay!
else
affecting = get_bodypart(ran_zone(user.zone_selected))
var/obj/item/bodypart/affecting = get_bodypart(impacting_zone)
if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest)
affecting = bodyparts[1]
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)

View File

@@ -0,0 +1,80 @@
// This file has a weird name, but it's for anything related to the checks for shields, blocking, dodging, and similar "stop this attack before it actually impacts the target" as opposed to "defend once it has hit".
/*
/// Bitflags for check_block() and handle_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS.
/// Attack was not blocked
#define BLOCK_NONE NONE
/// Attack was blocked, do not do damage. THIS FLAG MUST BE THERE FOR DAMAGE/EFFECT PREVENTION!
#define BLOCK_SUCCESS (1<<1)
/// The below are for "metadata" on "how" the attack was blocked.
/// Attack was and should be reflected (NOTE: the SHOULD here is important, as it says "the thing blocking isn't handling the reflecting for you so do it yourself"!)
#define BLOCK_SHOULD_REFLECT (1<<2)
/// Attack was manually redirected (including reflected) by any means by the defender. For when YOU are handling the reflection, rather than the thing hitting you. (see sleeping carp)
#define BLOCK_REDIRECTED (1<<3)
/// Attack was blocked by something like a shield.
#define BLOCK_PHYSICAL_EXTERNAL (1<<4)
/// Attack was blocked by something worn on you.
#define BLOCK_PHYSICAL_INTERNAL (1<<5)
/// Attack should pass through. Like SHOULD_REFLECT but for.. well, passing through harmlessly.
#define BLOCK_SHOULD_PASSTHROUGH (1<<6)
/// Attack outright missed because the target dodged. Should usually be combined with SHOULD_PASSTHROUGH or something (see martial arts)
#define BLOCK_TARGET_DODGED (1<<7)
*/
///Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields. Wrapper for do_run_block(). The arguments on that means the same as for this.
/mob/living/proc/check_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone)
return do_run_block(FALSE, object, damage, attack_Text, attack_type, armour_penetration, attacker, def_zone)
/// Runs a block "sequence", effectively checking and then doing effects if necessary. Wrapper for do_run_block(). The arguments on that means the same as for this.
/mob/living/proc/run_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone)
return do_run_block(TRUE, object, damage, attack_Text, attack_type, armour_penetration, attacker, def_zone)
/** The actual proc for block checks. DO NOT USE THIS DIRECTLY UNLESS YOU HAVE VERY GOOD REASON TO. To reduce copypaste for differences between handling for real attacks and virtual checks.
* Automatically checks all held items for /obj/item/proc/do_run_block() with the same parameters.
* @params
* real_attack - If this attack is real
* object - Whatever /atom is actually hitting us, in essence. For example, projectile if gun, item if melee, structure/whatever if it's a thrown, etc.
* damage - The nominal damage this would do if it was to hit. Obviously doesn't take into effect explosions/magic/similar things.. unless you implement it to raise the value.
* attack_text - The text that this attack should show, in the context of something like "[src] blocks [attack_text]!"
* attack_type - See __DEFINES/combat.dm - Attack types, to distinguish between, for example, someone throwing an item at us vs bashing us with it.
* armour_penetration - 0-100 value of how effectively armor penetrating the attack should be.
* attacker - Set to the mob attacking IF KNOWN. Do not expect this to always be set!
* def_zone - The zone this'll impact.
*/
/mob/living/proc/do_run_block(real_attack = TRUE, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone)
/mob/living/proc/_check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
var/block_chance_modifier = round(damage / -3)
for(var/obj/item/I in held_items)
if(!istype(I, /obj/item/clothing))
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return TRUE
return FALSE
/mob/living/proc/_check_reflect(def_zone) //Reflection checks for anything in your hands, based on the reflection chance of the object(s)
for(var/obj/item/I in held_items)
if(I.IsReflect(def_zone))
return TRUE
return FALSE
/obj/item
var/hit_reaction_chance = 0 //The base chance at which hit_reaction() will be called.
/obj/item/
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, args)
if(prob(final_block_chance))
owner.visible_message("<span class='danger'>[owner] blocks [attack_text] with [src]!</span>")
return 1
return 0
/obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit
return 0
var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom

View File

@@ -36,21 +36,6 @@
/mob/living/proc/on_hit(obj/item/projectile/P)
return BULLET_ACT_HIT
/mob/living/proc/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
var/block_chance_modifier = round(damage / -3)
for(var/obj/item/I in held_items)
if(!istype(I, /obj/item/clothing))
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return TRUE
return FALSE
/mob/living/proc/check_reflect(def_zone) //Reflection checks for anything in your hands, based on the reflection chance of the object(s)
for(var/obj/item/I in held_items)
if(I.IsReflect(def_zone))
return TRUE
return FALSE
/mob/living/proc/reflect_bullet_check(obj/item/projectile/P, def_zone)
if(P.is_reflectable && check_reflect(def_zone)) // Checks if you've passed a reflection% check
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \

View File

@@ -2186,6 +2186,7 @@
#include "code\modules\mob\living\emote.dm"
#include "code\modules\mob\living\life.dm"
#include "code\modules\mob\living\living.dm"
#include "code\modules\mob\living\living_block.dm"
#include "code\modules\mob\living\living_defense.dm"
#include "code\modules\mob\living\living_defines.dm"
#include "code\modules\mob\living\living_mobility.dm"