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

Knights in AR: Secure with swords and shocking batons #303

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
435 changes: 435 additions & 0 deletions _maps/templates/holodeck_doppler_sword_trainer.dmm

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions code/game/machinery/recharger.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
/obj/item/ammo_box/magazine/recharge,
/obj/item/modular_computer,
/obj/item/gun/ballistic/automatic/battle_rifle,
/obj/item/melee/baton/doppler_security, // DOPPLER EDIT ADDITION
))

/obj/machinery/recharger/RefreshParts()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
new /obj/item/storage/lockbox/loyalty(src)
new /obj/item/storage/box/flashbangs(src)
new /obj/item/shield/riot/tele(src)
new /obj/item/storage/belt/security/full(src)
new /obj/item/storage/belt/secsword/full(src) // DOPPLER EDIT - new /obj/item/storage/belt/security/full(src)
new /obj/item/circuitboard/machine/techfab/department/security(src)
new /obj/item/storage/photo_album/hos(src)

Expand All @@ -92,7 +92,7 @@
new /obj/item/storage/bag/garment/warden(src)
new /obj/item/storage/box/zipties(src)
new /obj/item/storage/box/flashbangs(src)
new /obj/item/storage/belt/security/full(src)
new /obj/item/storage/belt/secsword/full(src) // DOPPLER EDIT - new /obj/item/storage/belt/security/full(src)
new /obj/item/flashlight/seclite(src)
new /obj/item/door_remote/head_of_security(src)

Expand All @@ -115,7 +115,7 @@

/obj/structure/closet/secure_closet/security/sec/PopulateContents()
..()
new /obj/item/storage/belt/security/full(src)
new /obj/item/storage/belt/secsword/full(src) // DOPPLER EDIT - new /obj/item/storage/belt/security/full(src)

/obj/structure/closet/secure_closet/security/cargo

Expand Down
175 changes: 175 additions & 0 deletions modular_doppler/modular_weapons/code/sec_swords/baton.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/obj/item/melee/baton/doppler_security
name = "electro baton"
desc = "A high power baton for incapacitating humans and similar with. Delivers powerful jolts of electricity \
that may cause bodily harm, but will -- without a doubt -- entice cooperation."

desc_controls = "<b>Left Click</b> to stun, <b>Right Click</b> to harm."
context_living_rmb_active = "Harmful Stun"
attack_verb_continuous = list("beats")
attack_verb_simple = list("beat")

icon = 'modular_doppler/modular_weapons/icons/obj/sec_swords.dmi'
icon_state = "baton_two"
lefthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/melee_lefthand.dmi'
righthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/melee_righthand.dmi'
inhand_icon_state = "baton_two"
icon_angle = -20

on_stun_sound = 'sound/items/weapons/taserhit.ogg'
on_stun_volume = 50
drop_sound = 'sound/items/baton/stun_baton_active_drop.ogg'
pickup_sound = 'sound/items/baton/stun_baton_active_pickup.ogg'
sound_vary = TRUE

active = TRUE
force = 10
wound_bonus = 0
armor_type = /datum/armor/baton_security
throwforce = 7
force_say_chance = 50
stamina_damage = 35 // DOPPLER EDIT - 4 baton crit now (Original: 60)
knockdown_time = 5 SECONDS
clumsy_knockdown_time = 15 SECONDS
cooldown = 2.5 SECONDS

var/obj/item/stock_parts/power_store/cell
var/preload_cell_type //if not empty the baton starts with this type of cell
var/cell_hit_cost = STANDARD_CELL_CHARGE

/obj/item/melee/baton/doppler_security/Initialize(mapload)
. = ..()
if(preload_cell_type)
if(!ispath(preload_cell_type, /obj/item/stock_parts/power_store/cell))
log_mapping("[src] at [AREACOORD(src)] had an invalid preload_cell_type: [preload_cell_type].")
else
cell = new preload_cell_type(src)

/obj/item/melee/baton/doppler_security/get_cell()
return cell

/obj/item/melee/baton/doppler_security/suicide_act(mob/living/user)
if(cell?.charge && active)
user.visible_message(span_suicide("[user] is putting the live [name] right to [user.p_their()] heart! It looks like [user.p_theyre()] trying to commit suicide!"))
attack(user, user)
return FIRELOSS
return

/obj/item/melee/baton/doppler_security/Destroy()
if(cell)
QDEL_NULL(cell)
UnregisterSignal(src, COMSIG_ATOM_ATTACKBY)
return ..()

/obj/item/melee/baton/doppler_security/examine(mob/user)
. = ..()
if(cell)
. += span_notice("\The [src] is [round(cell.percent())]% charged.")
else
. += span_warning("\The [src] does not have a power source installed.")

/obj/item/melee/baton/doppler_security/proc/deductcharge(deducted_charge)
if(!cell)
return
//Note this value returned is significant, as it will determine
//if a stun is applied or not
. = cell.use(deducted_charge)

/obj/item/melee/baton/doppler_security/clumsy_check(mob/living/carbon/human/user)
if(!active || !HAS_TRAIT(user, TRAIT_CLUMSY) || prob(50))
return FALSE
user.visible_message(span_danger("[user] accidentally touches the prongs of [src]! Fool they are!"), span_userdanger("You accidentally touch the prongs of [src]!"))

if(iscyborg(user))
if(affect_cyborg)
user.flash_act(affect_silicon = TRUE)
user.Paralyze(clumsy_knockdown_time)
additional_effects_cyborg(user, user) // user is the target here
if(on_stun_sound)
playsound(get_turf(src), on_stun_sound, on_stun_volume, TRUE, -1)
else
playsound(get_turf(src), 'sound/items/weapons/taserhit.ogg', 10, TRUE)
else
if(ishuman(user))
var/mob/living/carbon/human/human_user = user
human_user.force_say()
user.Knockdown(clumsy_knockdown_time)
user.apply_damage(stamina_damage, STAMINA)
additional_effects_non_cyborg(user, user)
if(on_stun_sound)
playsound(get_turf(src), on_stun_sound, on_stun_volume, TRUE, -1)

user.apply_damage(2 * force, BURN, BODY_ZONE_CHEST, attacking_item = src)

log_combat(user, user, "accidentally stun attacked [user.p_them()]self due to their clumsiness", src)
if(stun_animation)
user.do_attack_animation(user)
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
deductcharge(cell_hit_cost)

/// Handles prodding targets with turned off stunbatons and right clicking stun'n'bash
/obj/item/melee/baton/doppler_security/baton_attack(mob/living/target, mob/living/user, modifiers)
. = ..()
if(. != BATON_DO_NORMAL_ATTACK)
return
if(LAZYACCESS(modifiers, RIGHT_CLICK))
if(active && cooldown_check <= world.time && !check_parried(target, user))
finalize_baton_attack(target, user, modifiers, in_attack_chain = FALSE)
else if(!user.combat_mode)
target.visible_message(span_warning("[user] prods [target] with [src]. Luckily it was off."), \
span_warning("[user] prods you with [src]. Luckily it was off."))
return BATON_ATTACK_DONE

/obj/item/melee/baton/doppler_security/baton_effect(mob/living/target, mob/living/user, modifiers, stun_override)
if(iscyborg(loc))
var/mob/living/silicon/robot/robot = loc
if(!robot || !robot.cell || !robot.cell.use(cell_hit_cost))
return FALSE
else if(!deductcharge(cell_hit_cost))
return FALSE
stun_override = 0 //Avoids knocking people down prematurely.
return ..()

/obj/item/melee/baton/doppler_security/additional_effects_non_cyborg(mob/living/target, mob/living/user)
target.set_jitter_if_lower(40 SECONDS)
target.set_stutter_if_lower(16 SECONDS)
if(iscarbon(target))
var/mob/living/carbon/big_shocker = target
big_shocker.electrocute_act(10, src, 1, jitter_time = 0 SECONDS, stutter_time = 0 SECONDS, stun_duration = 0 SECONDS)
else
target.electrocute_act(10, src, 1)
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
addtimer(CALLBACK(src, PROC_REF(apply_stun_effect_end), target), 2 SECONDS)

/// After the initial stun period, we check to see if the target needs to have the stun applied.
/obj/item/melee/baton/doppler_security/proc/apply_stun_effect_end(mob/living/target)
var/trait_check = HAS_TRAIT(target, TRAIT_BATON_RESISTANCE) //var since we check it in out to_chat as well as determine stun duration
if(!target.IsKnockdown())
to_chat(target, span_warning("Your muscles seize, making you collapse[trait_check ? ", but your body quickly recovers..." : "!"]"))

if(!trait_check)
target.Knockdown(knockdown_time)

/obj/item/melee/baton/doppler_security/get_wait_description()
return span_danger("The baton is still charging!")

/obj/item/melee/baton/doppler_security/get_stun_description(mob/living/target, mob/living/user)
. = list()

.["visible"] = span_danger("[user] shocks [target] with [src]!")
.["local"] = span_userdanger("[user] shocks you with [src]!")

/obj/item/melee/baton/doppler_security/get_unga_dunga_cyborg_stun_description(mob/living/target, mob/living/user)
. = list()

.["visible"] = span_danger("[user] tries to shock [target] with [src], and predictably fails!")
.["local"] = span_userdanger("[user] tries to... shock you with [src]?")

/obj/item/melee/baton/doppler_security/emp_act(severity)
. = ..()
if (!cell)
return
if (!(. & EMP_PROTECT_SELF))
deductcharge(STANDARD_CELL_CHARGE / severity)

/obj/item/melee/baton/doppler_security/loaded //this one starts with a cell pre-installed.
preload_cell_type = /obj/item/stock_parts/power_store/cell/high
49 changes: 49 additions & 0 deletions modular_doppler/modular_weapons/code/sec_swords/big_sword.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/obj/item/melee/secblade
name = "security shortblade"
desc = "A utilitarian weapon, handle and blade, with little more. \
Designed for ease of blade replacement when it inevitably breaks due to mistreatment."

icon = 'modular_doppler/modular_weapons/icons/obj/sec_swords.dmi'
icon_state = "sec_sword"
lefthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/melee_lefthand.dmi'
righthand_file = 'modular_doppler/modular_weapons/icons/mob/inhands/melee_righthand.dmi'
inhand_icon_state = "sec_sword"
icon_angle = -20

hitsound = 'sound/items/weapons/bladeslice.ogg'
block_sound = 'sound/items/weapons/parry.ogg'

obj_flags = CONDUCTS_ELECTRICITY
sharpness = SHARP_EDGED
w_class = WEIGHT_CLASS_BULKY
obj_flags = UNIQUE_RENAME

force = 18
throwforce = 10
block_chance = 1 // Nah, I'd win
wound_bonus = 0
bare_wound_bonus = 20

attack_verb_continuous = list("attacks", "slashes", "slices", "tears", "lacerates", "rips", "dices", "rends")
attack_verb_simple = list("attack", "slash", "slice", "tear", "lacerate", "rip", "dice", "rend")

var/list/alt_continuous = list("stabs", "pierces", "impales")
var/list/alt_simple = list("stab", "pierce", "impale")

/obj/item/melee/secblade/Initialize(mapload)
. = ..()
AddComponent(/datum/component/butchering, speed = 4 SECONDS, effectiveness = 100)
alt_continuous = string_list(alt_continuous)
alt_simple = string_list(alt_simple)
AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -5)

/obj/item/melee/secblade/training
name = "training shortblade"
desc = "A utilitarian weapon, handle and blade, with little more. \
This one doesn't seem completely real, incapable of bloodshed but likely still hurts quite a lot."

icon_state = "training_sword"

damtype = STAMINA
wound_bonus = -50
bare_wound_bonus = -50
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/datum/map_template/holodeck/doppler_sword_trainer
name = "Holodeck - Shortblade Trainer"
template_id = "holodeck_doppler_sword_trainer"
mappath = "_maps/templates/holodeck_doppler_sword_trainer.dmm"
109 changes: 109 additions & 0 deletions modular_doppler/modular_weapons/code/sec_swords/sheath.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/obj/item/storage/belt/secsword
name = "security weapons sheath"
desc = "A large block of metal made for safely holding on to a shortblade and matching electro baton, \
along with the rest of an officer's security equipment."
icon = 'modular_doppler/modular_weapons/icons/obj/sec_swords.dmi'
icon_state = "swordcase"
base_icon_state = "swordcase"
worn_icon = 'modular_doppler/modular_weapons/icons/mob/worn/cases.dmi'
worn_icon_state = "swordcase"
w_class = WEIGHT_CLASS_BULKY
interaction_flags_click = parent_type::interaction_flags_click | NEED_DEXTERITY | NEED_HANDS
obj_flags = UNIQUE_RENAME

/obj/item/storage/belt/secsword/Initialize(mapload)
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)

atom_storage.max_slots = 5
atom_storage.do_rustle = FALSE
atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
atom_storage.max_total_storage = (WEIGHT_CLASS_BULKY + (WEIGHT_CLASS_NORMAL * 4)) // One sword four other things
atom_storage.set_holdable(list(
/obj/item/ammo_box,
/obj/item/ammo_casing/shotgun,
/obj/item/assembly/flash/handheld,
/obj/item/clothing/glasses,
/obj/item/clothing/gloves,
/obj/item/flashlight/seclite,
/obj/item/food/donut,
/obj/item/grenade,
/obj/item/holosign_creator/security,
/obj/item/knife/combat,
/obj/item/melee/baton,
/obj/item/radio,
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
/obj/item/restraints/legcuffs/bola,
/obj/item/melee/secblade,
))
atom_storage.open_sound = 'sound/items/handling/holster_open.ogg'
atom_storage.open_sound_vary = TRUE

/obj/item/storage/belt/secsword/examine(mob/user)
. = ..()
if(length(contents))
. += span_notice("<b>Left Click</b> to draw a stored blade, <b>Right Click</b> to draw a stored baton while wearing.")

/obj/item/storage/belt/secsword/attack_hand(mob/user, list/modifiers)
if(!(user.get_slot_by_item(src) & ITEM_SLOT_BELT))
return ..()
for(var/obj/item/melee/secblade/blade_runner in contents)
user.visible_message(span_notice("[user] draws [blade_runner] from [src]."), span_notice("You draw [blade_runner] from [src]."))
user.put_in_hands(blade_runner)
playsound(user, 'sound/items/sheath.ogg', 50, TRUE)
update_appearance()
return
return ..()

/obj/item/storage/belt/secsword/attack_hand_secondary(mob/user, list/modifiers)
if(!(user.get_slot_by_item(src) & ITEM_SLOT_BELT))
return ..()
for(var/obj/item/melee/baton/doppler_security/simply_shocking in contents)
user.visible_message(span_notice("[user] draws [simply_shocking] from [src]."), span_notice("You draw [simply_shocking] from [src]."))
user.put_in_hands(simply_shocking)
playsound(user, 'sound/items/sheath.ogg', 50, TRUE)
update_appearance()
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
return ..()

/obj/item/storage/belt/secsword/update_icon_state()
var/has_sword = FALSE
var/has_baton = FALSE
for(var/obj/thing in contents)
if(has_baton && has_sword)
break
if(istype(thing, /obj/item/melee/baton/doppler_security))
has_baton = TRUE
if(istype(thing, /obj/item/melee/secblade))
has_sword = TRUE

icon_state = initial(icon_state)
worn_icon_state = initial(worn_icon_state)

var/next_appendage
if(has_sword && has_baton)
next_appendage = "-full"
else if(has_sword)
next_appendage = "-blayde"
else if(has_baton)
next_appendage = "-stun"

if(next_appendage)
icon_state += next_appendage
worn_icon_state += next_appendage
return ..()

/obj/item/storage/belt/secsword/full/PopulateContents()
new /obj/item/melee/secblade(src)
new /obj/item/melee/baton/doppler_security/loaded(src)
new /obj/item/restraints/handcuffs(src)
new /obj/item/reagent_containers/spray/pepper(src)
new /obj/item/assembly/flash/handheld(src)
update_appearance()

/obj/item/storage/belt/secsword/training/PopulateContents()
new /obj/item/melee/secblade/training(src) // No way attack on titan
new /obj/item/melee/secblade/training(src)
new /obj/item/melee/baton/doppler_security/loaded(src)
update_appearance()
Binary file not shown.
Binary file not shown.
Binary file modified modular_doppler/modular_weapons/icons/mob/worn/cases.dmi
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions modular_doppler/time_clock/code/console_tgui.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
#define TIME_CLOCK_RETURN_ITEMS list( \
/obj/item/melee/baton/security, \
/obj/item/melee/baton/security/loaded, \
/obj/item/melee/baton/doppler_security, \
/obj/item/melee/baton/doppler_security/loaded, \
/obj/item/melee/baton/telescopic, \
/obj/item/melee/baton, \
/obj/item/melee/secblade, \
/obj/item/assembly/flash/handheld, \
/obj/item/gun/energy/disabler, \
/obj/item/megaphone/command, \
Expand All @@ -25,6 +28,7 @@
/obj/item/clothing/shoes/magboots/advance, \
/obj/item/shield/riot/tele, \
/obj/item/storage/belt/security/full, \
/obj/item/storage/belt/secsword/full, \
/obj/item/gun/energy/e_gun/hos, \
/obj/item/pinpointer/nuke, \
/obj/item/gun/energy/e_gun, \
Expand Down
Loading
Loading