Merge pull request #14767 from KillianKirilenko/kk-shockmaul

Concussion Maul
This commit is contained in:
Heroman3003
2023-04-15 08:37:48 +10:00
committed by CHOMPStation2
parent b8a9f86017
commit d10da6fb22
10 changed files with 339 additions and 1 deletions

View File

@@ -0,0 +1,276 @@
/obj/item/weapon/melee/shock_maul
name = "concussion maul"
desc = "A heavy-duty concussion hammer, typically used for mining. An iconic weapon for the many uprisings of Mars. It uses a manually engaged concussive-force amplifier unit in the head to multiply impact force, but its weight and the charge up time makes it difficult to use effectively. Devastating if used correctly, but requires skill."
icon_state = "forcemaul"
item_state = "forcemaul"
slot_flags = SLOT_BACK
//stopping power/lethality
force = 35
armor_penetration = 20 //the sheer impact force bypasses quite a bit of armour
var/unwielded_force_divisor = 0.25
var/wielded = 0
var/force_unwielded = 8.75
var/wieldsound = null
var/unwieldsound = null
var/charge_force_mult = 1.75 //damage and AP multiplier on charged hits
var/launch_force = 3 //yeet distance
var/launch_force_unwielded = 1 //awful w/ one hand, but still gets a little distance
var/launch_force_disarm = 1.5 //distance multiplier when swinging in disarm mode, since disarm attacks do half damage
var/weaken_force = 2 //stun power
var/weaken_force_unwielded = 0 //can't stun at all if used onehanded
var/weaken_force_disarm = 1.5 //stun multiplier when in disarm mode
//mining interacts
var/excavation_amount = 200
var/destroy_artefacts = TRUE //sorry, breaks stuff
can_cleave = TRUE //SSSSMITE!
attackspeed = 15 //very slow!!
sharp = FALSE
edge = FALSE
throwforce = 25
flags = NOCONDUCT
w_class = ITEMSIZE_HUGE
drop_sound = 'sound/items/drop/metalweapon.ogg'
pickup_sound = 'sound/items/pickup/metalweapon.ogg'
origin_tech = list(TECH_COMBAT = 5)
attack_verb = list("beaten","slammed","smashed","mauled","hammered","bludgeoned")
var/lightcolor = "#D3FDFD"
var/status = 0 //whether the thing is on or not
var/obj/item/weapon/cell/bcell = null
var/hitcost = 600 //you get 4 hits out of a standard cell
/obj/item/weapon/melee/shock_maul/update_held_icon()
var/mob/living/M = loc
if(istype(M) && M.can_wield_item(src) && is_held_twohanded(M))
wielded = 1
if(status)
force = initial(force)*charge_force_mult
armor_penetration *= charge_force_mult
else
force = initial(force)
armor_penetration = initial(armor_penetration)
launch_force = initial(launch_force)
weaken_force = initial(weaken_force)
name = "[initial(name)] (wielded)"
update_icon()
else
wielded = 0
if(status)
force = force_unwielded*charge_force_mult
armor_penetration *= charge_force_mult
else
force = force_unwielded
armor_penetration = initial(armor_penetration)
launch_force = launch_force_unwielded
weaken_force = weaken_force_unwielded
name = "[initial(name)]"
update_icon()
..()
/obj/item/weapon/melee/shock_maul/New()
..()
update_held_icon()
return
/obj/item/weapon/melee/shock_maul/get_cell()
return bcell
/obj/item/weapon/melee/shock_maul/MouseDrop(obj/over_object as obj)
if(!canremove)
return
if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist
if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
return
if (!( istype(over_object, /obj/screen) ))
return ..()
//makes sure that the thing is equipped, so that we can't drag it into our hand from miles away.
//there's got to be a better way of doing this.
if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
return
if (( usr.restrained() ) || ( usr.stat ))
return
if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src))
return
switch(over_object.name)
if("r_hand")
usr.u_equip(src)
usr.put_in_r_hand(src)
if("l_hand")
usr.u_equip(src)
usr.put_in_l_hand(src)
src.add_fingerprint(usr)
/obj/item/weapon/melee/shock_maul/loaded/New() //this one starts with a cell pre-installed.
..()
bcell = new/obj/item/weapon/cell/device/weapon(src)
update_icon()
return
/obj/item/weapon/melee/shock_maul/proc/deductcharge()
if(status == 1) //Only deducts charge when it's on
if(bcell)
if(bcell.checked_use(hitcost))
return 1
else
return 0
return null
/obj/item/weapon/melee/shock_maul/proc/powercheck()
if(bcell)
if(bcell.charge < hitcost)
status = 0
update_held_icon()
/obj/item/weapon/melee/shock_maul/update_icon()
if(status)
icon_state = "[initial(icon_state)]_active[wielded]"
item_state = icon_state
else if(!bcell)
icon_state = "[initial(icon_state)]_nocell[wielded]"
item_state = icon_state
else
icon_state = "[initial(icon_state)][wielded]"
item_state = icon_state
if(icon_state == "[initial(icon_state)]_active[wielded]")
set_light(2, 1, lightcolor)
else
set_light(0)
/obj/item/weapon/melee/shock_maul/dropped()
..()
if(status)
status = 0
visible_message("<span class='warning'>\The [src]'s grip safety engages!</span>")
update_held_icon()
/obj/item/weapon/melee/shock_maul/examine(mob/user)
. = ..()
if(Adjacent(user))
if(bcell)
. += "<span class='notice'>The concussion maul is [round(bcell.percent())]% charged.</span>"
if(!bcell)
. += "<span class='warning'>The concussion maul does not have a power source installed.</span>"
/obj/item/weapon/melee/shock_maul/attackby(obj/item/weapon/W, mob/user)
if(!user.IsAdvancedToolUser())
return
if(istype(W, /obj/item/weapon/cell))
if(istype(W, /obj/item/weapon/cell/device))
if(!bcell)
user.drop_item()
W.loc = src
bcell = W
to_chat(user, "<span class='notice'>You install a cell in \the [src].</span>")
update_held_icon()
else
to_chat(user, "<span class='notice'>\The [src] already has a cell.</span>")
else
to_chat(user, "<span class='notice'>This cell is not fitted for [src].</span>")
/obj/item/weapon/melee/shock_maul/attack_hand(mob/user as mob)
if(user.get_inactive_hand() == src)
if(!user.IsAdvancedToolUser())
return
else if(bcell)
bcell.update_icon()
user.put_in_hands(bcell)
bcell = null
to_chat(user, "<span class='notice'>You remove the cell from the [src].</span>")
status = 0
update_held_icon()
return
..()
else
return ..()
/obj/item/weapon/melee/shock_maul/attack_self(mob/user)
if(!user.IsAdvancedToolUser())
return
if(!status && bcell && bcell.charge >= hitcost)
if(do_after(user, 2 SECONDS))
status = 1
user.visible_message("<span class='warning'>[user] charges \the [src]!</span>","<span class='warning'>You charge \the [src]. <b>It's hammer time!</b></span>")
playsound(src, "sparks", 75, 1, -1)
update_held_icon()
else if(status)
status = 0
user.visible_message("<span class='notice'>[user] safely disengages \the [src]'s power field.</span>","<span class='notice'>\The [src] is now off.</span>")
update_held_icon()
playsound(src, "sparks", 75, 1, -1)
if(!bcell)
to_chat(user, "<span class='warning'>\The [src] does not have a power source!</span>")
else
to_chat(user, "<span class='warning'>\The [src] is out of charge.</span>")
add_fingerprint(user)
/obj/item/weapon/melee/shock_maul/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity)
if(!proximity) return
..()
if(A && wielded && status)
deductcharge()
status = 0
user.visible_message("<span class='warning'>\The [src] discharges with a thunderous, hair-raising crackle!</span>")
playsound(src, 'sound/weapons/resonator_blast.ogg', 100, 1, -1)
update_held_icon()
if(istype(A,/obj/structure/window))
var/obj/structure/window/W = A
visible_message("<span class='warning'>\The [W] crumples under the force of the impact!</span>")
W.shatter()
else if(istype(A,/obj/structure/barricade))
var/obj/structure/barricade/B = A
B.dismantle()
else if(istype(A,/obj/structure/grille))
qdel(A)
powercheck(hitcost)
/obj/item/weapon/melee/shock_maul/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
. = ..()
if(user.a_intent == I_DISARM)
launch_force *= launch_force_disarm
weaken_force *= weaken_force_disarm
//yeet 'em away, boys!
if(status)
var/atom/target_zone = get_edge_target_turf(user,get_dir(user, target))
if(!target.anchored) //unless they're secured in place, natch
target.throw_at(target_zone, launch_force, 2, user, FALSE)
target.Weaken(weaken_force)
deductcharge()
status = 0
user.visible_message("<span class='warning'>\The [src] discharges with a thunderous, hair-raising crackle!</span>")
playsound(src, 'sound/weapons/resonator_blast.ogg', 100, 1, -1)
update_held_icon()
powercheck(hitcost)
/obj/item/weapon/melee/shock_maul/emp_act(severity)
if(bcell)
bcell.emp_act(severity) //let's not duplicate code everywhere if we don't have to please.
if(status)
status = 0
visible_message("<span class='warning'>\The [src]'s power field hisses and sputters out.</span>")
update_held_icon()
..()
/obj/item/weapon/melee/shock_maul/get_description_interaction()
var/list/results = list()
if(bcell)
results += "[desc_panel_image("offhand")]to remove the weapon cell."
else
results += "[desc_panel_image("weapon cell")]to add a new weapon cell."
results += ..()
return results

View File

@@ -73,6 +73,7 @@
prob(2);/obj/item/weapon/twohanded/fireaxe,\
prob(2);/obj/item/weapon/gun/projectile/luger/brown,\
prob(2);/obj/item/weapon/gun/launcher/crossbow,\
prob(2);/obj/item/weapon/melee/shock_maul,\
/* prob(1);/obj/item/weapon/gun/projectile/automatic/battlerifle,\ */ // Too OP
prob(1);/obj/item/weapon/gun/projectile/deagle/gold,\
prob(1);/obj/item/weapon/gun/energy/imperial,\

View File

@@ -100,6 +100,7 @@
list(pick(/obj/item/weapon/grenade/spawnergrenade/spesscarp, /obj/item/weapon/grenade/spawnergrenade/spider, /obj/item/weapon/grenade/explosive/frag), 7) = 1,
list(/obj/item/weapon/grenade/flashbang/clusterbang, 7) = 1,
list(/obj/item/weapon/card/emag, 11) = 1,
list(/obj/item/weapon/melee/shock_maul, 11) = 5,
list(/obj/item/weapon/storage/backpack/sport/hyd/catchemall, 11) = 1
))
var/path = choice[1]

View File

@@ -97,6 +97,21 @@
new outcropdrop(get_turf(src))
qdel(src)
return
if (istype(W, /obj/item/weapon/melee/shock_maul))
var/obj/item/weapon/melee/shock_maul/S = W
if(!S.wielded || !S.status)
to_chat(user, "<span class='warning'>\The [src] must be wielded in two hands and powered on to be used for mining!</span>")
return
to_chat(user, "<span class='notice'>You pulverize \the [src]!</span>")
for(var/i=0;i<(rand(mindrop,upperdrop));i++)
new outcropdrop(get_turf(src))
playsound(src, 'sound/weapons/resonator_blast.ogg', 100, 1, -1)
user.visible_message("<span class='warning'>\The [S] discharges with a thunderous, hair-raising crackle!</span>")
S.deductcharge()
S.status = 0
S.update_held_icon()
qdel(src)
return
/obj/random/outcrop //In case you want an outcrop without pre-determining the type of ore.
name = "random rock outcrop"

View File

@@ -380,7 +380,6 @@ var/list/mining_overlay_cache = list()
valid_tool = 1
digspeed = P.digspeed
if(valid_tool)
if (sand_dug)
to_chat(user, "<span class='warning'>This area has already been dug.</span>")
@@ -451,6 +450,51 @@ var/list/mining_overlay_cache = list()
to_chat(user, "<span class='notice'>\The [src] has been excavated to a depth of [excavation_level]cm.</span>")
return
if (istype(W, /obj/item/weapon/melee/shock_maul))
if(!istype(user.loc, /turf))
return
var/obj/item/weapon/melee/shock_maul/S = W
if(!S.wielded || !S.status) //if we're not wielded OR not powered up, do nothing
to_chat(user, "<span class='warning'>\The [src] must be wielded in two hands and powered on to be used for mining!</span>")
return
var/newDepth = excavation_level + S.excavation_amount // Used commonly below
//handle any archaeological finds we might uncover
var/fail_message = ""
if(finds && finds.len)
var/datum/find/F = finds[1]
if(newDepth > F.excavation_required) // Digging too deep can break the item. At least you won't summon a Balrog (probably)
fail_message = ". <b>[pick("There is a crunching noise","[S] collides with some different rock","Part of the rock face crumbles away","Something breaks under [S]")]</b>"
wreckfinds(S.destroy_artefacts)
to_chat(user, "<span class='notice'>You smash through \the [src][fail_message].</span>")
if(newDepth >= 200) // This means the rock is mined out fully
if(S.destroy_artefacts)
GetDrilled(0)
else
excavate_turf()
return
excavation_level += S.excavation_amount
update_archeo_overlays(S.excavation_amount)
//drop some rocks
next_rock += S.excavation_amount
while(next_rock > 50)
next_rock -= 50
var/obj/item/weapon/ore/O = new(src)
geologic_data.UpdateNearbyArtifactInfo(src)
O.geologic_data = geologic_data
user.visible_message("<span class='warning'>\The [src] discharges with a thunderous, hair-raising crackle!</span>")
playsound(src, 'sound/weapons/resonator_blast.ogg', 100, 1, -1)
S.deductcharge()
S.status = 0
S.update_held_icon()
if (istype(W, /obj/item/weapon/pickaxe))
if(!istype(user.loc, /turf))
return

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -1502,6 +1502,7 @@
#include "code\game\objects\items\weapons\melee\energy_vr.dm"
#include "code\game\objects\items\weapons\melee\misc.dm"
#include "code\game\objects\items\weapons\melee\misc_vr.dm"
#include "code\game\objects\items\weapons\melee\shock_maul.dm"
#include "code\game\objects\items\weapons\storage\backpack.dm"
#include "code\game\objects\items\weapons\storage\backpack_vr.dm"
#include "code\game\objects\items\weapons\storage\bags.dm"