Merge pull request #6896 from Hubblenaut/dev

Context-based Combat Part 1
This commit is contained in:
PsiOmegaDelta
2014-11-23 19:13:52 +01:00
6 changed files with 216 additions and 20 deletions

View File

@@ -1204,7 +1204,15 @@ datum/mind
return (duration <= world.time - brigged_since)
//Antagonist role check
/mob/living/proc/check_special_role(role)
if(mind)
if(!role)
return mind.special_role
else
return (mind.special_role == role) ? 1 : 0
else
return 0
//Initialisation procs
/mob/living/proc/mind_initialize()

View File

@@ -708,6 +708,28 @@
number += 2
return number
/mob/living/carbon/human/proc/magboot_stomp(mob/living/carbon/human/H as mob, datum/organ/external/affecting)
visible_message("\red [src] raises one of \his magboots over [H]'s [affecting.display_name]...")
attack_move = 1
if(do_after(usr, 20))
if(src.canmove && !src.lying && src.Adjacent(H) && H.lying)
visible_message("\red <B>[src] stomps \his magboot down on [H]'s [affecting.display_name] with full force!</B>")
apply_damage(rand(20,30), BRUTE, affecting, run_armor_check(affecting, "melee"))
playsound(loc, 'sound/weapons/genhit3.ogg', 25, 1, -1)
attack_move = 0
src.attack_log += text("\[[time_stamp()]\] <font color='red'>Magboot-stomped [H.name] ([H.ckey])</font>")
H.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been magboot-stomped by [src.name] ([src.ckey])</font>")
msg_admin_attack("[key_name(src)] magboot-stomped [key_name(H)]")
return 1
return 0
/mob/living/carbon/human/get_combat_buff(var/damage)
if(check_special_role("Ninja") || check_special_role("Changeling"))
damage += 3 // We assume Ninjas and Changelings are slightly better in combat than the usual human
if(HULK in mutations)
damage *= 2 // Hulks do twice the damage
return damage * damage_multiplier
/mob/living/carbon/human/IsAdvancedToolUser(var/silent)
if(species.has_fine_manipulation)

View File

@@ -100,31 +100,114 @@
attack = H.species.secondary_unarmed
if(!attack.is_usable(H))
return 0
if(attack_move) return 0
H.attack_log += text("\[[time_stamp()]\] <font color='red'>[pick(attack.attack_verb)]ed [src.name] ([src.ckey])</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been [pick(attack.attack_verb)]ed by [H.name] ([M.ckey])</font>")
msg_admin_attack("[key_name(H)] [pick(attack.attack_verb)]ed [key_name(src)]")
var/damage = rand(1, 5)
var/block = 0
var/accurate = 0
var/target_zone = check_zone(H.zone_sel.selecting) // The zone that was targeted
var/hit_zone = target_zone // The zone that is actually hit
var/datum/organ/external/affecting = get_organ(hit_zone)
var/damage = rand(0, 5)//BS12 EDIT
if(!damage)
playsound(loc, attack.miss_sound, 25, 1, -1)
visible_message("\red <B>[H] tried to [pick(attack.attack_verb)] [src]!</B>")
// Check for magboot attack
if(src.lying && H.canmove && !H.lying && H.shoes && istype(H.shoes, /obj/item/clothing/shoes/magboots))
var/obj/item/clothing/shoes/magboots/mboots = H.shoes
if(mboots.magpulse)
return H.magboot_stomp(src, affecting)
switch(src.a_intent)
if("help")
// We didn't see this coming, so we get the full blow
damage = 5
accurate = 1
if("hurt", "grab")
// We're in a fighting stance, there's a chance we block
if(prob(20) && src.canmove && !(src==H))
block = 1
if (M.grabbed_by.len)
// Someone got a good grip on them, they won't be able to do much damage
damage = max(0, damage - 2)
if(src.grabbed_by.len || src.buckled || !src.canmove || src==H)
accurate = 1 // certain circumstances make it impossible for us to evade punches
// Process evasion and blocking
if(!accurate)
if(prob(80))
hit_zone = ran_zone(target_zone)
if(prob(15) && hit_zone != "chest") // Missed!
playsound(loc, attack.miss_sound, 25, 1, -1)
var/atk_verb = pick(attack.attack_verb)
visible_message("\red <B>[H] attempted to [atk_verb] [src]!</B>")
visible_message("\red [pick("The [pick(attack.attack_noun)] barely missed their [affecting.display_name]!", "[src] managed to dodge the [pick(attack.attack_noun)] narrowly!")]")
H.attack_log += text("\[[time_stamp()]\] <font color='red'>attempted to [atk_verb] [src.name] ([src.ckey]) (dodged)</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Dodged attack by [H.name] ([H.ckey])</font>")
msg_admin_attack("[key_name(H)] attempted to [pick(attack.attack_verb)] [key_name(src)] (dodged)")
return 0
if(block)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("\red <B>[H] went for [src]'s [affecting.display_name] but was blocked!</B>")
H.attack_log += text("\[[time_stamp()]\] <font color='red'>attempted to [pick(attack.attack_verb)] [src.name] ([src.ckey]) (blocked)</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Blocked attack by [H.name] ([H.ckey])</font>")
msg_admin_attack("[key_name(H)] attempted to [pick(attack.attack_verb)] [key_name(src)] (blocked)")
return 0
var/datum/organ/external/affecting = get_organ(ran_zone(H.zone_sel.selecting))
var/armor_block = run_armor_check(affecting, "melee")
// Handle the attack logs
attack.combat_log(H, src, hit_zone, damage)
if(HULK in H.mutations) damage += 5
H.attack_log += text("\[[time_stamp()]\] <font color='red'>[pick(attack.attack_verb)]ed [src.name] ([src.ckey])</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been [pick(attack.attack_verb)]ed by [H.name] ([H.ckey])</font>")
msg_admin_attack("[key_name(H)] [pick(attack.attack_verb)]ed [key_name(src)]")
playsound(loc, attack.attack_sound, 25, 1, -1)
// Apply possible buffs
damage = H.get_combat_buff(damage)
visible_message("\red <B>[H] [pick(attack.attack_verb)]ed [src]!</B>")
//Rearranged, so claws don't increase weaken chance.
if(damage >= 5 && prob(50))
visible_message("\red <B>[H] has weakened [src]!</B>")
var/armor_block = run_armor_check(affecting, "melee") // IMPORTANT: To run armor check after attack log as it produces a log itself
var/numb = rand(0, 100)
if(damage >= 5 && armor_block < 2 && !(src == H) && numb <= damage*5) // 25% standard chance
switch(hit_zone) // strong punches can have effects depending on where they hit
if("head")
// Induce blurriness
visible_message("\red [src] stares blankly for a few moments.", "\red You see stars.")
apply_effect(damage*2, EYE_BLUR, armor_block)
if("l_arm", "l_hand")
if (l_hand)
// Disarm left hand
visible_message("\red [src] [pick("dropped", "let go off")] \the [l_hand][pick("", " with a scream")]!")
drop_l_hand()
if("r_arm", "r_hand")
if (r_hand)
// Disarm right hand
visible_message("\red [src] [pick("dropped", "let go off")] \the [r_hand][pick("", " with a scream")]!")
drop_r_hand()
if("chest")
if(!src.lying)
visible_message("\red [pick("[src] was sent flying backward a few metres!", "[src] staggers back from the impact!")]")
step(src, get_dir(get_turf(M), get_turf(src)))
apply_effect(0.4*damage, WEAKEN, armor_block)
if("groin")
visible_message("\red [src] looks like \he is in pain!", (gender=="female")?"\red <i>Oh god that hurt!</i>":"\red <i>Oh no, not your[pick("testicles", "crown jewels", "clockweights", "family jewels", "marbles", "bean bags", "teabags", "sweetmeats", "goolies")]!</i>")
apply_effects(stutter=damage*2, agony=damage*3, blocked=armor_block)
if("l_leg", "l_foot", "r_leg", "r_foot")
if(!src.lying)
visible_message("\red [src] gives way slightly.")
apply_effect(damage*3, AGONY, armor_block)
else if(damage >= 5 && !(src == H) && numb+damage*5 >= 100 && armor_block < 2) // Chance to get the usual throwdown as well (25% standard chance)
if(!src.lying)
visible_message("\red [src] [pick("slumps", "falls", "drops")] down to the ground!")
else
visible_message("\red [src] has been weakened!")
apply_effect(3, WEAKEN, armor_block)
damage += attack.damage
// Sum up species damage bonus at the very end so xenos don't get buffed stun chances
damage += attack.damage // 3 for human/skrell, 5 for tajaran/unathi
playsound(H.loc, attack.attack_sound, 25, 1, -1)
// Finally, apply damage to target
apply_damage(damage, BRUTE, affecting, armor_block, sharp=attack.sharp, edge=attack.edge)
if("disarm")
@@ -218,4 +301,4 @@
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
updatehealth()
return 1
return 1

View File

@@ -24,6 +24,7 @@
var/b_skin = 0
var/size_multiplier = 1 //multiplier for the mob's icon size
var/damage_multiplier = 1 //multiplies melee combat damage
var/icon_update = 1 //whether icon updating shall take place
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
@@ -80,4 +81,6 @@
var/mob/remoteview_target = null
var/hand_blood_color
var/list/flavor_texts = list()
var/list/flavor_texts = list()
var/attack_move = 0 //Used in combat to check if user is performing an attack over several ticks

View File

@@ -496,6 +496,7 @@
//Species unarmed attacks
/datum/unarmed_attack
var/attack_verb = list("attack") // Empty hand hurt intent verb.
var/attack_noun = list("fist")
var/damage = 0 // Extra empty hand attack damage.
var/attack_sound = "punch"
var/miss_sound = 'sound/weapons/punchmiss.ogg'
@@ -518,6 +519,11 @@
return 0
/datum/unarmed_attack/proc/combat_log(mob/living/carbon/human/M as mob, mob/living/carbon/human/T as mob, zone, damage)
var/datum/organ/external/affecting = T.get_organ(zone)
M.visible_message("<span class='warning'>[M] [pick(attack_verb)] [T] in the [affecting.display_name]!</span>")
playsound(M.loc, attack_sound, 25, 1, -1)
/datum/unarmed_attack/bite
attack_verb = list("bite") // 'x has biteed y', needs work.
attack_sound = 'sound/weapons/bite.ogg'
@@ -541,20 +547,91 @@
/datum/unarmed_attack/punch
attack_verb = list("punch")
attack_noun = list("fist")
damage = 3
/datum/unarmed_attack/punch/combat_log(mob/living/carbon/human/M as mob, mob/living/carbon/human/T as mob, zone, damage)
var/skill = M.skills["combat"]
var/datum/organ/external/affecting = T.get_organ(zone)
var/organ = affecting.display_name
if(!skill) skill = 1
damage = Clamp(damage, 1, 5)
if(T == M)
M.visible_message("\red <B>[M] [pick(attack_verb)]ed \himself in the [organ]!</B>")
return 0
if(!T.lying)
switch(zone)
if("head")
// ----- HEAD ----- //
switch(damage)
if(1 to 2) M.visible_message("\red <B>[M] slapped [T] across \his cheek!</B>")
if(3 to 4) M.visible_message("\red <B>[M] struck [T] in the head[pick("", " with a closed fist")]!</B>")
if(5) M.visible_message("\red <B>[M] gave [T] a resounding slap to the face!</B>")
if("chest", "l_arm", "r_arm", "l_hand", "r_hand")
// -- UPPER BODY -- //
switch(damage)
if(1 to 2) M.visible_message("\red <B>[M] slapped [T]'s [organ]!</B>")
if(3 to 4) M.visible_message("\red <B>[M] [findtext(zone, "hand")?"[pick(attack_verb)]ed":pick("[pick(attack_verb)]ed", "shoulders")] [T] in \his [organ]!</B>")
if(5) M.visible_message("\red <B>[M] rammed \his [pick(attack_noun)] into [T]'s [organ]!</B>")
if("groin", "l_leg", "r_leg")
// -- LOWER BODY -- //
switch(damage)
if(1 to 2) M.visible_message("\red <B>[M] gave [T] a light kick to the [organ]!</B>")
if(3 to 4) M.visible_message("\red <B>[M] [pick("kicked", "kneed")] [T] in \his [organ]!</B>")
if(5) M.visible_message("\red <B>[M] landed a strong kick against [T]'s [organ]!</B>")
if("l_foot", "r_foot")
// ----- FEET ----- //
switch(damage)
if(1 to 4) M.visible_message("\red <B>[M] kicked [T] in \his [organ]!</B>")
if(5) M.visible_message("\red <B>[M] stomped down hard on [T]'s [organ]!")
else if (M.loc != T.loc)
M.visible_message("\red <B>[M] [pick("stomped down hard on", "kicked against", "gave a strong kick against", "rams their foot into")] [T]'s [organ]!</B>")
else
M.visible_message("\red <B>[M] [pick("punches", "throws a punch", "strikes", "slaps", "rams their [pick(attack_noun)] into")] [T]'s [organ]!</B>")
/datum/unarmed_attack/diona
attack_verb = list("lash", "bludgeon")
attack_noun = list("tendril")
damage = 5
/datum/unarmed_attack/claws
attack_verb = list("scratch", "claw")
attack_verb = list("scratch", "claw", "goug")
attack_noun = list("claws")
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
damage = 5
sharp = 1
edge = 1
/datum/unarmed_attack/claws/combat_log(mob/living/carbon/human/M as mob, mob/living/carbon/human/T as mob, zone, damage)
var/skill = M.skills["combat"]
var/datum/organ/external/affecting = T.get_organ(zone)
var/organ = affecting.display_name
if(!skill) skill = 1
damage = Clamp(damage, 1, 5)
if(T == M)
M.visible_message("\red <B>[M] [pick(attack_verb)]ed \himself in the [organ]!</B>")
return 0
switch(zone)
if("head")
// ----- HEAD ----- //
switch(damage)
if(1 to 2) M.visible_message("\red <B>[M] scratched [T] across \his cheek!</B>")
if(3 to 4) M.visible_message("\red <B>[M] [pick(attack_verb)]ed [pick("", "the side of")][T] [pick("head", "neck")][pick("", " with spread [pick(attack_noun)]")]!</B>")
if(5) M.visible_message("\red <B>[M] [pick(attack_verb)]ed [T] across \his face!</B>")
if("chest", "l_arm", "r_arm", "l_hand", "r_hand", "groin", "l_leg", "r_leg", "l_foot", "r_foot")
// ----- BODY ----- //
switch(damage)
if(1 to 2) M.visible_message("\red <B>[M] scratched [T]'s [organ]!</B>")
if(3 to 4) M.visible_message("\red <B>[M] [pick(attack_verb)]ed [pick("", "the side of")][T]'s [organ]!</B>")
if(5) M.visible_message("\red <B>[M] digs \his [pick(attack_noun)] deep into [T]'s [organ]!</B>")
/datum/unarmed_attack/claws/strong
attack_verb = list("slash")
damage = 10

View File

@@ -650,6 +650,9 @@ var/list/slot_equipment_priority = list( \
var/mob/pulled = AM
pulled.inertia_dir = 0
/mob/proc/get_combat_buff(var/damage)
return damage
/mob/proc/can_use_hands()
return