Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bounty] Graytide Sectorwide #4428

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/__DEFINES/~monkestation/martial_arts.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//Monkestation exclusive martial arts defines.

#define MARTIALART_TRIBALCLAW "tribal claw"
#define MARTIALART_TUNNELARTS "tunnel arts"
Binary file modified icons/mob/clothing/suits/jacket.dmi
Binary file not shown.
Binary file modified icons/obj/clothing/suits/jacket.dmi
Binary file not shown.
10 changes: 10 additions & 0 deletions monkestation/code/game/objects/items/storage/uplink_kits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@
new /obj/item/gun/ballistic/automatic/plastikov(src)
new /obj/item/ammo_box/magazine/plastikov9mm(src)

/obj/item/storage/box/syndie_kit/khan_package
name = "Tunel Khans Khare Paccage"
desc = "It's a syndicate box written all over with gray crayon."
icon_state = "syndiebox"
illustration = "writing_syndie"

/obj/item/storage/box/syndie_kit/khan_package/PopulateContents()
new /obj/item/book/granter/martial/the_tunnel_arts(src)
new /obj/item/clothing/suit/jacket/det_suit/khan(src)

#undef KIT_ITEM_CATEGORY_SUPPORT
#undef KIT_ITEM_CATEGORY_WEAPONS
#undef KIT_ITEM_CATEGORY_MISC
33 changes: 33 additions & 0 deletions monkestation/code/modules/martial_arts/granters/tunnel_arts_gr.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/obj/item/book/granter/martial/the_tunnel_arts
martial = /datum/martial_art/the_tunnel_arts
name = "odd scroll"
martial_name = "tunnel arts"
desc = "A scroll made up of torn books, scrwaled with gray crayon."
greet = span_sciradio("You can visualize how you and your kind will one day rule the spinward sector with a gray fist. You've learned The Tunnel Arts. You can review what you've learned at any time within The Tunnel Arts tab.")
icon = 'icons/obj/scrolls.dmi'
icon_state = "scroll-ancient"
remarks = list("I must prove myself worthy to the masters of the maintainence...",
"What do you mean you can clone yourself...?",
"I feel someone with the fireaxe running away from the captain...",
"I don't think this would combine with other martial arts...",
"Graytide sectorwide..."
)

/obj/item/book/granter/martial/the_tunnel_arts/on_reading_finished(mob/living/carbon/user)
. = ..()
update_appearance()

/obj/item/book/granter/martial/the_tunnel_arts/update_appearance(updates)
. = ..()
if(uses <= 0)
name = "odd scroll"
desc = "Whatever was written here, you can't recognize it anymore."
else
name = initial(name)
desc = initial(desc)
icon_state = initial(icon_state)

/obj/item/book/granter/martial/the_tunnel_arts/can_learn(mob/user)
//someone ought to find logic to make it assistant only, but I don't wanna
return TRUE

8 changes: 8 additions & 0 deletions monkestation/code/modules/martial_arts/misc/clothing.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/obj/item/clothing/suit/jacket/det_suit/khan
name = "khan warcoat"
desc = "More experienced khans sometimes get their hands on Nanotrasen kevlar trenchcoats. And when they do, they inevitably tear the arms off them to show off the grey jumpsuit underneath. \
Bears a crudely drawn kanji symobl on the back: '悪'. It doesn't look quite right..."
icon_state = "khancoat"
inhand_icon_state = null
body_parts_covered = CHEST|GROIN

23 changes: 23 additions & 0 deletions monkestation/code/modules/martial_arts/misc/martial_effects.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/datum/status_effect/no_gravity
id = "no_gravity"
alert_type = null
duration = 2 SECONDS
status_type = STATUS_EFFECT_UNIQUE

/datum/status_effect/no_gravity/on_apply()
owner.AddElement(/datum/element/forced_gravity, 0)

/datum/status_effect/no_gravity/on_remove()
owner.RemoveElement(/datum/element/forced_gravity, 0)



/datum/status_effect/amok/proc/exclusion_check(mob/living/potential_target)
return IS_HERETIC_OR_MONSTER(potential_target)

/datum/status_effect/amok/tunnel_madness
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no duration or effect?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk lol

id = "tunnel_madness"

/datum/status_effect/amok/tunnel_madness/exclusion_check(mob/living/potential_target)
return faction_check(potential_target.faction, list(FACTION_RAT))

227 changes: 227 additions & 0 deletions monkestation/code/modules/martial_arts/tunnel_arts.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
#define SPACE_WIND_GOD_FIST_COMBO "HD"
#define CHAOS_REIGNS_COMBO "DH"
#define ONE_THOUSAND_FISTS_COMBO "HH"

#define TUNNEL_ARTS_TRAIT "sleeping_carp"
//god's sketchiest solution

/datum/martial_art/the_tunnel_arts
name = "The Tunnel Arts"
id = MARTIALART_TUNNELARTS
allow_temp_override = FALSE
help_verb = /mob/living/proc/tunnel_arts_help
display_combos = TRUE
/// List of traits applied to users of this martial art.
var/list/tunnel_traits = list(TRAIT_HARDLY_WOUNDED, TRAIT_NOSOFTCRIT, TRAIT_BATON_RESISTANCE, TRAIT_PERFECT_ATTACKER, TRAIT_NOGUNS)
/// Probability of successfully blocking attacks while on throw mode
block_chance = 50

/datum/martial_art/the_tunnel_arts/teach(mob/living/new_holder)
. = ..()
new_holder.add_traits(tunnel_traits, TUNNEL_ARTS_TRAIT)
RegisterSignal(new_holder, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby))
new_holder.faction |= FACTION_RAT //:D

/datum/martial_art/the_tunnel_arts/on_remove(mob/living/remove_from)
remove_from.remove_traits(tunnel_traits, TUNNEL_ARTS_TRAIT)
UnregisterSignal(remove_from, list(COMSIG_ATOM_ATTACKBY))
remove_from.faction -= FACTION_RAT //:(
return ..()

/datum/martial_art/the_tunnel_arts/proc/check_streak(mob/living/attacker, mob/living/defender)
if(findtext(streak, SPACE_WIND_GOD_FIST_COMBO))
reset_streak()
return god_fist(attacker, defender)

if(findtext(streak, CHAOS_REIGNS_COMBO))
reset_streak()
return chaos_punch(attacker, defender)

if(findtext(streak, ONE_THOUSAND_FISTS_COMBO))
reset_streak()
return thousand_fists(attacker, defender)

return FALSE

///Space Wind God Fist: Harm Disarm, stuns the target briefly and temporarily causing them to lose personal gravity.
/datum/martial_art/the_tunnel_arts/proc/god_fist(mob/living/attacker, mob/living/defender)
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] uppercuts [defender], sending them skyward!"),
span_userdanger("[attacker] uppercuts you, sending you hurtling through the air!"),
span_hear("You hear a sickening sound of flesh hitting flesh!"),
null,
attacker,
)
to_chat(attacker, span_danger("You uppercut [defender]!"))
playsound(defender, 'sound/weapons/punch1.ogg', 25, TRUE, -1)
log_combat(attacker, defender, "god fist (The Tunnel Arts))")
defender.apply_damage(20, attacker.get_attack_type(), affecting)
defender.emote("flip")
defender.emote("spin")
defender.apply_status_effect(/datum/status_effect/no_gravity)
defender.Paralyze(1 SECONDS)
return TRUE

///Chaos Reigns: Disarm Harm, Launches the target backwards, confuses them and causes the target to randomly lash out at others.
/datum/martial_art/the_tunnel_arts/proc/chaos_punch(mob/living/attacker, mob/living/defender)
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] slams their palm into [defender]!"),
span_userdanger("[attacker] palm strikes you, rattling you to your very core!"),
span_hear("You hear a sickening sound of flesh hitting flesh!"),
null,
attacker,
)
to_chat(attacker, span_danger("You palm strike [defender], corrupting their Chi energy!"))
playsound(defender, 'sound/weapons/punch1.ogg', 25, TRUE, -1)
log_combat(attacker, defender, "god fist (The Tunnel Arts))")
defender.apply_damage(30, attacker.get_attack_type(), affecting)
var/atom/throw_target = get_edge_target_turf(defender, attacker.dir)
defender.throw_at(throw_target, 3, 4, attacker)
defender.apply_status_effect(/datum/status_effect/amok/tunnel_madness)
defender.adjust_confusion_up_to(5 SECONDS, 10 SECONDS)
defender.adjust_dizzy_up_to(5 SECONDS, 10 SECONDS)
return TRUE

///One Thousand Fists: Harm Harm, Delivers a lethal strike, and produces a duplicate of yourself to fight with you. Only works if the target is alive, and has a mind.
/datum/martial_art/the_tunnel_arts/proc/thousand_fists(mob/living/attacker, mob/living/defender)
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] punches [defender] with a rapid series of blows!"),
span_userdanger("[attacker] rapidly punches you!"),
span_hear("You hear a sickening sound of flesh hitting flesh!"),
null,
attacker,
)
to_chat(attacker, span_danger("You rapidly punch [defender]!"))

// Borrows this trick from standard holoparsites
for(var/sounds in 1 to 4)
addtimer(CALLBACK(src, PROC_REF(do_attack_sound), defender.loc), sounds DECISECONDS, TIMER_DELETE_ME)

log_combat(attacker, defender, "god fist (The Tunnel Arts))")
defender.apply_damage(20, attacker.get_attack_type(), affecting)

if(!defender.mind || defender.stat != CONSCIOUS || prob(50))
return TRUE

var/mob/living/simple_animal/hostile/illusion/khan = new(attacker.loc)
khan.faction = attacker.faction.Copy()
khan.Copy_Parent(attacker, 100, attacker.health/2.5, 12, 30)
khan.GiveTarget(defender)
attacker.visible_message(
span_danger("[attacker] seems to duplicate before your very eyes!"),
span_userdanger("[attacker] seems to duplicate before your eyes!"),
span_hear("You hear a multitude of stamping feet!"),
null,
attacker,
)
to_chat(attacker, span_danger("You conjure an illusionary warrior to fight with you!"))
return TRUE

/// Echo our punching sounds
/datum/martial_art/the_tunnel_arts/proc/do_attack_sound(atom/playing_from)
playsound(playing_from, 'sound/weapons/punch1.ogg', 25, TRUE, -1)

/datum/martial_art/the_tunnel_arts/grab_act(mob/living/attacker, mob/living/defender)
if(!check_usability(attacker)) //allows for deniability
return MARTIAL_ATTACK_INVALID

add_to_streak("G", defender)
if(check_streak(attacker, defender))
return MARTIAL_ATTACK_SUCCESS

log_combat(attacker, defender, "grabbed (The Tunnel Arts)")
return MARTIAL_ATTACK_INVALID // normal grab

/datum/martial_art/the_tunnel_arts/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

add_to_streak("H", defender)
if(check_streak(attacker, defender))
return MARTIAL_ATTACK_SUCCESS

log_combat(attacker, defender, "punched (The Tunnel Arts)")
return MARTIAL_ATTACK_INVALID //normal punch

/datum/martial_art/the_tunnel_arts/disarm_act(mob/living/attacker, mob/living/defender)
if(!check_usability(attacker)) //allows for deniability
return MARTIAL_ATTACK_INVALID

add_to_streak("D", defender)
if(check_streak(attacker, defender))
return MARTIAL_ATTACK_SUCCESS

log_combat(attacker, defender, "disarmed (The Tunnel Arts)")
return MARTIAL_ATTACK_INVALID // normal disarm

/datum/martial_art/the_tunnel_arts/proc/check_usability(mob/living/khan_user)
if(!(khan_user.istate & ISTATE_HARM)) // monke edit: istates/intents
return FALSE
if(khan_user.incapacitated(IGNORE_GRAB)) //NO STUN
return FALSE
if(!(khan_user.mobility_flags & MOBILITY_USE)) //NO UNABLE TO USE
return FALSE
var/datum/dna/dna = khan_user.has_dna()
if(dna?.check_mutation(/datum/mutation/human/hulk)) //NO HULK
return FALSE
if(!isturf(khan_user.loc)) //NO MOTHERFLIPPIN MECHS!
return FALSE
return TRUE

///Signal from getting attacked with an item, for a special interaction with touch spells
/datum/martial_art/the_tunnel_arts/proc/on_attackby(mob/living/khan_user, obj/item/attack_weapon, mob/attacker, params)
SIGNAL_HANDLER

if(!istype(attack_weapon, /obj/item/melee/touch_attack) || !check_usability(khan_user))
return
var/obj/item/melee/touch_attack/touch_weapon = attack_weapon
khan_user.visible_message(
span_danger("[khan_user] carefully dodges [attacker]'s [touch_weapon]!"),
span_userdanger("You take great care to remain untouched by [attacker]'s [touch_weapon]!"),
ignored_mobs = list(attacker),
)
to_chat(attacker, span_userdanger("[khan_user] carefully dodges your [touch_weapon], remaining completely untouched!"), type = MESSAGE_TYPE_COMBAT)
khan_user.balloon_alert(attacker, "miss!")
playsound(khan_user, 'monkestation/sound/effects/miss.ogg', vol = 50, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
return COMPONENT_NO_AFTERATTACK

/// Verb added to humans who learn the tunnel arts.
/mob/living/proc/tunnel_arts_help()
set name = "Remember the Arts"
set desc = "Remember the martial techniques of Maint Khan, who brought to the Spinward Sector the knowledge of the Tunnel Arts."
set category = "The Tunnel Arts"

to_chat(usr, "<b><i>You retreat inward and recall the teachings of the Tunnel Arts...</i></b>\n\
[span_notice("One Thousand Fists")]: Punch Punch. Deal additional damage every second (consecutive) punch, and potentially conjure forth an illusionary Khan Warrior.\n\
[span_notice("Chaos Reigns")]: Shove Punch. Launch your opponent away from you and corrupt their Chi energy, causing them to flail madly in their confused state!\n\
[span_notice("Space Wind God Fist")]: Punch Shove. Send the target spinning helplessly through the air with this vicious uppercut.\n\
<span class='notice'>While in throw mode (and not stunned, not a hulk, and not in a mech), you can block various attacks against you in melee with your bare hands!</span>")

#undef SPACE_WIND_GOD_FIST_COMBO
#undef CHAOS_REIGNS_COMBO
#undef ONE_THOUSAND_FISTS_COMBO
7 changes: 7 additions & 0 deletions monkestation/code/modules/uplink/uplink_items/job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,10 @@
cost = 8
item = /obj/item/clothing/gloves/color/yellow/power_gloves
restricted_roles = list(JOB_STATION_ENGINEER, JOB_CHIEF_ENGINEER, JOB_ATMOSPHERIC_TECHNICIAN)

/datum/uplink_item/role_restricted/tunnel_khans
name = "Tunnel Khans Care Package"
desc = "A... questionably packed box written on with gray crayon. It's really hard to read. We hope that your assistant mind can comprehend it better than us."
cost = 13
item = /obj/item/storage/box/syndie_kit/khan_package
restricted_roles = list(JOB_ASSISTANT)
4 changes: 4 additions & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -7384,7 +7384,11 @@
#include "monkestation\code\modules\mapping\mapping_helpers.dm"
#include "monkestation\code\modules\maptext\maptext_image_helper.dm"
#include "monkestation\code\modules\martial_arts\tribal_claw.dm"
#include "monkestation\code\modules\martial_arts\tunnel_arts.dm"
#include "monkestation\code\modules\martial_arts\granters\tribal_claw_gr.dm"
#include "monkestation\code\modules\martial_arts\granters\tunnel_arts_gr.dm"
#include "monkestation\code\modules\martial_arts\misc\clothing.dm"
#include "monkestation\code\modules\martial_arts\misc\martial_effects.dm"
#include "monkestation\code\modules\martial_arts\spells\spells.dm"
#include "monkestation\code\modules\mech_comp\_interface.dm"
#include "monkestation\code\modules\mech_comp\_message.dm"
Expand Down
Loading