Skip to content

Commit

Permalink
CQC and Grab ports (#504)
Browse files Browse the repository at this point in the history
* CQC and Grab ports

* Moving outside of grab's range will break it
  • Loading branch information
EgorDinamit authored Jan 25, 2024
1 parent ce62ccc commit fe33025
Show file tree
Hide file tree
Showing 19 changed files with 245 additions and 120 deletions.
3 changes: 3 additions & 0 deletions code/datums/movement/mob.dm
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@

for(var/obj/item/grab/G in mob.grabbed_by)
if(G.assailant != mob && G.stop_move())
if(get_dist(G.assailant, mob) > 1 || G.assailant.z != mob.z)
qdel(G)
continue
if(mover == mob)
to_chat(mob, "<span class='notice'>You're stuck in a grab!</span>")
mob.ProcessGrabs()
Expand Down
7 changes: 4 additions & 3 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -537,9 +537,10 @@ var/list/global/slot_flags_enumeration = list(

/obj/item/proc/get_parry_chance(mob/user)
. = base_parry_chance
if(user)
if(base_parry_chance || user.skill_check(SKILL_COMBAT, SKILL_TRAINED))
. += 10 * (user.get_skill_value(SKILL_COMBAT) - SKILL_BASIC)
if (user.a_intent == I_HELP)
. = 0
if (.)
. += Clamp((user.get_skill_value(SKILL_COMBAT) * 10) - 20, 0, 75)

/obj/item/proc/on_disarm_attempt(mob/target, mob/living/attacker)
if(force < 1)
Expand Down
6 changes: 6 additions & 0 deletions code/modules/mob/grab/abomination/abom_aggressive.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@

/datum/grab/abomination/aggressive/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/target = G.affecting
var/mob/living/carbon/human/assailant = G.assailant

if(assailant.incapacitated(INCAPACITATION_ALL))
target.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
qdel(G)
return

if(G.target_zone in list(BP_L_HAND, BP_R_HAND))
target.drop_l_hand()
Expand Down
5 changes: 5 additions & 0 deletions code/modules/mob/grab/abomination/abom_kill.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
var/mob/living/carbon/human/user = G.assailant
var/mob/living/carbon/human/target = G.affecting

if(user.incapacitated(INCAPACITATION_ALL))
user.visible_message(SPAN_WARNING("[user] lets go of \his grab!"))
qdel(G)
return

target.Stun(3)

switch(user.a_intent)
Expand Down
93 changes: 62 additions & 31 deletions code/modules/mob/grab/grab_datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,22 @@
to_chat(G.assailant, "<span class='warning'>[string_process(G, fail_down)]</span>")
return

/datum/grab/proc/let_go(var/obj/item/grab/G)
if (G)
/datum/grab/proc/let_go(obj/item/grab/G)
if(G)
let_go_effect(G)
G.force_drop()

/datum/grab/proc/on_target_change(var/obj/item/grab/G, old_zone, new_zone)
/datum/grab/proc/on_target_change(obj/item/grab/G, old_zone, new_zone)
G.special_target_functional = check_special_target(G)
if(G.special_target_functional)
special_target_change(G, old_zone, new_zone)
special_target_effect(G)

/datum/grab/proc/process(var/obj/item/grab/G)
/datum/grab/proc/process(obj/item/grab/G)
special_target_effect(G)
process_effect(G)

/datum/grab/proc/throw_held(var/obj/item/grab/G)
/datum/grab/proc/throw_held(obj/item/grab/G)
if(G.assailant == G.affecting)
return

Expand All @@ -128,11 +128,12 @@

// check if we're grabbing with our inactive hand
G = thrower.get_inactive_hand()
if(!istype(G)) return
if(!istype(G))
return
qdel(G)
return

/datum/grab/proc/hit_with_grab(var/obj/item/grab/G)
/datum/grab/proc/hit_with_grab(obj/item/grab/G)
if(downgrade_on_action)
G.downgrade()

Expand Down Expand Up @@ -163,11 +164,11 @@
else
to_chat(G.assailant, "<span class='warning'>You must wait before you can do that.</span>")

/datum/grab/proc/make_log(var/obj/item/grab/G, var/action)
/datum/grab/proc/make_log(obj/item/grab/G, action)
admin_attack_log(G.assailant, G.affecting, "[action]s their victim", "was [action]ed", "used [action] on")


/datum/grab/proc/adjust_position(var/obj/item/grab/G)
/datum/grab/proc/adjust_position(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
var/mob/living/carbon/human/assailant = G.assailant
var/adir = get_dir(assailant, affecting)
Expand All @@ -193,15 +194,15 @@

affecting.reset_plane_and_layer()

/datum/grab/proc/reset_position(var/obj/item/grab/G)
/datum/grab/proc/reset_position(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting

if(!affecting.buckled)
animate(affecting, pixel_x = 0, pixel_y = 0, 4, 1, LINEAR_EASING)
affecting.reset_plane_and_layer()

// This is called whenever the assailant moves.
/datum/grab/proc/assailant_moved(var/obj/item/grab/G)
/datum/grab/proc/assailant_moved(obj/item/grab/G)
adjust_position(G)
moved_effect(G)
if(downgrade_on_move)
Expand All @@ -214,78 +215,107 @@
*/

// What happens when you upgrade from one grab state to the next.
/datum/grab/proc/upgrade_effect(var/obj/item/grab/G)
/datum/grab/proc/upgrade_effect(obj/item/grab/G)

// Conditions to see if upgrading is possible
/datum/grab/proc/can_upgrade(var/obj/item/grab/G)
/datum/grab/proc/can_upgrade(obj/item/grab/G)
return 1

// What happens when you downgrade from one grab state to the next.
/datum/grab/proc/downgrade_effect(var/obj/item/grab/G)
/datum/grab/proc/downgrade_effect(obj/item/grab/G)

// Conditions to see if downgrading is possible
/datum/grab/proc/can_downgrade(var/obj/item/grab/G)
/datum/grab/proc/can_downgrade(obj/item/grab/G)
return 1

// What happens when you let go of someone by either dropping the grab
// or by downgrading from the lowest grab state.
/datum/grab/proc/let_go_effect(var/obj/item/grab/G)
/datum/grab/proc/let_go_effect(obj/item/grab/G)

// What happens each tic when process is called.
/datum/grab/proc/process_effect(var/obj/item/grab/G)
/datum/grab/proc/process_effect(obj/item/grab/G)

// Handles special targeting like eyes and mouth being covered.
/datum/grab/proc/special_target_effect(var/obj/item/grab/G)
/datum/grab/proc/special_target_effect(obj/item/grab/G)

// Handles when they change targeted areas and something is supposed to happen.
/datum/grab/proc/special_target_change(var/obj/item/grab/G, var/diff_zone)
/datum/grab/proc/special_target_change(obj/item/grab/G, diff_zone)

// Checks if the special target works on the grabbed humanoid.
/datum/grab/proc/check_special_target(var/obj/item/grab/G)
/datum/grab/proc/check_special_target(obj/item/grab/G)

// What happens when you hit the grabbed person with the grab on help intent.
/datum/grab/proc/on_hit_help(var/obj/item/grab/G)
/datum/grab/proc/on_hit_help(obj/item/grab/G)
return 1

// What happens when you hit the grabbed person with the grab on disarm intent.
/datum/grab/proc/on_hit_disarm(var/obj/item/grab/G)
/datum/grab/proc/on_hit_disarm(obj/item/grab/G)
return 1

// What happens when you hit the grabbed person with the grab on grab intent.
/datum/grab/proc/on_hit_grab(var/obj/item/grab/G)
/datum/grab/proc/on_hit_grab(obj/item/grab/G)
return 1

// What happens when you hit the grabbed person with the grab on harm intent.
/datum/grab/proc/on_hit_harm(var/obj/item/grab/G)
/datum/grab/proc/on_hit_harm(obj/item/grab/G)
return 1

// What happens when you hit the grabbed person with an open hand and you want it
// to do some special snowflake action based on some other factor such as
// intent.
/datum/grab/proc/resolve_openhand_attack(var/obj/item/grab/G)
/datum/grab/proc/resolve_openhand_attack(obj/item/grab/G)
return 0

// Used when you want an effect to happen when the grab enters this state as an upgrade
/datum/grab/proc/enter_as_up(var/obj/item/grab/G)
/datum/grab/proc/enter_as_up(obj/item/grab/G)

/datum/grab/proc/item_attack(var/obj/item/grab/G, var/obj/item)
/datum/grab/proc/item_attack(obj/item/grab/G, obj/item)

/datum/grab/proc/resolve_item_attack(var/obj/item/grab/G, var/mob/living/carbon/human/user, var/obj/item/I, var/target_zone)
/datum/grab/proc/resolve_item_attack(obj/item/grab/G, mob/living/carbon/human/user, obj/item/I, target_zone)
return 0

/datum/grab/proc/handle_resist(var/obj/item/grab/G)
/datum/grab/proc/handle_resist(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
var/mob/living/carbon/human/assailant = G.assailant

if(assailant.incapacitated(INCAPACITATION_ALL))
let_go(G)
return

if(affecting.incapacitated(INCAPACITATION_KNOCKOUT | INCAPACITATION_STUNNED))
to_chat(G.affecting, "<span class='warning'>You can't resist in your current state!</span>")
to_chat(G.affecting, SPAN_WARNING("You can't resist in your current state!"))
var/skill_mod = Clamp(affecting.get_skill_difference(SKILL_COMBAT, assailant), -1, 1)
var/break_strength = breakability + size_difference(affecting, assailant) + skill_mod
var/shock = affecting.get_shock()
var/ashock = assailant.get_shock()

if(affecting.incapacitated(INCAPACITATION_ALL))
break_strength--
if(affecting.confused)
break_strength--
if(affecting.eye_blind)
break_strength--
if(affecting.eye_blurry)
break_strength--
if(shock >= 10)
break_strength--
if(shock >= 30)
break_strength--
if(shock >= 50)
break_strength--

if(assailant.confused)
break_strength++
if(assailant.eye_blind)
break_strength++
if(assailant.eye_blurry)
break_strength++
if(ashock >= 10)
break_strength++
if(ashock >= 30)
break_strength++
if(ashock >= 50)
break_strength++

if(break_strength < 1)
to_chat(G.affecting, "<span class='warning'>You try to break free but feel that unless something changes, you'll never escape!</span>")
Expand All @@ -304,4 +334,5 @@
/datum/grab/proc/size_difference(mob/A, mob/B)
return mob_size_difference(A.mob_size, B.mob_size)

/datum/grab/proc/moved_effect(var/obj/item/grab/G)
/datum/grab/proc/moved_effect(obj/item/grab/G)
return
12 changes: 9 additions & 3 deletions code/modules/mob/grab/nab/nab_aggressive.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@

break_chance_table = list(3, 18, 45, 100)

/datum/grab/nab/aggressive/upgrade_effect(var/obj/item/grab/G)
/datum/grab/nab/aggressive/upgrade_effect(obj/item/grab/G)
process_effect(G)

/datum/grab/nab/aggressive/process_effect(var/obj/item/grab/G)
/datum/grab/nab/aggressive/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
var/mob/living/carbon/human/assailant = G.assailant

affecting.Stun(3)
if(assailant.incapacitated(INCAPACITATION_ALL))
affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
qdel(G)
return

affecting.Stun(3)
11 changes: 8 additions & 3 deletions code/modules/mob/grab/nab/nab_kill.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,22 @@

break_chance_table = list(3, 10, 20, 100)

/datum/grab/nab/kill/upgrade_effect(var/obj/item/grab/G)
/datum/grab/nab/kill/upgrade_effect(obj/item/grab/G)
process_effect(G)

/datum/grab/nab/kill/process_effect(var/obj/item/grab/G)
/datum/grab/nab/kill/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/assailant = G.assailant
var/mob/living/carbon/human/affecting = G.affecting

if(assailant.incapacitated(INCAPACITATION_ALL))
affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
qdel(G)
return

affecting.Stun(3)

switch(assailant.a_intent)
if(I_GRAB)
on_hit_grab(G)
if(I_HURT)
on_hit_harm(G)
on_hit_harm(G)
2 changes: 1 addition & 1 deletion code/modules/mob/grab/nab/nab_passive.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@

icon_state = "reinforce1"

break_chance_table = list(50, 80, 100)
break_chance_table = list(50, 80, 100)
17 changes: 12 additions & 5 deletions code/modules/mob/grab/normal/norm_aggressive.dm
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,20 @@
same_tile = 0
can_throw = 1
force_danger = 1
breakability = 3
breakability = 4

icon_state = "reinforce1"

break_chance_table = list(5, 20, 40, 80, 100)
/datum/grab/normal/aggressive/process_effect(var/obj/item/grab/G)
break_chance_table = list(25, 30, 35, 40, 45, 50, 55)

/datum/grab/normal/aggressive/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
var/mob/living/carbon/human/assailant = G.assailant

if(assailant.incapacitated(INCAPACITATION_ALL))
affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
qdel(G)
return

if(G.target_zone in list(BP_L_HAND, BP_R_HAND))
affecting.drop_l_hand()
Expand All @@ -32,7 +39,7 @@
if(affecting.lying)
affecting.Weaken(4)

/datum/grab/normal/aggressive/can_upgrade(var/obj/item/grab/G)
/datum/grab/normal/aggressive/can_upgrade(obj/item/grab/G)
if(!(G.target_zone in list(BP_CHEST, BP_HEAD)))
to_chat(G.assailant, "<span class='warning'>You need to be grabbing their torso or head for this!</span>")
return FALSE
Expand All @@ -41,4 +48,4 @@
if((C.max_pressure_protection) && C.armor["melee"] > 20)
to_chat(G.assailant, "<span class='warning'>\The [C] is in the way!</span>")
return FALSE
return TRUE
return TRUE
14 changes: 10 additions & 4 deletions code/modules/mob/grab/normal/norm_kill.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@

icon_state = "kill1"

break_chance_table = list(5, 20, 40, 80, 100)
break_chance_table = list(3, 4, 5, 6, 7)

/datum/grab/normal/kill/process_effect(var/obj/item/grab/G)
/datum/grab/normal/kill/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
var/mob/living/carbon/human/assailant = G.assailant

if(assailant.incapacitated(INCAPACITATION_ALL))
affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
qdel(G)
return

affecting.drop_l_hand()
affecting.drop_r_hand()
Expand All @@ -33,6 +39,6 @@

affecting.adjustOxyLoss(1)

affecting.apply_effect(STUTTER, 5) //It will hamper your voice, being choked and all.
affecting.Weaken(5) //Should keep you down unless you get help.
affecting.apply_effect(STUTTER, 5) // It will hamper your voice, being choked and all.
affecting.Weaken(5) // Should keep you down unless you get help.
affecting.losebreath = max(affecting.losebreath + 2, 3)
Loading

0 comments on commit fe33025

Please sign in to comment.