/
sleeping_carp.dm
343 lines (305 loc) · 15.8 KB
/
sleeping_carp.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
#define STRONG_PUNCH_COMBO "HH"
#define LAUNCH_KICK_COMBO "HD"
#define DROP_KICK_COMBO "DD"
/datum/martial_art/the_sleeping_carp
name = "The Sleeping Carp"
id = MARTIALART_SLEEPINGCARP
allow_temp_override = FALSE
help_verb = /mob/living/proc/sleeping_carp_help
display_combos = TRUE
/// List of traits applied to users of this martial art.
var/list/scarp_traits = list(TRAIT_NOGUNS, TRAIT_HARDLY_WOUNDED, TRAIT_NODISMEMBER, TRAIT_HEAVY_SLEEPER)
/datum/martial_art/the_sleeping_carp/on_teach(mob/living/new_holder)
. = ..()
new_holder.add_traits(scarp_traits, SLEEPING_CARP_TRAIT)
RegisterSignal(new_holder, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby))
RegisterSignal(new_holder, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(hit_by_projectile))
new_holder.faction |= FACTION_CARP //:D
/datum/martial_art/the_sleeping_carp/on_remove(mob/living/remove_from)
remove_from.remove_traits(scarp_traits, SLEEPING_CARP_TRAIT)
UnregisterSignal(remove_from, list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_PRE_BULLET_ACT))
remove_from.faction -= FACTION_CARP //:(
return ..()
/datum/martial_art/the_sleeping_carp/proc/check_streak(mob/living/attacker, mob/living/defender)
if(findtext(streak,STRONG_PUNCH_COMBO))
reset_streak()
return strongPunch(attacker, defender)
if(findtext(streak,LAUNCH_KICK_COMBO))
reset_streak()
return launchKick(attacker, defender)
if(findtext(streak,DROP_KICK_COMBO))
reset_streak()
return dropKick(attacker, defender)
return FALSE
///Gnashing Teeth: Harm Harm, consistent 20 force punch on every second harm punch
/datum/martial_art/the_sleeping_carp/proc/strongPunch(mob/living/attacker, mob/living/defender)
// this var is so that the strong punch is always aiming for the body part the user is targeting and not trying to apply to the chest before deviating
var/obj/item/bodypart/affecting = defender.get_bodypart(defender.get_random_valid_zone(attacker.zone_selected))
attacker.do_attack_animation(defender, ATTACK_EFFECT_PUNCH)
var/atk_verb = pick("precisely kick", "brutally chop", "cleanly hit", "viciously slam")
defender.visible_message(
span_danger("[attacker] [atk_verb]s [defender]!"),
span_userdanger("[attacker] [atk_verb]s you!"),
span_hear("You hear a sickening sound of flesh hitting flesh!"),
null,
attacker,
)
to_chat(attacker, span_danger("You [atk_verb] [defender]!"))
playsound(defender, 'sound/weapons/punch1.ogg', 25, TRUE, -1)
log_combat(attacker, defender, "strong punched (Sleeping Carp)")
defender.apply_damage(20, attacker.get_attack_type(), affecting)
return TRUE
///Crashing Wave Kick: Harm Disarm combo, throws people seven tiles backwards
/datum/martial_art/the_sleeping_carp/proc/launchKick(mob/living/attacker, mob/living/defender)
attacker.do_attack_animation(defender, ATTACK_EFFECT_KICK)
defender.visible_message(
span_warning("[attacker] kicks [defender] square in the chest, sending them flying!"),
span_userdanger("You are kicked square in the chest by [attacker], sending you flying!"),
span_hear("You hear a sickening sound of flesh hitting flesh!"),
COMBAT_MESSAGE_RANGE,
attacker,
)
playsound(attacker, 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
var/atom/throw_target = get_edge_target_turf(defender, attacker.dir)
defender.throw_at(throw_target, 7, 4, attacker)
defender.apply_damage(15, attacker.get_attack_type(), BODY_ZONE_CHEST, wound_bonus = CANT_WOUND)
log_combat(attacker, defender, "launchkicked (Sleeping Carp)")
return TRUE
///Keelhaul: Disarm Disarm combo, knocks people down and deals substantial stamina damage, and also discombobulates them. Knocks objects out of their hands if they're already on the ground.
/datum/martial_art/the_sleeping_carp/proc/dropKick(mob/living/attacker, mob/living/defender)
attacker.do_attack_animation(defender, ATTACK_EFFECT_KICK)
playsound(attacker, 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
if(defender.body_position == STANDING_UP)
defender.Knockdown(4 SECONDS)
defender.visible_message(span_warning("[attacker] kicks [defender] in the head, sending them face first into the floor!"), \
span_userdanger("You are kicked in the head by [attacker], sending you crashing to the floor!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, attacker)
else
defender.drop_all_held_items()
defender.visible_message(span_warning("[attacker] kicks [defender] in the head!"), \
span_userdanger("You are kicked in the head by [attacker]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, attacker)
defender.apply_damage(40, STAMINA)
defender.adjust_dizzy_up_to(10 SECONDS, 10 SECONDS)
defender.adjust_temp_blindness_up_to(2 SECONDS, 10 SECONDS)
log_combat(attacker, defender, "dropkicked (Sleeping Carp)")
return TRUE
/datum/martial_art/the_sleeping_carp/grab_act(mob/living/attacker, mob/living/defender)
if(!can_deflect(attacker)) //allows for deniability
return MARTIAL_ATTACK_INVALID
if(defender.check_block(attacker, 0, "[attacker]'s grab", UNARMED_ATTACK))
return MARTIAL_ATTACK_FAIL
add_to_streak("G", defender)
if(check_streak(attacker, defender))
return MARTIAL_ATTACK_SUCCESS
var/grab_log_description = "grabbed"
attacker.do_attack_animation(defender, ATTACK_EFFECT_PUNCH)
playsound(defender, 'sound/weapons/punch1.ogg', 25, TRUE, -1)
if(defender.stat != DEAD && !defender.IsUnconscious() && defender.getStaminaLoss() >= 80) //We put our target to sleep.
defender.visible_message(
span_danger("[attacker] carefully pinch a nerve in [defender]'s neck, knocking them out cold!"),
span_userdanger("[attacker] pinches something in your neck, and you fall unconscious!"),
)
grab_log_description = "grabbed and nerve pinched"
defender.Unconscious(10 SECONDS)
defender.apply_damage(20, STAMINA)
log_combat(attacker, defender, "[grab_log_description] (Sleeping Carp)")
return MARTIAL_ATTACK_INVALID // normal grab
/datum/martial_art/the_sleeping_carp/harm_act(mob/living/attacker, mob/living/defender)
if(attacker.grab_state == GRAB_KILL \
&& attacker.zone_selected == BODY_ZONE_HEAD \
&& attacker.pulling == defender \
&& defender.stat != DEAD \
)
var/obj/item/bodypart/head = defender.get_bodypart(BODY_ZONE_HEAD)
if(!isnull(head))
playsound(defender, 'sound/effects/wounds/crack1.ogg', 100)
defender.visible_message(
span_danger("[attacker] snaps the neck of [defender]!"),
span_userdanger("Your neck is snapped by [attacker]!"),
span_hear("You hear a sickening snap!"),
ignored_mobs = attacker
)
to_chat(attacker, span_danger("In a swift motion, you snap the neck of [defender]!"))
log_combat(attacker, defender, "snapped neck")
defender.apply_damage(100, BRUTE, BODY_ZONE_HEAD, wound_bonus=CANT_WOUND)
if(!HAS_TRAIT(defender, TRAIT_NODEATH))
defender.death()
defender.investigate_log("has had [defender.p_their()] neck snapped by [attacker].", INVESTIGATE_DEATHS)
return MARTIAL_ATTACK_SUCCESS
var/atk_verb = pick("kick", "chop", "hit", "slam")
var/final_damage = rand(10, 15)
if(defender.check_block(attacker, final_damage, "[attacker]'s [atk_verb]", UNARMED_ATTACK))
return MARTIAL_ATTACK_FAIL
add_to_streak("H", defender)
if(check_streak(attacker, defender))
return MARTIAL_ATTACK_SUCCESS
var/obj/item/bodypart/affecting = defender.get_bodypart(defender.get_random_valid_zone(attacker.zone_selected))
attacker.do_attack_animation(defender, ATTACK_EFFECT_PUNCH)
defender.visible_message(
span_danger("[attacker] [atk_verb]s [defender]!"),
span_userdanger("[attacker] [atk_verb]s you!"),
span_hear("You hear a sickening sound of flesh hitting flesh!"),
null,
attacker,
)
to_chat(attacker, span_danger("You [atk_verb] [defender]!"))
defender.apply_damage(final_damage, attacker.get_attack_type(), affecting, wound_bonus = CANT_WOUND)
playsound(defender, 'sound/weapons/punch1.ogg', 25, TRUE, -1)
log_combat(attacker, defender, "punched (Sleeping Carp)")
return MARTIAL_ATTACK_SUCCESS
/datum/martial_art/the_sleeping_carp/disarm_act(mob/living/attacker, mob/living/defender)
if(!can_deflect(attacker)) //allows for deniability
return MARTIAL_ATTACK_INVALID
if(defender.check_block(attacker, 0, attacker.name, UNARMED_ATTACK))
return MARTIAL_ATTACK_FAIL
add_to_streak("D", defender)
if(check_streak(attacker, defender))
return MARTIAL_ATTACK_SUCCESS
attacker.do_attack_animation(defender, ATTACK_EFFECT_PUNCH)
playsound(defender, 'sound/weapons/punch1.ogg', 25, TRUE, -1)
defender.apply_damage(20, STAMINA)
log_combat(attacker, defender, "disarmed (Sleeping Carp)")
return MARTIAL_ATTACK_INVALID // normal disarm
/datum/martial_art/the_sleeping_carp/proc/can_deflect(mob/living/carp_user)
if(!can_use(carp_user) || !carp_user.combat_mode)
return FALSE
if(carp_user.incapacitated(IGNORE_GRAB)) //NO STUN
return FALSE
if(!(carp_user.mobility_flags & MOBILITY_USE)) //NO UNABLE TO USE
return FALSE
var/datum/dna/dna = carp_user.has_dna()
if(dna?.check_mutation(/datum/mutation/human/hulk)) //NO HULK
return FALSE
if(!isturf(carp_user.loc)) //NO MOTHERFLIPPIN MECHS!
return FALSE
return TRUE
/datum/martial_art/the_sleeping_carp/proc/hit_by_projectile(mob/living/carp_user, obj/projectile/hitting_projectile, def_zone)
SIGNAL_HANDLER
if(!can_deflect(carp_user))
return NONE
carp_user.visible_message(
span_danger("[carp_user] effortlessly swats [hitting_projectile] aside! [carp_user.p_They()] can block bullets with [carp_user.p_their()] bare hands!"),
span_userdanger("You deflect [hitting_projectile]!"),
)
playsound(carp_user, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE)
hitting_projectile.firer = carp_user
hitting_projectile.set_angle(rand(0, 360))//SHING
return COMPONENT_BULLET_PIERCED
///Signal from getting attacked with an item, for a special interaction with touch spells
/datum/martial_art/the_sleeping_carp/proc/on_attackby(mob/living/carp_user, obj/item/attack_weapon, mob/attacker, params)
SIGNAL_HANDLER
if(!istype(attack_weapon, /obj/item/melee/touch_attack))
return
if(!can_deflect(carp_user))
return
var/obj/item/melee/touch_attack/touch_weapon = attack_weapon
carp_user.visible_message(
span_danger("[carp_user] carefully dodges [attacker]'s [touch_weapon]!"),
span_userdanger("You take great care to remain untouched by [attacker]'s [touch_weapon]!"),
)
return COMPONENT_NO_AFTERATTACK
/// Verb added to humans who learn the art of the sleeping carp.
/mob/living/proc/sleeping_carp_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Sleeping Carp clan."
set category = "Sleeping Carp"
to_chat(usr, "<b><i>You retreat inward and recall the teachings of the Sleeping Carp...</i></b>\n\
[span_notice("Gnashing Teeth")]: Punch Punch. Deal additional damage every second (consecutive) punch! Very good chance to wound!\n\
[span_notice("Crashing Wave Kick")]: Punch Shove. Launch your opponent away from you with incredible force!\n\
[span_notice("Keelhaul")]: Shove Shove. Nonlethally kick an opponent to the floor, knocking them down, discombobulating them and dealing substantial stamina damage. If they're already prone, disarm them as well.\n\
[span_notice("Grabs and Shoves")]: While in combat mode, your typical grab and shove do decent stamina damage. If you grab someone who has substantial amounts of stamina damage, you knock them out!\n\
<span class='notice'>While in combat mode (and not stunned, not a hulk, and not in a mech), you can reflect all projectiles that come your way, sending them back at the people who fired them! \n\
Also, you are more resilient against suffering wounds in combat, and your limbs cannot be dismembered. This grants you extra staying power during extended combat, especially against slashing and other bleeding weapons. \n\
You are not invincible, however- while you may not suffer debilitating wounds often, you must still watch your health and should have appropriate medical supplies for use during downtime. \n\
In addition, your training has imbued you with a loathing of guns, and you can no longer use them.</span>")
/obj/item/staff/bostaff
name = "bo staff"
desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate."
force = 10
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
throwforce = 20
throw_speed = 2
attack_verb_continuous = list("smashes", "slams", "whacks", "thwacks")
attack_verb_simple = list("smash", "slam", "whack", "thwack")
icon = 'icons/obj/weapons/staff.dmi'
icon_state = "bostaff0"
base_icon_state = "bostaff"
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
block_chance = 50
/obj/item/staff/bostaff/Initialize(mapload)
. = ..()
AddComponent(/datum/component/two_handed, \
force_unwielded = 10, \
force_wielded = 24, \
icon_wielded = "[base_icon_state]1", \
)
/obj/item/staff/bostaff/update_icon_state()
icon_state = "[base_icon_state]0"
return ..()
/obj/item/staff/bostaff/attack(mob/target, mob/living/user, params)
add_fingerprint(user)
if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
to_chat(user, span_warning("You club yourself over the head with [src]."))
user.Paralyze(6 SECONDS)
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.apply_damage(2*force, BRUTE, BODY_ZONE_HEAD)
else
user.take_bodypart_damage(2*force)
return
if(iscyborg(target))
return ..()
if(!isliving(target))
return ..()
var/mob/living/carbon/C = target
if(C.stat)
to_chat(user, span_warning("It would be dishonorable to attack a foe while they cannot retaliate."))
return
var/list/modifiers = params2list(params)
if(LAZYACCESS(modifiers, RIGHT_CLICK))
if(!HAS_TRAIT(src, TRAIT_WIELDED))
return ..()
if(!ishuman(target))
return ..()
var/mob/living/carbon/human/H = target
var/list/fluffmessages = list("club", "smack", "broadside", "beat", "slam")
H.visible_message(span_warning("[user] [pick(fluffmessages)]s [H] with [src]!"), \
span_userdanger("[user] [pick(fluffmessages)]s you with [src]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), null, user)
to_chat(user, span_danger("You [pick(fluffmessages)] [H] with [src]!"))
playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, TRUE, -1)
H.adjustStaminaLoss(rand(13,20))
if(prob(10))
H.visible_message(span_warning("[H] collapses!"), \
span_userdanger("Your legs give out!"))
H.Paralyze(8 SECONDS)
if(H.staminaloss && !H.IsSleeping())
var/total_health = (H.health - H.staminaloss)
if(total_health <= HEALTH_THRESHOLD_CRIT && !H.stat)
H.visible_message(span_warning("[user] delivers a heavy hit to [H]'s head, knocking [H.p_them()] out cold!"), \
span_userdanger("You're knocked unconscious by [user]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), null, user)
to_chat(user, span_danger("You deliver a heavy hit to [H]'s head, knocking [H.p_them()] out cold!"))
H.SetSleeping(60 SECONDS)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 150)
else
return ..()
/obj/item/staff/bostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
if(!HAS_TRAIT(src, TRAIT_WIELDED))
return ..()
return FALSE
/obj/item/clothing/gloves/the_sleeping_carp
name = "carp gloves"
desc = "These gloves are capable of making people use The Sleeping Carp."
icon_state = "black"
greyscale_colors = COLOR_BLACK
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
resistance_flags = NONE
/obj/item/clothing/gloves/the_sleeping_carp/Initialize(mapload)
. = ..()
AddComponent(/datum/component/martial_art_giver, /datum/martial_art/the_sleeping_carp)
#undef STRONG_PUNCH_COMBO
#undef LAUNCH_KICK_COMBO
#undef DROP_KICK_COMBO