implementations

This commit is contained in:
kevinz000
2020-05-24 14:56:01 -07:00
parent 9c08df761f
commit 95c6c7345c
10 changed files with 73 additions and 42 deletions
@@ -87,8 +87,10 @@
totitemdamage *= 1.5
//CIT CHANGES END HERE
var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected)
if((user != src) && (run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone) & BLOCK_SUCCESS))
var/list/block_return = list()
if((user != src) && (run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, return_list = block_return) & BLOCK_SUCCESS))
return FALSE
totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return)
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]
+14 -11
View File
@@ -1668,10 +1668,22 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
disarm(M, H, attacker_style)
/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 0.5
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
totitemdamage *= 0.5
if(istype(H))
if(!(H.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 1.5
//CIT CHANGES END HERE
// Allows you to put in item-specific reactions based on species
if(user != H)
if(H.run_block(I, I.force, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone) & BLOCK_SUCCESS)
var/list/block_return = list()
if(H.run_block(I, I.force, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone, return_list = block_return) & BLOCK_SUCCESS)
return 0
totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return)
if(H.check_martial_melee_block())
H.visible_message("<span class='warning'>[H] blocks [I]!</span>")
return 0
@@ -1686,16 +1698,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/armor_block = H.run_armor_check(affecting, "melee", "<span class='notice'>Your armor has protected your [hit_area].</span>", "<span class='notice'>Your armor has softened a hit to your [hit_area].</span>",I.armour_penetration)
armor_block = min(90,armor_block) //cap damage reduction at 90%
var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 0.5
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
totitemdamage *= 0.5
if(istype(H))
if(!(H.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 1.5
//CIT CHANGES END HERE
var/weakness = H.check_weakness(I, user)
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H) //CIT CHANGE - replaces I.force with totitemdamage
+12
View File
@@ -93,3 +93,15 @@
SEND_SIGNAL(src, COMSIG_ITEM_CHECK_BLOCK, owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
var/existing = block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE]
block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE] = max(existing || 0, final_block_chance)
// HELPER PROCS
/**
* Considers a block return_list and calculates damage to use from that.
*/
/proc/block_calculate_resultant_damage(damage, list/block_return)
if(!isnull(block_return[BLOCK_RETURN_SET_DAMAGE_TO)) // higher priority
return block_return[BLOCK_RETURN_SET_DAMAGE_TO]
else if(!isnull(block_return[BLOCK_RETURN_MITIGATION_PERCENT]))
return damage * ((100 - block_return[BLOCK_RETURN_MITIGATION_PERCENT]) * 0.01)
return damage
@@ -108,7 +108,6 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/parry_stamina_cost = 5
#warn implement
/// Parry windup duration in deciseconds. 0 to this is windup, afterwards is main stage.
var/parry_time_windup = 2
/// Parry spindown duration in deciseconds. main stage end to this is the spindown stage, afterwards the parry fully ends.
@@ -170,17 +169,17 @@ GLOBAL_LIST_EMPTY(block_parry_data)
//Stubs.
/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency)
/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time)
/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency)
/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time)
/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency)
/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time)
/obj/item/proc/active_parry_reflex_counter(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list)
/obj/item/proc/active_parry_reflex_counter(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, parry_efficiency)
/mob/living/proc/active_parry_reflex_counter(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list)
/mob/living/proc/active_parry_reflex_counter(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, parry_efficiency)
/datum/martial_art/proc/active_parry_reflex_counter(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list)
/datum/martial_art/proc/active_parry_reflex_counter(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, parry_efficiency)
/**
* Gets the stage of our parry sequence we're currently in.
@@ -203,6 +202,8 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/**
* Gets the percentage efficiency of our parry.
*
* Returns a percentage in normal 0 to 100 scale, but not clamped to just 0 to 100.
*/
/mob/living/proc/get_parry_efficiency(attack_type)
var/datum/block_parry_data/data = get_parry_data()
@@ -236,16 +237,18 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/efficiency = get_parry_efficiency(attack_type)
switch(parrying)
if(ITEM_PARRY)
. = active_parry_item.on_active_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency)
. = active_parry_item.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, get_parry_time())
if(UNARMED_PARRY)
. = on_active_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency)
. = on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, get_parry_time())
if(MARTIAL_PARRY)
. = mind.martial_art.on_active_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency)
if(efficiency <= 0)
. = mind.martial_art.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, get_parry_time())
if(!isnull(return_list[BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY])) // one of our procs overrode
efficiency = return_list[BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY]
if(efficiency <= 0) // Do not allow automatically handled/standardized parries that increase damage for now.
return
. |= BLOCK_SHOULD_PARTIAL_MITIGATE
var/current = return_list[BLOCK_RETURN_MITIGATION_PERCENT] || 0
return_list[BLOCK_RETURN_MITIGATION_PERCENT] = 100 - (clamp(100 - current, 0, 100) * clamp(1 - (efficiency / 100), 0, 1))
if(isnull(return_list[BLOCK_RETURN_MITIGATION_PERCENT])) // if one of the on_active_parry procs overrode. We don't have to worry about interference since parries are the first thing checked in the [do_run_block()] sequence.
return_list[BLOCK_RETURN_MITIGATION_PERCENT] = clamp(efficiency, 0, 100) // do not allow > 100% or < 0% for now.
var/list/effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency)
if(data.parry_default_handle_feedback)
handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text)
@@ -269,11 +272,11 @@ GLOBAL_LIST_EMPTY(block_parry_data)
if(PARRY_COUNTERATTACK_PROC)
switch(parrying)
if(ITEM_PARRY)
active_parry_item.active_parry_reflex_counter(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)
active_parry_item.active_parry_reflex_counter(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, parry_efficiency)
if(UNARMED_PARRY)
active_parry_reflex_counter(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)
active_parry_reflex_counter(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, parry_efficiency)
if(MARTIAL_PARRY)
mind.martial_art.active_parry_reflex_counter(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)
mind.martial_art.active_parry_reflex_counter(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, parry_efficiency)
if(PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN)
switch(parrying)
if(ITEM_PARRY)
+11 -4
View File
@@ -66,6 +66,7 @@
CRASH("Invalid rediretion mode [redirection_mode]")
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
var/totaldamage = P.damage
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
var/list/returnlist = list()
var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist)
@@ -76,9 +77,10 @@
if(returned & BLOCK_SUCCESS)
P.on_hit(src, 100, def_zone)
return BULLET_ACT_BLOCK
totaldamage = block_calculate_resultant_damage(totaldamage, returnlist)
var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
if(!P.nodamage)
apply_damage(P.damage, P.damage_type, def_zone, armor)
apply_damage(totaldamage, P.damage_type, def_zone, armor)
if(P.dismemberment)
check_projectile_dismemberment(P, def_zone)
return P.on_hit(src, armor) ? BULLET_ACT_HIT : BULLET_ACT_BLOCK
@@ -111,10 +113,13 @@
I = AM
throwpower = I.throwforce
var/impacting_zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
if(run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone) & BLOCK_SUCCESS)
var/list/block_return = list()
var/total_damage = I.throwforce
if(run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone, return_list = block_return) & BLOCK_SUCCESS)
hitpush = FALSE
skipcatch = TRUE
blocked = TRUE
total_damage = block_calculate_resultant_damage(total_damage, block_return)
else if(I && I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && can_embed(I, src) && prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE) && (!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) || incapacitated() || get_active_held_item()))
embed_item(I)
hitpush = FALSE
@@ -143,7 +148,7 @@
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
"<span class='userdanger'>[src] has been hit by [I].</span>")
var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration)
apply_damage(I.throwforce, dtype, impacting_zone, armor)
apply_damage(total_damage, dtype, impacting_zone, armor)
if(I.thrownby)
log_combat(I.thrownby, src, "threw and hit", I)
else
@@ -303,8 +308,10 @@
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(20, 40)
if(run_block(M, damage, "the [M.name]", ATTACK_TYPE_MELEE, null, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS)
var/list/block_return = list()
if(run_block(M, damage, "the [M.name]", ATTACK_TYPE_MELEE, null, M, check_zone(M.zone_selected), return_list = block_return) & BLOCK_SUCCESS)
return FALSE
damage = block_calculate_resultant_damage(damage, block_return)
if (stat != DEAD)
log_combat(M, src, "attacked")
@@ -113,6 +113,7 @@
flash_act(affect_silicon = 1)
/mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone)
var/totaldamage = P.damage
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
var/list/returnlist = list()
var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist)
@@ -123,17 +124,14 @@
if(returned & BLOCK_SUCCESS)
P.on_hit(src, 100, def_zone)
return BULLET_ACT_BLOCK
totaldamage = block_calculate_resultant_damage(totaldamage, returnlist)
if((P.damage_type == BRUTE || P.damage_type == BURN))
adjustBruteLoss(P.damage)
if(prob(P.damage*1.5))
for(var/mob/living/M in buckled_mobs)
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src]!</span>")
unbuckle_mob(M)
M.DefaultCombatKnockdown(40)
if(P.stun || P.knockdown)
adjustBruteLoss(totaldamage)
if((P.damage >= 10) || P.stun || P.knockdown || (P.stamina >= 20))
for(var/mob/living/M in buckled_mobs)
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src]!</span>")
unbuckle_mob(M)
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [P]!</span>")
M.DefaultCombatKnockdown(40)
P.on_hit(src)
return BULLET_ACT_HIT