mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-22 19:47:22 +01:00
Crossbows and piescannons
This commit is contained in:
@@ -200,4 +200,22 @@
|
||||
time = 15
|
||||
reqs = list(/obj/item/stack/sheet/wood = 1,
|
||||
/obj/item/stack/cable_coil = 5)
|
||||
tools = list(/obj/item/weapon/kitchen/knife) // Gotta carve the wood into handles
|
||||
tools = list(/obj/item/weapon/kitchen/knife) // Gotta carve the wood into handles
|
||||
|
||||
/datum/table_recipe/makeshift_bolt
|
||||
name = "Makeshift Bolt"
|
||||
result = /obj/item/weapon/arrow/rod
|
||||
time = 15
|
||||
reqs = list(/obj/item/stack/rods = 1)
|
||||
tools = list(/obj/item/weapon/weldingtool)
|
||||
|
||||
/datum/table_recipe/crossbow
|
||||
name = "Powered Crossbow"
|
||||
result = /obj/item/weapon/gun/throw/crossbow
|
||||
time = 300
|
||||
reqs = list(/obj/item/stack/rods = 3,
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
/obj/item/stack/sheet/mineral/plastic = 3,
|
||||
/obj/item/stack/sheet/wood = 5)
|
||||
tools = list(/obj/item/weapon/weldingtool,
|
||||
/obj/item/weapon/screwdriver)
|
||||
|
||||
+3
-2
@@ -24,10 +24,12 @@
|
||||
qdel(D)
|
||||
rockets = null
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/rocketlauncher/update_icon()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/rocketlauncher/attackby(obj/item/I as obj, mob/user as mob, params)
|
||||
/obj/item/weapon/gun/rocketlauncher/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/ammo_casing/rocket))
|
||||
if(rockets.len < max_rockets)
|
||||
user.drop_item()
|
||||
@@ -52,6 +54,5 @@
|
||||
log_game("[key_name_admin(user)] used a rocket launcher ([name]).")
|
||||
rockets -= I
|
||||
qdel(I)
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>[src] is empty.</span>")
|
||||
@@ -0,0 +1,93 @@
|
||||
/obj/item/weapon/gun/throw
|
||||
name = "abstract item thrower"
|
||||
desc = "This shouldn't be here, yell at a coder."
|
||||
fire_sound = 'sound/weapons/punchmiss.ogg'
|
||||
fire_sound_text = "thwock"
|
||||
|
||||
var/obj/item/to_launch
|
||||
var/list/valid_projectile_type
|
||||
var/max_capacity = 1
|
||||
var/list/loaded_projectiles = list()
|
||||
|
||||
var/projectile_speed = 1
|
||||
var/projectile_range = 1
|
||||
|
||||
/obj/item/weapon/gun/throw/proc/notify_ammo_count(mob/user)
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/throw/proc/get_throwrange()
|
||||
return projectile_speed
|
||||
|
||||
/obj/item/weapon/gun/throw/proc/get_throwspeed()
|
||||
return projectile_range
|
||||
|
||||
/obj/item/weapon/gun/throw/proc/modify_projectile(obj/item/I, on_chamber = 0)
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/throw/proc/get_ammocount(include_loaded = 1)
|
||||
var/count = loaded_projectiles.len
|
||||
if(include_loaded && to_launch)
|
||||
count++
|
||||
return count
|
||||
|
||||
/obj/item/weapon/gun/throw/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>It is [to_launch ? "loaded with \a [to_launch]" : "not loaded"].</span>")
|
||||
notify_ammo_count(user)
|
||||
|
||||
/obj/item/weapon/gun/throw/Destroy()
|
||||
qdel(to_launch)
|
||||
to_launch = null
|
||||
for(var/atom/A in loaded_projectiles)
|
||||
qdel(A)
|
||||
loaded_projectiles = null
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/throw/update_icon()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/throw/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, valid_projectile_type) && !(I.flags & NODROP))
|
||||
if(get_ammocount() < max_capacity)
|
||||
user.drop_item()
|
||||
I.forceMove(src)
|
||||
loaded_projectiles += I
|
||||
to_chat(user, "<span class='notice'>You load [I] into [src].</span>")
|
||||
if(!to_launch)
|
||||
process_chamber()
|
||||
notify_ammo_count(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] cannot hold any more projectiles.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You cannot load [I] into [src]!</span>")
|
||||
|
||||
/obj/item/weapon/gun/throw/process_chamber()
|
||||
if(!to_launch && loaded_projectiles.len)
|
||||
to_launch = loaded_projectiles[1]
|
||||
loaded_projectiles -= to_launch
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/throw/can_shoot()
|
||||
if(to_launch)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/gun/throw/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override)
|
||||
add_fingerprint(user)
|
||||
if(semicd)
|
||||
return
|
||||
|
||||
var/obj/item/I = to_launch
|
||||
I.forceMove(get_turf(src))
|
||||
to_launch = null
|
||||
modify_projectile(I)
|
||||
playsound(user, fire_sound, 50, 1)
|
||||
I.throw_at(target, get_throwrange(), get_throwspeed(), user, 1)
|
||||
message_admins("[key_name_admin(user)] fired \a [I] from a [src].")
|
||||
log_game("[key_name_admin(user)] used \a [src].")
|
||||
process_chamber()
|
||||
|
||||
semicd = 1
|
||||
spawn(fire_delay)
|
||||
semicd = 0
|
||||
@@ -0,0 +1,181 @@
|
||||
#define XBOW_TENSION_20 "20%"
|
||||
#define XBOW_TENSION_40 "40%"
|
||||
#define XBOW_TENSION_60 "60%"
|
||||
#define XBOW_TENSION_80 "80%"
|
||||
#define XBOW_TENSION_FULL "100%"
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow
|
||||
name = "powered crossbow"
|
||||
desc = "A modern twist on an old classic. Pick up that can."
|
||||
icon_state = "crossbow"
|
||||
item_state = "crossbow-solid"
|
||||
fire_sound_text = "a solid thunk"
|
||||
fire_delay = 25
|
||||
|
||||
valid_projectile_type = /obj/item/weapon/arrow
|
||||
|
||||
var/tension = 0
|
||||
var/drawtension = 5
|
||||
var/maxtension = 5
|
||||
var/speed_multiplier = 5
|
||||
var/range_multiplier = 3
|
||||
var/obj/item/weapon/stock_parts/cell/cell = null // Used for firing superheated rods.
|
||||
var/list/possible_tensions = list(XBOW_TENSION_20, XBOW_TENSION_40, XBOW_TENSION_60, XBOW_TENSION_80, XBOW_TENSION_FULL)
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/emp_act(severity)
|
||||
if(cell && severity)
|
||||
emp_act(severity)
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/update_icon()
|
||||
if(!tension)
|
||||
if(!to_launch)
|
||||
icon_state = "[initial(icon_state)]"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-nocked"
|
||||
else
|
||||
icon_state = "[initial(icon_state)]-drawn"
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/examine(mob/user)
|
||||
..()
|
||||
if(cell)
|
||||
to_chat(user, "<span class='notice'>\A [cell] is mounted onto [src]. Battery cell charge: [cell.charge]/[cell.maxcharge]")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>It has an empty mount for a battery cell.</span>")
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/modify_projectile(obj/item/I, on_chamber = 0)
|
||||
if(cell && on_chamber && istype(I, /obj/item/weapon/arrow/rod))
|
||||
var/obj/item/weapon/arrow/rod/R = I
|
||||
visible_message("<span class='danger'>[R] plinks and crackles as it begins to glow red-hot.</span>")
|
||||
R.throwforce = 15
|
||||
R.superheated = 1
|
||||
cell.use(500)
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/get_throwspeed()
|
||||
return tension * speed_multiplier
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/get_throwrange()
|
||||
return tension * range_multiplier
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/process_chamber()
|
||||
..()
|
||||
if(to_launch)
|
||||
modify_projectile(to_launch, 1)
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/attack_self(mob/living/user)
|
||||
if(tension)
|
||||
if(to_launch)
|
||||
user.visible_message("<span class='notice'>[user] relaxes the tension on [src]'s string and removes [to_launch].</span>","<span class='notice'>You relax the tension on [src]'s string and remove [to_launch].</span>")
|
||||
to_launch.forceMove(get_turf(src))
|
||||
var/obj/item/weapon/arrow/A = to_launch
|
||||
to_launch = null
|
||||
A.removed()
|
||||
process_chamber()
|
||||
else
|
||||
user.visible_message("<span class='notice'>[user] relaxes the tension on [src]'s string.</span>","<span class='notice'>You relax the tension on [src]'s string.</span>")
|
||||
tension = 0
|
||||
update_icon()
|
||||
else
|
||||
draw(user)
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/proc/draw(mob/living/user)
|
||||
if(user.incapacitated())
|
||||
return
|
||||
if(!to_launch)
|
||||
to_chat(user, "<span class='warning'>You can't draw [src] without a bolt nocked.</span>")
|
||||
return
|
||||
|
||||
user.visible_message("[user] begins to draw back the string of [src].","You begin to draw back the string of [src].")
|
||||
if(do_after(user, 25 * drawtension, target = user))
|
||||
tension = drawtension
|
||||
user.visible_message("[usr] draws back the string of [src]!","[src] clunks as you draw the string to its maximum tension!!")
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
if(istype(W, /obj/item/weapon/stock_parts/cell))
|
||||
if(!cell)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
cell = W
|
||||
to_chat(user, "<span class='notice'>You jam [cell] into [src] and wire it to the firing coil.</span>")
|
||||
process_chamber()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] already has a cell installed.</span>")
|
||||
else if(istype(W, /obj/item/weapon/screwdriver))
|
||||
if(cell)
|
||||
cell.loc = get_turf(src)
|
||||
to_chat(user, "<span class='notice'>You jimmy [cell] out of [src] with [W].</span>")
|
||||
cell = null
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] doesn't have a cell installed.</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/verb/set_tension()
|
||||
set name = "Adjust Tension"
|
||||
set category = "Object"
|
||||
set src in range(0)
|
||||
|
||||
var/mob/user = usr
|
||||
if(user.incapacitated())
|
||||
return
|
||||
var/choice = input("Select tension to draw to:", "[src]", XBOW_TENSION_FULL) as null|anything in possible_tensions
|
||||
if(!choice)
|
||||
return
|
||||
|
||||
switch(choice)
|
||||
if(XBOW_TENSION_20)
|
||||
drawtension = Ceiling(0.2 * maxtension)
|
||||
if(XBOW_TENSION_40)
|
||||
drawtension = Ceiling(0.4 * maxtension)
|
||||
if(XBOW_TENSION_60)
|
||||
drawtension = Ceiling(0.6 * maxtension)
|
||||
if(XBOW_TENSION_80)
|
||||
drawtension = Ceiling(0.8 * maxtension)
|
||||
if(XBOW_TENSION_FULL)
|
||||
drawtension = maxtension
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override)
|
||||
..()
|
||||
tension = 0
|
||||
update_icon()
|
||||
/obj/item/weapon/gun/throw/crossbow/french
|
||||
name = "french powered crossbow"
|
||||
icon_state = "fcrossbow"
|
||||
valid_projectile_type = /obj/item/weapon/reagent_containers/food/snacks/baguette
|
||||
|
||||
/obj/item/weapon/gun/throw/crossbow/french/modify_projectile(obj/item/I, on_chamber = 0)
|
||||
return
|
||||
|
||||
/obj/item/weapon/arrow
|
||||
name = "bolt"
|
||||
desc = "It's got a tip for you - get the point?"
|
||||
icon_state = "bolt"
|
||||
item_state = "bolt"
|
||||
throwforce = 20
|
||||
w_class = 3.0
|
||||
sharp = 1
|
||||
edge = 0
|
||||
|
||||
/obj/item/weapon/arrow/proc/removed() //Helper for metal rods falling apart.
|
||||
return
|
||||
|
||||
/obj/item/weapon/arrow/rod
|
||||
name = "makeshift bolt"
|
||||
desc = "A sharpened metal rod that can be fired out of a crossbow."
|
||||
icon_state = "metal-rod"
|
||||
throwforce = 8
|
||||
var/superheated = 0
|
||||
|
||||
/obj/item/weapon/arrow/rod/removed()
|
||||
if(superheated) // The rod has been superheated - we don't want it to be useable when removed from the bow.
|
||||
visible_message("[src] shatters into a scattering of overstressed metal shards as it leaves the crossbow.")
|
||||
var/obj/item/weapon/shard/shrapnel/S = new /obj/item/weapon/shard/shrapnel
|
||||
S.loc = get_turf(src)
|
||||
qdel(src)
|
||||
|
||||
#undef XBOW_TENSION_20
|
||||
#undef XBOW_TENSION_40
|
||||
#undef XBOW_TENSION_60
|
||||
#undef XBOW_TENSION_80
|
||||
#undef XBOW_TENSION_FULL
|
||||
@@ -0,0 +1,36 @@
|
||||
/obj/item/weapon/gun/throw/piecannon
|
||||
name = "pie cannon"
|
||||
desc = "A projectile weapon that fires pies."
|
||||
icon_state = "piecannon"
|
||||
w_class = 5
|
||||
throw_speed = 2
|
||||
throw_range = 3
|
||||
force = 5
|
||||
|
||||
clumsy_check = 0
|
||||
valid_projectile_type = /obj/item/weapon/reagent_containers/food/snacks/pie
|
||||
max_capacity = 5
|
||||
projectile_speed = 2
|
||||
projectile_range = 30
|
||||
|
||||
|
||||
/obj/item/weapon/gun/throw/piecannon/New()
|
||||
..()
|
||||
for(var/i in 1 to max_capacity)
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/pie/P = new /obj/item/weapon/reagent_containers/food/snacks/pie(src)
|
||||
loaded_projectiles += P
|
||||
process_chamber()
|
||||
|
||||
/obj/item/weapon/gun/throw/piecannon/notify_ammo_count(mob/user)
|
||||
to_chat(user, "<span class='notice'>[src] has [get_ammocount()] of [max_capacity] pies left.")
|
||||
|
||||
/obj/item/weapon/gun/throw/piecannon/update_icon()
|
||||
if(to_launch)
|
||||
icon_state = "piecannon1"
|
||||
else
|
||||
icon_state = "piecannon0"
|
||||
item_state = icon_state
|
||||
|
||||
/obj/item/weapon/gun/throw/piecannon/process_chamber()
|
||||
..()
|
||||
update_icon()
|
||||
@@ -178,6 +178,7 @@
|
||||
stun = 5
|
||||
forcedodge = 1
|
||||
nodamage = 1
|
||||
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
|
||||
hitsound = 'sound/items/bikehorn.ogg'
|
||||
icon = 'icons/obj/harvest.dmi'
|
||||
icon_state = "banana"
|
||||
|
||||
Reference in New Issue
Block a user