New bullet types, projectile rewrite

* Refactors projectile Bump()
* Converts projectile_type var strings to paths
* Reorganizes bullet projectile paths
* Made a pass through all the bullet_act() definitions. Mainly ensured that damage_type is checked when dealing damage to certain objects. Removed stupid /turf bullet_act() override, replaced with on_hit() overrides on the relevant projectiles.

* Adds shotgun pellets projectile. Adds Raptor's shotgun slug sprite.
* Gives stunshots more of their own identity, refluffs them as taser cartridges for shotguns. They still aren't obtainable anywhere unless spawned.
* Makes projectiles pass through girders and cultgirders with a certain probability, unless the girder itself was clicked.
* Projectiles are also able to pass through grilles. Low damage projectiles have a chance to be blocked by grilles. High damage projectiles have a chance to have some damage absorbed by the grille.
* Makes projectiles for blanks invisible.
* Adds flash bullet types
* Adds support for 'penetrating' projectiles
* Swaps .45 and 9mm projectile types. .45s hit slightly harder, 9mils have more ammo capacity.
This commit is contained in:
unknown
2015-02-04 17:56:43 -05:00
committed by mwerezak
parent c9eae483c6
commit 39b467c9da
41 changed files with 542 additions and 283 deletions

View File

@@ -221,6 +221,9 @@ update_flag
return
/obj/machinery/portable_atmospherics/canister/bullet_act(var/obj/item/projectile/Proj)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
if(Proj.damage)
src.health -= round(Proj.damage / 2)
healthcheck()

View File

@@ -81,6 +81,8 @@
..()
/obj/machinery/bot/bullet_act(var/obj/item/projectile/Proj)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
health -= Proj.damage
..()
healthcheck()

View File

@@ -89,7 +89,7 @@
return
/obj/machinery/turret/bullet_act(var/obj/item/projectile/Proj)
if(Proj.damage_type == HALLOSS)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
take_damage(Proj.damage)
..()
@@ -299,7 +299,7 @@
popping = 0
/obj/machinery/turret/bullet_act(var/obj/item/projectile/Proj)
if(Proj.damage_type == HALLOSS)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
src.health -= Proj.damage
..()

View File

@@ -1083,6 +1083,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/passenger/destroy()
for(var/atom/movable/AM in src)
AM.forceMove(get_turf(src))
AM << "<span class='danger'>You tumble out of the destroyed [src.name]!"
return ..()
/obj/item/mecha_parts/mecha_equipment/tool/passenger/Exit(atom/movable/O)

View File

@@ -199,7 +199,7 @@
name = "\improper LBX AC 10 \"Scattershot\""
icon_state = "mecha_scatter"
equip_cooldown = 20
projectile = /obj/item/projectile/bullet/midbullet
projectile = /obj/item/projectile/bullet/pistol/medium
fire_sound = 'sound/weapons/Gunshot.ogg'
fire_volume = 80
projectiles = 40
@@ -211,7 +211,7 @@
name = "\improper Ultra AC 2"
icon_state = "mecha_uac2"
equip_cooldown = 10
projectile = /obj/item/projectile/bullet/weakbullet
projectile = /obj/item/projectile/bullet/pistol/medium
fire_sound = 'sound/weapons/Gunshot.ogg'
projectiles = 300
projectiles_per_shot = 3

View File

@@ -507,8 +507,25 @@
if(istype(Proj, /obj/item/projectile/beam/pulse))
ignore_threshold = 1
src.take_damage(Proj.damage, Proj.flag)
if(prob(25)) spark_system.start()
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold)
//AP projectiles have a chance to cause additional damage
if(Proj.penetrating)
var/distance = get_dist(Proj.starting, get_turf(loc))
var/hit_occupant = 1 //only allow the occupant to be hit once
for(var/i in 1 to min(Proj.penetrating, round(Proj.damage/15)))
if(src.occupant && hit_occupant && prob(20))
Proj.attack_mob(src.occupant, distance)
hit_occupant = 0
else
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT), 1)
Proj.penetrating--
if(prob(15))
break //give a chance to exit early
Proj.on_hit(src)
return

View File

@@ -233,6 +233,21 @@ steam.start() -- spawns the effect
return 0
return 1
/////////////////////////////////////////////
// Illumination
/////////////////////////////////////////////
/obj/effect/effect/smoke/illumination
name = "illumination"
opacity = 0
icon = 'icons/effects/effects.dmi'
icon_state = "sparks"
/obj/effect/effect/smoke/illumination/New(var/newloc, var/brightness=15, var/lifetime=10)
time_to_live=lifetime
..()
SetLuminosity(brightness)
/////////////////////////////////////////////
// Bad smoke
/////////////////////////////////////////////

View File

@@ -21,7 +21,7 @@
B.health -= damage
B.update_icon()
new/obj/effect/effect/smoke/flashbang(src.loc)
new/obj/effect/effect/smoke/illumination(src.loc, brightness=15)
del(src)
return
@@ -100,16 +100,6 @@
M << "\red Your ears start to ring!"
M.update_icons()
/obj/effect/effect/smoke/flashbang
name = "illumination"
time_to_live = 10
opacity = 0
icon_state = "sparks"
/obj/effect/effect/smoke/flashbang/New()
..()
SetLuminosity(15)
/obj/item/weapon/grenade/flashbang/clusterbang//Created by Polymorph, fixed by Sieve
desc = "Use of this weapon may constiute a war crime in your area, consult your local captain."
name = "clusterbang"

View File

@@ -161,6 +161,9 @@
del(src)
/obj/structure/closet/bullet_act(var/obj/item/projectile/Proj)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
health -= Proj.damage
..()
if(health <= 0)

View File

@@ -5,6 +5,7 @@
layer = 2
var/state = 0
var/health = 200
var/cover = 50 //how much cover the girder provides against projectiles.
/obj/structure/girder/attack_generic(var/mob/user, var/damage, var/attack_message = "smashes apart", var/wallbreaker)
if(!damage || !wallbreaker)
@@ -14,13 +15,19 @@
return 1
/obj/structure/girder/bullet_act(var/obj/item/projectile/Proj)
//Girders only provide partial cover. There's a chance that the projectiles will just pass through. (unless you are trying to shoot the girder)
if(Proj.original != src && !prob(cover))
return -1 //pass through
//Tasers and the like should not damage girders.
if(Proj.damage_type == HALLOSS || Proj.damage_type == TOX || Proj.damage_type == CLONE)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
if(istype(Proj, /obj/item/projectile/beam))
health -= Proj.damage
var/damage = Proj.damage
if(!istype(Proj, /obj/item/projectile/beam))
damage *= 0.4 //non beams do reduced damage
health -= damage
..()
if(health <= 0)
new /obj/item/stack/sheet/metal(get_turf(src))
@@ -209,11 +216,13 @@
icon_state = "displaced"
anchored = 0
health = 50
cover = 25
/obj/structure/girder/reinforced
icon_state = "reinforced"
state = 2
health = 500
cover = 80
/obj/structure/cultgirder
icon= 'icons/obj/cult.dmi'
@@ -222,6 +231,7 @@
density = 1
layer = 2
var/health = 250
var/cover = 70
/obj/structure/cultgirder/attack_generic(var/mob/user, var/damage, var/attack_message = "smashes apart", var/wallbreaker)
if(!damage || !wallbreaker)
@@ -258,6 +268,14 @@
dismantle()
/obj/structure/cultgirder/bullet_act(var/obj/item/projectile/Proj) //No beam check- How else will you destroy the cult girder with silver bullets?????
//Girders only provide partial cover. There's a chance that the projectiles will just pass through. (unless you are trying to shoot the girder)
if(Proj.original != src && !prob(cover))
return -1 //pass through
//Tasers and the like should not damage cultgirders.
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
health -= Proj.damage
..()
if(health <= 0)

View File

@@ -59,16 +59,33 @@
return !density
/obj/structure/grille/bullet_act(var/obj/item/projectile/Proj)
if(!Proj) return
//Tasers and the like should not damage grilles.
if(Proj.damage_type == HALLOSS)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
src.health -= Proj.damage*0.2
healthcheck()
return 0
//Flimsy grilles aren't so great at stopping projectiles. However they can absorb some of the impact
var/damage = Proj.damage
var/passthrough
if(damage > 30)
passthrough = 1
if(prob(20))
Proj.damage *= 0.5 //weaken the projectile
else
//weaker bullets are affected to a greater extent
if(prob(20))
passthrough = 0
else
Proj.damage *= 0.5 //weaken the projectile
passthrough = 1
if(passthrough)
. = -1
damage *= 0.1 //if the bullet passes through then the grille avoids most of the damage
src.health -= damage*0.2
spawn(0) healthcheck() //spawn to make sure we return properly if the grille is deleted
/obj/structure/grille/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(iswirecutter(W))

View File

@@ -38,6 +38,9 @@
return 0
/obj/structure/inflatable/bullet_act(var/obj/item/projectile/Proj)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
health -= Proj.damage
..()
if(health <= 0)

View File

@@ -1,7 +1,7 @@
//wip wip wup
/obj/structure/mirror
name = "\improper SalonPro Nano-Mirror(TM)"
desc = "The leading technology in hair salon products, utilizing nano-machinery to style your hair just right."
name = "mirror"
desc = "A SalonPro Nano-Mirror(TM) brand mirror! The leading technology in hair salon products, utilizing nano-machinery to style your hair just right."
icon = 'icons/obj/watercloset.dmi'
icon_state = "mirror"
density = 0
@@ -70,6 +70,9 @@
/obj/structure/mirror/bullet_act(var/obj/item/projectile/Proj)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
if(prob(Proj.damage * 2))
if(!shattered)
shatter()

View File

@@ -100,7 +100,7 @@
/obj/structure/window/bullet_act(var/obj/item/projectile/Proj)
//Tasers and the like should not damage windows.
if(Proj.damage_type == HALLOSS)
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
..()

View File

@@ -54,18 +54,6 @@
step(user.pulling, get_dir(user.pulling.loc, src))
return 1
/turf/bullet_act(var/obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/beam/pulse))
src.ex_act(2)
..()
return 0
/turf/bullet_act(var/obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/bullet/gyro))
explosion(src, -1, 0, 2)
..()
return 0
/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
if(movement_disabled && usr.ckey != movement_disabled_exception)
usr << "\red Movement is admin-disabled." //This is to identify lag problems

View File

@@ -28,7 +28,7 @@
var/obj/item/weapon/rig/suit = H.back
if(istype(suit) && suit.cell && suit.cell.charge >= 250)
suit.cell.use(250)
var/prog_path = text2path(projectile_type)
var/prog_path = projectile_type
in_chamber = new prog_path(src)
return 1
return 0
@@ -45,7 +45,7 @@
var/obj/item/weapon/rig/suit = H.back
if(istype(suit) && suit.cell && suit.cell.charge >= 250)
suit.cell.use(250)
var/prog_path = text2path(projectile_type)
var/prog_path = projectile_type
in_chamber = new prog_path(src)
return 1
return 0

View File

@@ -24,7 +24,7 @@ emp_act
if(!(def_zone in list("chest", "groin")))
reflectchance /= 2
if(prob(reflectchance))
visible_message("\red <B>The [P.name] gets reflected by [src]'s [wear_suit.name]!</B>")
visible_message("\red <B>\The [P] gets reflected by \the [src]'s [wear_suit.name]!</B>")
// Find a turf near or on the original location to bounce to
if(P.starting)
@@ -33,12 +33,7 @@ emp_act
var/turf/curloc = get_turf(src)
// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.current = curloc
P.firer = src
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
P.redirect(new_x, new_y, curloc, src)
return -1 // complete projectile permutation
@@ -47,9 +42,9 @@ emp_act
var/armor = getarmor_organ(organ, "bullet")
if((P.embed && prob(20 + max(P.damage - armor, -10))))
var/obj/item/weapon/shard/shrapnel/SP = new()
(SP.name) = "[P.name] shrapnel"
(SP.desc) = "[SP.desc] It looks like it was fired from [P.shot_from]."
(SP.loc) = organ
SP.name = (P.name != "shrapnel")? "[P.name] shrapnel" : "shrapnel"
SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]."
SP.loc = organ
organ.embed(SP)
return (..(P , def_zone))

View File

@@ -56,7 +56,7 @@
signaler.signal()
//Stun Beams
if(istype(P, /obj/item/projectile/beam/stun) || istype(P, /obj/item/projectile/bullet/stunshot))
if(P.taser_effect)
stun_effect_act(0, P.agony, def_zone, P)
src <<"\red You have been hit by [P]!"
del P

View File

@@ -166,8 +166,8 @@
var/reflectchance = 80 - round(P.damage/3)
if(prob(reflectchance))
adjustBruteLoss(P.damage * 0.5)
visible_message("<span class='danger'>The [P.name] gets reflected by [src]'s shell!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [src]'s shell!</span>")
visible_message("<span class='danger'>\The [P] was reflected by \the [src]'s shell!</span>", \
"<span class='userdanger'>\The [P] was reflected by \the [src]'s shell!</span>")
// Find a turf near or on the original location to bounce to
if(P.starting)
@@ -176,12 +176,7 @@
var/turf/curloc = get_turf(src)
// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.current = curloc
P.firer = src
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
P.redirect(new_x, new_y, curloc, src)
return -1 // complete projectile permutation

View File

@@ -108,7 +108,7 @@
icon_living = "syndicateranged"
casingtype = /obj/item/ammo_casing/a12mm
projectilesound = 'sound/weapons/Gunshot_smg.ogg'
projectiletype = /obj/item/projectile/bullet/midbullet2
projectiletype = /obj/item/projectile/bullet/pistol/medium
weapon1 = /obj/item/weapon/gun/projectile/automatic/c20r

View File

@@ -8,13 +8,13 @@
throwforce = 1
w_class = 1.0
var/caliber = "" //Which kind of guns it can be loaded into
var/projectile_type = ""//The bullet type to create when New() is called
var/projectile_type //The bullet type to create when New() is called
var/obj/item/projectile/BB = null //The loaded bullet
New()
..()
if(projectile_type)
if(ispath(projectile_type))
BB = new projectile_type(src)
pixel_x = rand(-10.0, 10)
pixel_y = rand(-10.0, 10)

View File

@@ -56,7 +56,7 @@
icon_state = "9x19p"
origin_tech = "combat=2"
ammo_type = "/obj/item/ammo_casing/c9mm"
max_ammo = 8
max_ammo = 10
multiple_sprites = 1
/obj/item/ammo_magazine/mc9mm/empty

View File

@@ -1,113 +1,129 @@
/obj/item/ammo_casing/a357
desc = "A .357 bullet casing."
caliber = "357"
projectile_type = "/obj/item/projectile/bullet"
projectile_type = /obj/item/projectile/bullet/pistol/strong
/obj/item/ammo_casing/a50
desc = "A .50AE bullet casing."
caliber = ".50"
projectile_type = "/obj/item/projectile/bullet"
/obj/item/ammo_casing/a418
desc = "A .418 bullet casing."
caliber = "357"
projectile_type = "/obj/item/projectile/bullet/suffocationbullet"
projectile_type = /obj/item/projectile/bullet/pistol/strong
/obj/item/ammo_casing/a75
desc = "A .75 bullet casing."
desc = "A 20mm bullet casing."
caliber = "75"
projectile_type = "/obj/item/projectile/bullet/gyro"
/obj/item/ammo_casing/a666
desc = "A .666 bullet casing."
caliber = "357"
projectile_type = "/obj/item/projectile/bullet/cyanideround"
projectile_type = /obj/item/projectile/bullet/gyro
/obj/item/ammo_casing/c38
desc = "A .38 bullet casing."
caliber = "38"
projectile_type = "/obj/item/projectile/bullet/weakbullet"
projectile_type = /obj/item/projectile/bullet/pistol/rubber
/obj/item/ammo_casing/c9mm
desc = "A 9mm bullet casing."
caliber = "9mm"
projectile_type = "/obj/item/projectile/bullet/midbullet2"
projectile_type = /obj/item/projectile/bullet/pistol
/obj/item/ammo_casing/c45
desc = "A .45 bullet casing."
caliber = ".45"
projectile_type = "/obj/item/projectile/bullet/midbullet"
projectile_type = /obj/item/projectile/bullet/pistol/medium
/obj/item/ammo_casing/c45r
desc = "A .45 rubber bullet casing."
caliber = ".45"
projectile_type = "/obj/item/projectile/bullet/weakbullet/rubber"
projectile_type = /obj/item/projectile/bullet/pistol/rubber
/obj/item/ammo_casing/c45f
desc = "A .45 flash shell casing."
caliber = ".45"
projectile_type = /obj/item/projectile/energy/flash
/obj/item/ammo_casing/a12mm
desc = "A 12mm bullet casing."
caliber = "12mm"
projectile_type = "/obj/item/projectile/bullet/midbullet2"
projectile_type = /obj/item/projectile/bullet/pistol/medium
/obj/item/ammo_casing/shotgun
name = "shotgun slug"
desc = "A 12 gauge slug."
icon_state = "slshell"
caliber = "shotgun"
projectile_type = /obj/item/projectile/bullet/shotgun
matter = list("metal" = 12500)
/obj/item/ammo_casing/shotgun/pellet
name = "shotgun shell"
desc = "A 12 gauge shell."
icon_state = "gshell"
caliber = "shotgun"
projectile_type = "/obj/item/projectile/bullet"
projectile_type = /obj/item/projectile/bullet/pellet/shotgun
matter = list("metal" = 12500)
/obj/item/ammo_casing/shotgun/blank
name = "shotgun shell"
desc = "A blank shell."
icon_state = "blshell"
projectile_type = "/obj/item/projectile/bullet/chameleon"
projectile_type = /obj/item/projectile/bullet/blank
matter = list("metal" = 250)
/obj/item/ammo_casing/shotgun/beanbag
name = "beanbag shell"
desc = "A weak beanbag shell."
desc = "A beanbag shell."
icon_state = "bshell"
projectile_type = "/obj/item/projectile/bullet/weakbullet/beanbag"
projectile_type = /obj/item/projectile/bullet/shotgun/beanbag
matter = list("metal" = 500)
/obj/item/ammo_casing/shotgun/stunshell
name = "stun shell"
desc = "A stunning shell."
desc = "A 12 gauge taser cartridge."
icon_state = "stunshell"
projectile_type = "/obj/item/projectile/bullet/stunshot"
matter = list("metal" = 2500)
projectile_type = /obj/item/projectile/energy/electrode/stunshot
matter = list("metal" = 1250, "glass" = 1250)
/obj/item/ammo_casing/shotgun/flash
name = "flash shell"
desc = "A flash shell used to provide illumination."
icon_state = "fshell"
projectile_type = /obj/item/projectile/energy/flash/flare
matter = list("metal" = 250, "glass" = 250)
/obj/item/ammo_casing/shotgun/dart
name = "shotgun darts"
name = "shotgun dart"
desc = "A dart for use in shotguns."
icon_state = "dart"
projectile_type = "/obj/item/projectile/energy/dart"
projectile_type = /obj/item/projectile/energy/dart
matter = list("metal" = 12500)
/obj/item/ammo_casing/a762
desc = "A 7.62 bullet casing."
desc = "A 7.62mm bullet casing."
caliber = "a762"
projectile_type = "/obj/item/projectile/bullet/a762"
projectile_type = /obj/item/projectile/bullet/rifle/a762
/obj/item/ammo_casing/a145
name = "\improper AP shell casing"
desc = "A 14.5mm AP shell."
icon_state = "slshell"
projectile_type = /obj/item/projectile/bullet/rifle/a145
/obj/item/ammo_casing/rocket
name = "rocket shell"
desc = "A high explosive designed to be fired from a launcher."
icon_state = "rocketshell"
projectile_type = "/obj/item/missile"
projectile_type = /obj/item/missile
caliber = "rocket"
/obj/item/ammo_casing/chameleon
name = "chameleon bullets"
desc = "A set of bullets for the Chameleon Gun."
projectile_type = "/obj/item/projectile/bullet/chameleon"
projectile_type = /obj/item/projectile/bullet/chameleon
caliber = ".45"
/obj/item/ammo_casing/a418
desc = "A .418 bullet casing."
caliber = "357"
projectile_type = /obj/item/projectile/bullet/suffocationbullet
/obj/item/ammo_casing/a666
desc = "A .666 bullet casing."
caliber = "357"
projectile_type = /obj/item/projectile/bullet/cyanideround

View File

@@ -77,6 +77,8 @@
/obj/item/weapon/gun/proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)//TODO: go over this
//Exclude lasertag guns from the CLUMSY check.
if(!user) return
if(clumsy_check)
if(istype(user, /mob/living))
var/mob/living/M = user
@@ -97,11 +99,6 @@
add_fingerprint(user)
var/turf/curloc = get_turf(user)
var/turf/targloc = get_turf(target)
if (!istype(targloc) || !istype(curloc))
return
if(!special_check(user))
return
@@ -116,18 +113,6 @@
if(!in_chamber)
return
in_chamber.firer = user
in_chamber.def_zone = user.zone_sel.selecting
if(targloc == curloc)
user.bullet_act(in_chamber)
del(in_chamber)
update_icon()
return
if(recoil)
spawn()
shake_camera(user, recoil + 1, recoil)
if(silenced)
playsound(user, fire_sound, 10, 1)
else
@@ -136,34 +121,46 @@
"<span class='warning'>You fire [src][reflex ? "by reflex":""]!</span>", \
"You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!")
in_chamber.original = target
in_chamber.loc = get_turf(user)
in_chamber.starting = get_turf(user)
in_chamber.shot_from = src
user.next_move = world.time + 4
in_chamber.silenced = silenced
in_chamber.current = curloc
in_chamber.yo = targloc.y - curloc.y
in_chamber.xo = targloc.x - curloc.x
var/x_offset = 0
var/y_offset = 0
if(istype(user, /mob/living/carbon))
var/mob/living/carbon/mob = user
if(mob.shock_stage > 120)
in_chamber.yo += rand(-2,2)
in_chamber.xo += rand(-2,2)
y_offset = rand(-2,2)
x_offset = rand(-2,2)
else if(mob.shock_stage > 70)
in_chamber.yo += rand(-1,1)
in_chamber.xo += rand(-1,1)
y_offset = rand(-1,1)
x_offset = rand(-1,1)
var/p_x
var/p_y
if(params)
var/list/mouse_control = params2list(params)
if(mouse_control["icon-x"])
in_chamber.p_x = text2num(mouse_control["icon-x"])
p_x = text2num(mouse_control["icon-x"])
if(mouse_control["icon-y"])
in_chamber.p_y = text2num(mouse_control["icon-y"])
p_y = text2num(mouse_control["icon-y"])
spawn()
if(in_chamber)
in_chamber.process()
var/fail = in_chamber.launch(
target = target,
user = user,
launcher = src,
target_zone = user.zone_sel.selecting,
x_offset = x_offset,
y_offset = y_offset,
px = p_x,
py = p_y
)
if(fail) return
if(recoil)
spawn()
shake_camera(user, recoil + 1, recoil)
sleep(1)
in_chamber = null

View File

@@ -73,7 +73,7 @@
recoil = 1
force = 10
projectile_type = "/obj/item/projectile/energy/sonic"
projectile_type = /obj/item/projectile/energy/sonic
cell_type = "/obj/item/weapon/cell/super"
fire_delay = 40
fire_sound = 'sound/effects/basscannon.ogg'

View File

@@ -7,7 +7,7 @@
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
var/charge_cost = 100 //How much energy is needed to fire.
var/cell_type = "/obj/item/weapon/cell"
var/projectile_type = "/obj/item/projectile/beam/practice"
var/projectile_type = /obj/item/projectile/beam/practice
var/modifystate
emp_act(severity)
@@ -30,7 +30,7 @@
if(in_chamber) return 1
if(!power_supply) return 0
if(!power_supply.use(charge_cost)) return 0
if(!projectile_type) return 0
if(!ispath(projectile_type)) return 0
in_chamber = new projectile_type(src)
return 1

View File

@@ -6,7 +6,7 @@
fire_sound = 'sound/weapons/Taser.ogg'
charge_cost = 100 //How much energy is needed to fire.
projectile_type = "/obj/item/projectile/beam/stun"
projectile_type = /obj/item/projectile/beam/stun
origin_tech = "combat=3;magnets=2"
modifystate = "energystun"
@@ -20,14 +20,14 @@
charge_cost = 100
fire_sound = 'sound/weapons/Laser.ogg'
user << "\red [src.name] is now set to kill."
projectile_type = "/obj/item/projectile/beam"
projectile_type = /obj/item/projectile/beam
modifystate = "energykill"
if(1)
mode = 0
charge_cost = 100
fire_sound = 'sound/weapons/Taser.ogg'
user << "\red [src.name] is now set to stun."
projectile_type = "/obj/item/projectile/beam/stun"
projectile_type = /obj/item/projectile/beam/stun
modifystate = "energystun"
update_icon()
if(user.l_hand == src)

View File

@@ -6,7 +6,7 @@
force = 10
fire_sound = 'sound/weapons/pulse.ogg'
charge_cost = 200
projectile_type = "/obj/item/projectile/beam/pulse"
projectile_type = /obj/item/projectile/beam/pulse
cell_type = "/obj/item/weapon/cell/super"
var/mode = 2
fire_delay = 25
@@ -18,19 +18,19 @@
charge_cost = 100
fire_sound = 'sound/weapons/Taser.ogg'
user << "\red [src.name] is now set to stun."
projectile_type = "/obj/item/projectile/beam/stun"
projectile_type = /obj/item/projectile/beam/stun
if(0)
mode = 1
charge_cost = 100
fire_sound = 'sound/weapons/Laser.ogg'
user << "\red [src.name] is now set to kill."
projectile_type = "/obj/item/projectile/beam"
projectile_type = /obj/item/projectile/beam
if(1)
mode = 2
charge_cost = 200
fire_sound = 'sound/weapons/pulse.ogg'
user << "\red [src.name] is now set to DESTROY."
projectile_type = "/obj/item/projectile/beam/pulse"
projectile_type = /obj/item/projectile/beam/pulse
return
isHandgun()

View File

@@ -5,7 +5,7 @@
item_state = null //so the human update icon uses the icon_state instead.
fire_sound = 'sound/weapons/Taser.ogg'
charge_cost = 100
projectile_type = "/obj/item/projectile/beam/stun"
projectile_type = /obj/item/projectile/beam/stun
cell_type = "/obj/item/weapon/cell/crap"
/obj/item/weapon/gun/energy/taser/cyborg
@@ -47,7 +47,7 @@
fire_sound = 'sound/weapons/Taser.ogg'
origin_tech = "combat=3;materials=3;powerstorage=2"
charge_cost = 125
projectile_type = "/obj/item/projectile/beam/stun"
projectile_type = /obj/item/projectile/beam/stun
cell_type = "/obj/item/weapon/cell"
@@ -62,7 +62,7 @@
origin_tech = "combat=2;magnets=2;syndicate=5"
silenced = 1
fire_sound = 'sound/weapons/Genhit.ogg'
projectile_type = "/obj/item/projectile/energy/bolt"
projectile_type = /obj/item/projectile/energy/bolt
cell_type = "/obj/item/weapon/cell/crap"
var/charge_tick = 0
@@ -91,7 +91,7 @@
/obj/item/weapon/gun/energy/crossbow/ninja
name = "energy dart thrower"
projectile_type = "/obj/item/projectile/energy/dart"
projectile_type = /obj/item/projectile/energy/dart
/obj/item/weapon/gun/energy/crossbow/largecrossbow
name = "Energy Crossbow"
@@ -99,4 +99,4 @@
w_class = 4.0
force = 10
matter = list("metal" = 200000)
projectile_type = "/obj/item/projectile/energy/bolt/large"
projectile_type = /obj/item/projectile/energy/bolt/large

View File

@@ -4,7 +4,7 @@
/obj/item/weapon/gun/projectile
name = "revolver"
desc = "A classic revolver. Uses 357 ammo"
desc = "A classic revolver. Uses .357 ammo"
icon_state = "revolver"
caliber = "357"
origin_tech = "combat=2;materials=2"
@@ -16,12 +16,14 @@
var/max_shells = 7
var/load_method = SPEEDLOADER //0 = Single shells or quick loader, 1 = box, 2 = magazine
var/obj/item/ammo_magazine/empty_mag = null
var/mag_type = null
/obj/item/weapon/gun/projectile/New()
..()
for(var/i = 1, i <= max_shells, i++)
loaded += new ammo_type(src)
if(load_method == MAGAZINE)
empty_mag = new mag_type(src)
update_icon()
return

View File

@@ -3,7 +3,7 @@
desc = "A lightweight, fast firing gun. Uses 9mm rounds."
icon_state = "saber" //ugly
w_class = 3.0
max_shells = 18
max_shells = 22
caliber = "9mm"
origin_tech = "combat=4;materials=2"
ammo_type = "/obj/item/ammo_casing/c9mm"
@@ -14,6 +14,9 @@
isHandgun()
return 0
/obj/item/weapon/gun/projectile/automatic/test
name = "test gun"
ammo_type = "/obj/item/ammo_casing/a145"
/obj/item/weapon/gun/projectile/automatic/mini_uzi
name = "\improper Uzi"
@@ -40,15 +43,8 @@
origin_tech = "combat=5;materials=2;syndicate=8"
ammo_type = "/obj/item/ammo_casing/a12mm"
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
load_method = 2
New()
..()
empty_mag = new /obj/item/ammo_magazine/a12mm/empty(src)
update_icon()
return
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/a12mm/empty
afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
@@ -80,7 +76,7 @@
origin_tech = "combat=5;materials=1;syndicate=2"
ammo_type = "/obj/item/ammo_casing/a762"
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
load_method = 2
load_method = MAGAZINE
var/cover_open = 0
var/mag_inserted = 1

View File

@@ -19,13 +19,8 @@
max_shells = 7
caliber = ".50"
ammo_type ="/obj/item/ammo_casing/a50"
load_method = 2
New()
..()
empty_mag = new /obj/item/ammo_magazine/a50/empty(src)
update_icon()
return
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/a50/empty
afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
@@ -59,13 +54,8 @@
fire_sound = 'sound/effects/Explosion1.ogg'
origin_tech = "combat=3"
ammo_type = "/obj/item/ammo_casing/a75"
load_method = 2
New()
..()
empty_mag = new /obj/item/ammo_magazine/a75/empty(src)
update_icon()
return
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/a75/empty
afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
@@ -89,17 +79,13 @@
desc = "A small, easily concealable gun. Uses 9mm rounds."
icon_state = "pistol"
w_class = 2
max_shells = 8
max_shells = 10
caliber = "9mm"
silenced = 0
origin_tech = "combat=2;materials=2;syndicate=2"
ammo_type = "/obj/item/ammo_casing/c9mm"
load_method = 2
/obj/item/weapon/gun/projectile/pistol/New()
..()
empty_mag = new /obj/item/ammo_magazine/mc9mm/empty(src)
return
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/mc9mm/empty
/obj/item/weapon/gun/projectile/pistol/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()

View File

@@ -7,7 +7,6 @@
origin_tech = "combat=2;materials=2"
ammo_type = "/obj/item/ammo_casing/c38"
special_check(var/mob/living/carbon/human/M)
if(caliber == initial(caliber))
return 1
@@ -77,12 +76,8 @@
max_shells = 7
caliber = ".45"
ammo_type = "/obj/item/ammo_casing/c45r"
load_method = 2
/obj/item/weapon/gun/projectile/detective/semiauto/New()
..()
empty_mag = new /obj/item/ammo_magazine/c45r/empty(src)
return
load_method = MAGAZINE
mag_type = /obj/item/ammo_magazine/c45r/empty
/obj/item/weapon/gun/projectile/detective/semiauto/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
@@ -130,7 +125,7 @@
var/num_loaded = 0
if(istype(A, /obj/item/ammo_magazine))
if((load_method == 2) && loaded.len) return
if((load_method == MAGAZINE) && loaded.len) return
var/obj/item/ammo_magazine/AM = A
for(var/obj/item/ammo_casing/AC in AM.stored_ammo)
if(getAmmo() > 0 || loaded.len >= max_shells)

View File

@@ -36,8 +36,10 @@
var/damage = 10
var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here
var/nodamage = 0 //Determines if the projectile will skip any damage inflictions
var/taser_effect = 0 //If set then the projectile will apply it's agony damage using stun_effect_act() to mobs it hits, and other damage will be ignored
var/flag = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid
var/projectile_type = "/obj/item/projectile"
var/projectile_type = /obj/item/projectile
var/penetrating = 0 //If greater than zero, the projectile will pass through dense objects as specified by on_penetrate()
var/kill_count = 50 //This will de-increment every process(). When 0, it will delete the projectile.
//Effects
var/stun = 0
@@ -50,7 +52,8 @@
var/agony = 0
var/embed = 0 // whether or not the projectile can embed itself in the mob
proc/on_hit(var/atom/target, var/blocked = 0)
//TODO: make it so this is called more reliably, instead of sometimes by bullet_act() and sometimes not
proc/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null)
if(blocked >= 2) return 0//Full block
if(!isliving(target)) return 0
if(isanimal(target)) return 0
@@ -58,6 +61,14 @@
L.apply_effects(stun, weaken, paralyze, irradiate, stutter, eyeblur, drowsy, agony, blocked) // add in AGONY!
return 1
//called when the projectile stops flying because it collided with something
proc/on_impact(var/atom/A)
return
//return 1 if the projectile should be allowed to pass through after all, 0 if not.
proc/on_penetrate(var/atom/A)
return 1
proc/check_fire(var/mob/living/target as mob, var/mob/living/user as mob) //Checks if you can hit them or not.
if(!istype(target) || !istype(user))
return 0
@@ -70,50 +81,128 @@
del(in_chamber) //No need for it anymore
return output //Send it back to the gun!
Bump(atom/A as mob|obj|turf|area)
if(A == firer)
loc = A.loc
return 0 //cannot shoot yourself
//called to launch a projectile from a gun
proc/launch(atom/target, mob/user, obj/item/weapon/gun/launcher, var/target_zone, var/x_offset=0, var/y_offset=0, var/px=null, var/py=null)
var/turf/curloc = get_turf(user)
var/turf/targloc = get_turf(target)
if (!istype(targloc) || !istype(curloc))
return 1
if(bumped) return 0
var/forcedodge = 0 // force the projectile to pass
firer = user
def_zone = user.zone_sel.selecting
bumped = 1
if(firer && istype(A, /mob))
var/mob/M = A
if(!istype(A, /mob/living))
loc = A.loc
return 0// nope.avi
if(user == target) //Shooting yourself
user.bullet_act(src, target_zone)
del(src)
return 0
if(targloc == curloc) //Shooting the ground
targloc.bullet_act(src, target_zone)
del(src)
return 0
var/distance = get_dist(starting,loc)
var/miss_modifier = -30
original = target
loc = curloc
starting = curloc
current = curloc
yo = targloc.y - curloc.y + y_offset
xo = targloc.x - curloc.x + x_offset
if(!isnull(py)) p_y = py
if(!isnull(px)) p_x = px
shot_from = launcher
silenced = launcher.silenced
spawn()
process()
return 0
//Used to change the direction of the projectile in flight.
proc/redirect(var/new_x, var/new_y, var/atom/starting_loc, var/mob/new_firer=null)
original = locate(new_x, new_y, src.z)
starting = starting_loc
current = starting_loc
if(new_firer)
firer = src
yo = new_y - starting_loc.y
xo = new_x - starting_loc.x
//Called when the projectile intercepts a mob. Returns 1 if the projectile hit the mob, 0 if it missed and should keep flying.
proc/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier = -30)
//accuracy bonus from aiming
if (istype(shot_from, /obj/item/weapon/gun)) //If you aim at someone beforehead, it'll hit more often.
var/obj/item/weapon/gun/daddy = shot_from //Kinda balanced by fact you need like 2 seconds to aim
if (daddy.target && original in daddy.target) //As opposed to no-delay pew pew
miss_modifier += -30
def_zone = get_zone_with_miss_chance(def_zone, M, miss_modifier + 15*distance)
if(!def_zone)
visible_message("\blue \The [src] misses [M] narrowly!")
forcedodge = -1
else
//roll to-hit
var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, max(miss_modifier + 15*distance, 0))
if(!hit_zone)
visible_message("<span class='notice'>\The [src] misses [target_mob] narrowly!</span>")
return 0
//set def_zone, so if the projectile ends up hitting someone else later (to be implemented), it is more likely to hit the same part
def_zone = hit_zone
//hit messages
if(silenced)
M << "\red You've been shot in the [parse_zone(def_zone)] by the [src.name]!"
target_mob << "<span class='danger'>You've been hit in the [parse_zone(def_zone)] by \the [src]!</span>"
else
visible_message("\red [A.name] is hit by the [src.name] in the [parse_zone(def_zone)]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter
if(istype(firer, /mob))
M.attack_log += "\[[time_stamp()]\] <b>[firer]/[firer.ckey]</b> shot <b>[M]/[M.ckey]</b> with a <b>[src.type]</b>"
firer.attack_log += "\[[time_stamp()]\] <b>[firer]/[firer.ckey]</b> shot <b>[M]/[M.ckey]</b> with a <b>[src.type]</b>"
msg_admin_attack("[firer] ([firer.ckey]) shot [M] ([M.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
else
M.attack_log += "\[[time_stamp()]\] <b>UNKNOWN SUBJECT (No longer exists)</b> shot <b>[M]/[M.ckey]</b> with a <b>[src]</b>"
msg_admin_attack("UNKNOWN shot [M] ([M.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
visible_message("<span class='danger'>\The [target_mob] is hit by \the [src] in the [parse_zone(def_zone)]!</span>")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter
if(A)
if (!forcedodge)
forcedodge = A.bullet_act(src, def_zone) // searches for return value
if(forcedodge == -1) // the bullet passes through a dense object!
//admin logs
if(istype(firer, /mob))
target_mob.attack_log += "\[[time_stamp()]\] <b>[firer]/[firer.ckey]</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src.type]</b>"
firer.attack_log += "\[[time_stamp()]\] <b>[firer]/[firer.ckey]</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src.type]</b>"
msg_admin_attack("[firer] ([firer.ckey]) shot [target_mob] ([target_mob.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
else
target_mob.attack_log += "\[[time_stamp()]\] <b>UNKNOWN SUBJECT (No longer exists)</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src]</b>"
msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
//sometimes bullet_act() will want the projectile to continue flying
if (target_mob.bullet_act(src, def_zone) == -1)
return 0
return 1
Bump(atom/A as mob|obj|turf|area)
if(A == src)
return 0 //no
if(A == firer)
loc = A.loc
return 0 //cannot shoot yourself
if(bumped)
return 0
var/passthrough = 0 //if the projectile should continue flying
var/distance = get_dist(starting,loc)
bumped = 1
if(ismob(A))
var/mob/M = A
if(istype(A, /mob/living))
passthrough = !attack_mob(M, distance)
else
passthrough = 1 //so ghosts don't stop bullets
else
passthrough = (A.bullet_act(src, def_zone) == -1) //backwards compatibility
if(isturf(A))
for(var/obj/O in A)
O.bullet_act(src)
for(var/mob/M in A)
attack_mob(M, distance)
//penetrating projectiles can pass through things that otherwise would not let them
if(penetrating > 0)
if(on_penetrate(A))
passthrough = 1
penetrating--
//the bullet passes through a dense object!
if(passthrough)
bumped = 0 //reset bumped variable!
if(istype(A, /turf))
loc = A
@@ -121,26 +210,23 @@
loc = A.loc
permutated.Add(A)
return 0
if(istype(A,/turf))
for(var/obj/O in A)
O.bullet_act(src)
for(var/mob/M in A)
M.bullet_act(src, def_zone)
//stop flying
on_impact(A)
density = 0
invisibility = 101
del(src)
return 1
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0)) return 1
if(istype(mover, /obj/item/projectile))
return prob(95)
return prob(95) //ha
else
return 1
process()
if(kill_count < 1)
del(src)

View File

@@ -105,6 +105,10 @@ var/list/beam_master = list()
icon_state = "u_laser"
damage = 50
/obj/item/projectile/beam/pulse/on_hit(var/atom/target, var/blocked = 0)
if(isturf(target))
target.ex_act(2)
..()
/obj/item/projectile/beam/emitter
name = "emitter beam"
@@ -169,5 +173,6 @@ var/list/beam_master = list()
name = "stun beam"
icon_state = "stun"
nodamage = 1
taser_effect = 1
agony = 40
damage_type = HALLOSS

View File

@@ -8,62 +8,153 @@
embed = 1
sharp = 1
on_hit(var/atom/target, var/blocked = 0)
/obj/item/projectile/bullet/on_hit(var/atom/target, var/blocked = 0)
if (..(target, blocked))
var/mob/living/L = target
shake_camera(L, 3, 2)
/obj/item/projectile/bullet/weakbullet // "rubber" bullets
/obj/item/projectile/bullet/on_penetrate(var/atom/A)
if(!A) return 1 //if whatever it was got destroyed when we hit it, then I guess we can just keep going
if(istype(A, /obj/mecha))
return 1 //mecha have their own penetration handling
if(ismob(A))
if(iscarbon(A))
//squishy mobs absorb KE
if (damage <= 20) return 0
damage *= 0.7
return 1
if(istype(A, /obj/machinery) || istype(A, /obj/structure))
var/chance = 15
if(istype(A, /turf/simulated/wall))
var/turf/simulated/wall/W = A
chance = round(damage/W.damage_cap*100)
else if(istype(A, /obj/machinery/door))
var/obj/machinery/door/D = A
chance = round(damage/D.maxhealth*100)
else if(istype(A, /obj/structure/girder) || istype(A, /obj/structure/cultgirder))
chance = 100
if(prob(chance))
if(A.opacity)
//display a message so that people on the other side aren't so confused
A.visible_message("<span class='warning'>\The [src] pierces through \the [A]!")
return 1
return 0
//For projectiles that actually represent clouds of projectiles
/obj/item/projectile/bullet/pellet
name = "shrapnel" //'shrapnel' sounds more dangerous (i.e. cooler) than 'pellet'
damage = 20
//icon_state = "bullet" //TODO: would be nice to have it's own icon state
var/pellets = 4 //number of pellets
var/range_step = 2 //effective pellet count decreases every few tiles
var/base_spread = 90 //lower means the pellets spread more across body parts
var/spread_step = 10 //higher means the pellets spread more across body parts with distance
/obj/item/projectile/bullet/pellet/Bumped()
. = ..()
bumped = 0 //can hit all mobs in a tile. pellets is decremented inside attack_mob so this should be fine.
/obj/item/projectile/bullet/pellet/attack_mob(var/mob/living/target_mob, var/distance)
if (pellets < 0) return 1
var/pellet_loss = round((distance - 1)/range_step) //pellets lost due to distance
var/total_pellets = max(pellets - pellet_loss, 1)
var/spread = max(base_spread - (spread_step*distance), 0)
var/hits = 0
for (var/i in 1 to total_pellets)
//pellet hits spread out across different zones, but 'aim at' the targeted zone with higher probability
//whether the pellet actually hits the def_zone or a different zone should still be determined by the parent using get_zone_with_miss_chance().
var/old_zone = def_zone
def_zone = ran_zone(def_zone, spread)
if (..()) hits++
def_zone = old_zone //restore the original zone the projectile was aimed at
pellets -= hits //each hit reduces the number of pellets left
if (hits >= total_pellets || pellets <= 0)
return 1
return 0
/* short-casing projectiles, like the kind used in pistols or SMGs */
/obj/item/projectile/bullet/pistol
damage = 20
/obj/item/projectile/bullet/pistol/medium
damage = 25
/obj/item/projectile/bullet/pistol/strong //revolvers and matebas
damage = 60
/obj/item/projectile/bullet/pistol/rubber //"rubber" bullets
name = "rubber bullet"
damage = 10
agony = 40
embed = 0
sharp = 0
/obj/item/projectile/bullet/weakbullet/beanbag //because beanbags are not bullets
/* shotgun projectiles */
/obj/item/projectile/bullet/shotgun
name = "slug"
damage = 60
/obj/item/projectile/bullet/shotgun/beanbag //because beanbags are not bullets
name = "beanbag"
damage = 20
agony = 60
embed = 0
sharp = 0
/obj/item/projectile/bullet/weakbullet/rubber
name = "rubber bullet"
//Should do about 80 damage at 1 tile distance (adjacent), and 50 damage at 3 tiles distance.
//Overall less damage than slugs in exchange for more damage at very close range and more embedding
/obj/item/projectile/bullet/pellet/shotgun
name = "shrapnel"
damage = 13
pellets = 6
range_step = 1
spread_step = 10
/obj/item/projectile/bullet/midbullet
damage = 20
/* "Rifle" rounds */
/obj/item/projectile/bullet/midbullet2
/obj/item/projectile/bullet/rifle/a762
damage = 25
/obj/item/projectile/bullet/rifle/a145
damage = 90
penetrating = 5
/* Miscellaneous */
/obj/item/projectile/bullet/suffocationbullet//How does this even work?
name = "co bullet"
damage = 20
damage_type = OXY
/obj/item/projectile/bullet/cyanideround
name = "poison bullet"
damage = 40
damage_type = TOX
/obj/item/projectile/bullet/burstbullet//I think this one needs something for the on hit
/obj/item/projectile/bullet/burstbullet
name = "exploding bullet"
damage = 20
embed = 0
edge = 1
/obj/item/projectile/bullet/gyro/on_hit(var/atom/target, var/blocked = 0)
if(isturf(target))
explosion(target, -1, 0, 2)
..()
/obj/item/projectile/bullet/stunshot
name = "stunshot"
damage = 5
agony = 80
stutter = 10
/obj/item/projectile/bullet/blank
invisibility = 101
damage = 1
embed = 0
sharp = 0
/obj/item/projectile/bullet/a762
damage = 25
/obj/item/projectile/bullet/chameleon
damage = 1 // stop trying to murderbone with a fake gun dumbass!!!

View File

@@ -6,6 +6,35 @@
flag = "energy"
//releases a very short burst of light on impact, mainly used to blind people
/obj/item/projectile/energy/flash
name = "shell" //a chemical filled shell or something
icon_state = "bullet"
damage = 5
var/flash_range = 1
var/brightness = 5
var/light_duration = 10
/obj/item/projectile/energy/flash/on_impact()
var/turf/T = get_turf(src)
if(!istype(T)) return
src.visible_message("<span class='warning'>\The [src] explodes in a bright flash!</span>")
for (var/mob/living/carbon/M in viewers(T, flash_range))
if(M.eyecheck() < 1)
flick("e_flash", M.flash)
playsound(src, 'sound/effects/snap.ogg', 50, 1)
new/obj/effect/effect/smoke/illumination(src.loc, brightness=max(flash_range*2, brightness), lifetime=light_duration)
//blinds people like the flash round, but can also be used for temporary illumination
/obj/item/projectile/energy/flash/flare
damage = 10
flash_range = 1
brightness = 7 //similar to a flare
light_duration = 150
/obj/item/projectile/energy/electrode
name = "electrode"
icon_state = "spark"
@@ -15,11 +44,16 @@
weaken = 10
stutter = 10
*/
taser_effect = 1
agony = 40
damage_type = HALLOSS
//Damage will be handled on the MOB side, to prevent window shattering.
/obj/item/projectile/energy/electrode/stunshot
name = "stunshot"
damage = 5
taser_effect = 1
agony = 80
/obj/item/projectile/energy/declone
name = "declone"

View File

@@ -146,7 +146,7 @@
/obj/structure/reagent_dispensers/fueltank/bullet_act(var/obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet))
if(Proj.damage_type == BRUTE || Proj.damage_type == BURN)
if(istype(Proj.firer))
message_admins("[key_name_admin(Proj.firer)] shot fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[loc.x];Y=[loc.y];Z=[loc.z]'>JMP</a>).")
log_game("[key_name(Proj.firer)] shot fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]).")

View File

@@ -26,7 +26,7 @@ datum/chemical_reaction/coolant
reagents.add_reagent("coolant",1000)
/obj/structure/reagent_dispensers/coolanttank/bullet_act(var/obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet))
if(Proj.damage_type == BRUTE || Proj.damage_type == BURN)
if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) )
explode()

View File

@@ -114,6 +114,7 @@
..()
/obj/vehicle/bullet_act(var/obj/item/projectile/Proj)
if (Proj.damage_type == BRUTE || Proj.damage_type == BURN)
health -= Proj.damage
..()
healthcheck()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB