Files
vgstation13/code/modules/projectiles/projectile/ricochet.dm
SECBATON GRIFFON 0a37d67dc2 Fixes a ton of sentence starts with non capitalised improper nouns. (#37099)
* Fixes capitalisation on throwing stuff in disposals

* in fact, fixes it for everything

* even more

* outta here
2024-09-16 22:37:36 -05:00

404 lines
8.9 KiB
Plaintext

// RICOCHET SHOT
//A projectile that mones only in diagonal, bounces off walls and opaque doors, goes through everything else.
/obj/item/projectile/ricochet
name = "ricochet shot"
damage_type = BURN
flag = "laser"
kill_count = 100
layer = PROJECTILE_LAYER
damage = 30
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "ricochet_head"
animate_movement = 0
linear_movement = 0
custom_impact = 1
var/pos_from = EAST //which side of the turf is the shot coming from
var/pos_to = SOUTH //which side of the turf is the shot heading to
var/bouncin = 0
//list of objects that'll stop the shot, and apply bullet_act
var/list/obj/ricochet_bump = list(
/obj/effect/blob,
/obj/machinery/turret,
/obj/machinery/turretcover,
/obj/mecha,
/obj/structure/reagent_dispensers,
/obj/structure/bed/chair/vehicle,
)
/obj/item/projectile/ricochet/taser
name = "electrode"
damage = 0
nodamage = 1
stun = 10
weaken = 10
stutter = 10
jittery = 20
agony = 10
hitsound = 'sound/weapons/taserhit.ogg'
icon_state = "ricochet_head_t"
/obj/item/projectile/ricochet/OnFired() //The direction and position of the projectile when it spawns depends heavily on where the player clicks.
var/turf/T1 = get_turf(shot_from) //From a single turf, a player can fire the ricochet rifle in 8 different directions.
var/turf/T2 = get_turf(original)
shot_from.update_icon()
var/X = T2.x - T1.x
var/Y = T2.y - T1.y
var/X_spawn = 0
var/Y_spawn = 0
if(X>0)
if(Y>0)
if(X>Y)
pos_from = WEST
pos_to = NORTH
X_spawn = 1
else if(X<Y)
pos_from = SOUTH
pos_to = EAST
Y_spawn = 1
else
if(prob(50))
pos_from = WEST
pos_to = NORTH
X_spawn = 1
else
pos_from = SOUTH
pos_to = EAST
Y_spawn = 1
else if(Y<0)
if(X>(Y*-1))
pos_from = WEST
pos_to = SOUTH
X_spawn = 1
else if(X<(Y*-1))
pos_from = NORTH
pos_to = EAST
Y_spawn = -1
else
if(prob(50))
pos_from = WEST
pos_to = SOUTH
X_spawn = 1
else
pos_from = NORTH
pos_to = EAST
Y_spawn = -1
else if(Y==0)
pos_from = WEST
X_spawn = 1
if(prob(50))
pos_to = NORTH
else
pos_to = SOUTH
else if(X<0)
if(Y>0)
if((X*-1)>Y)
pos_from = EAST
pos_to = NORTH
X_spawn = -1
else if((X*-1)<Y)
pos_from = SOUTH
pos_to = WEST
Y_spawn = 1
else
if(prob(50))
pos_from = EAST
pos_to = NORTH
X_spawn = -1
else
pos_from = SOUTH
pos_to = WEST
Y_spawn = 1
else if(Y<0)
if((X*-1)>(Y*-1))
pos_from = EAST
pos_to = SOUTH
X_spawn = -1
else if((X*-1)<(Y*-1))
pos_from = NORTH
pos_to = WEST
Y_spawn = -1
else
if(prob(50))
pos_from = EAST
pos_to = SOUTH
X_spawn = -1
else
pos_from = NORTH
pos_to = WEST
Y_spawn = -1
else if(Y==0)
pos_from = EAST
X_spawn = -1
if(prob(50))
pos_to = NORTH
else
pos_to = SOUTH
else if(X==0)
if(Y>0)
Y_spawn = 1
pos_from = SOUTH
if(prob(50))
pos_to = EAST
else
pos_to = WEST
else if(Y<0)
Y_spawn = -1
pos_from = NORTH
if(prob(50))
pos_to = EAST
else
pos_to = WEST
else
OnDeath()
loc = null
qdel(src)
return
var/turf/newspawn = locate(T1.x + X_spawn, T1.y + Y_spawn, z)
src.forceMove(newspawn)
update_icon()
..()
/obj/item/projectile/ricochet/update_icon()//8 possible combinations
switch(pos_to)
if(NORTH)
if(pos_from == WEST)
dir = NORTHWEST
else
dir = EAST
if(SOUTH)
if(pos_from == WEST)
dir = WEST
else
dir = SOUTHEAST
if(EAST)
if(pos_from == NORTH)
dir = NORTHEAST
else
dir = SOUTH
if(WEST)
if(pos_from == NORTH)
dir = NORTH
else
dir = SOUTHWEST
/obj/item/projectile/ricochet/proc/bounce()
bouncin = 1
var/obj/structure/ricochet_bump/bump = new(loc)
if(nodamage)
bump.icon_state += "_t"
bump.dir = pos_to
playsound(src, 'sound/items/metal_impact.ogg', 50, 1)
switch(pos_to)
if(NORTH)
if(pos_from == WEST)
pos_to = EAST
else
pos_to = WEST
pos_from = NORTH
if(SOUTH)
if(pos_from == WEST)
pos_to = EAST
else
pos_to = WEST
pos_from = SOUTH
if(EAST)
if(pos_from == NORTH)
pos_to = SOUTH
else
pos_to = NORTH
pos_from = EAST
if(WEST)
if(pos_from == NORTH)
pos_to = SOUTH
else
pos_to = NORTH
pos_from = WEST
/obj/item/projectile/ricochet/proc/bulletdies(var/atom/A = null)
var/obj/effect/overlay/beam/impact = new /obj/effect/overlay/beam(get_turf(src), 10, 0, 'icons/obj/projectiles_impacts.dmi')
if(A)
switch(get_dir(src,A))
if(NORTH)
impact.pixel_y = WORLD_ICON_SIZE/2
if(SOUTH)
impact.pixel_y = -WORLD_ICON_SIZE/2
if(EAST)
impact.pixel_x = WORLD_ICON_SIZE/2
if(WEST)
impact.pixel_x = -WORLD_ICON_SIZE/2
impact.icon_state = "ricochet_hit[nodamage ? "_t" : ""]"
playsound(impact, 'sound/weapons/pierce.ogg', 30, 1)
spawn()
setDensity(FALSE)
invisibility = 101
qdel(src)
OnDeath()
/obj/item/projectile/ricochet/to_bump(atom/A as mob|obj|turf|area)
if(bumped)
return 0
bumped = 1
if(A)
if(istype(A,/turf/) || (istype(A,/obj/machinery/door/) && A.opacity))
bounce()
else if(istype(A,/mob/living))//ricochet shots "never miss"
if(istype(A,/mob/living/carbon/human))
var/mob/living/carbon/human/H = A
if(istype(H.wear_suit,/obj/item/clothing/suit/armor/laserproof))// bwoing!!
visible_message("<span class='warning'>\The [src.name] bounces off \the [A.name]'s [H.wear_suit]!</span>")
bounce()
else
visible_message("<span class='warning'>\The [A.name] is hit by \the [src.name] in the [parse_zone(def_zone)]!</span>")
A.bullet_act(src, def_zone)
admin_warn(A)
bulletdies(A)
else
visible_message("<span class='warning'>\The [A.name] is hit by \the [src.name] in the [parse_zone(def_zone)]!</span>")
A.bullet_act(src, def_zone)
admin_warn(A)
bulletdies(A)
else if(is_type_in_list(A,ricochet_bump))//beware fuel tanks!
visible_message("<span class='warning'>\The [A.name] is hit by \the [src.name]!</span>")
A.bullet_act(src)
bulletdies(A)
else if((istype(A,/obj/structure/window) || istype(A,/obj/machinery/door/window) || istype(A,/obj/machinery/door/firedoor/border_only)) && (A.loc == src.loc))
//all this part is to prevent a bug that causes the shot to go through walls
//if they are one the same tile as a one-directional window/windoor and try to cross them
var/turf/T = get_step(src, pos_to)
if(T.density)
bounce()
else
ricochet_jump()
else
ricochet_jump()
/obj/item/projectile/ricochet/process_step()//unlike laser guns the projectile isn't instantaneous, but it still travels twice as fast as kinetic bullets since it moves twices per ticks
if(src.loc)
if(kill_count < 1)
bulletdies()
kill_count--
for(var/i=1;i<=2;i++)
ricochet_movement()
update_icon()
sleep(1)
/obj/item/projectile/ricochet/proc/ricochet_step(var/phase=1)
var/obj/structure/ricochet_trail/trail = new(loc)
if(nodamage)
trail.icon_state += "_t"
switch(pos_to)
if(NORTH)
if(pos_from == WEST)
trail.dir = NORTH
else
trail.dir = EAST
if(SOUTH)
if(pos_from == WEST)
trail.dir = WEST
else
trail.dir = SOUTH
if(EAST)
if(pos_from == NORTH)
trail.dir = EAST
else
trail.dir = SOUTH
if(WEST)
if(pos_from == NORTH)
trail.dir = NORTH
else
trail.dir = WEST
if(phase)
current = get_step(src, pos_to)
step_towards(src, current)
else
var/turf/T = get_step(src, pos_to)
loc = T
if((bumped && !phase) || bouncin)
return
switch(pos_to)
if(NORTH)
if(pos_from == WEST)
pos_to = EAST
else
pos_to = WEST
pos_from = SOUTH
if(SOUTH)
if(pos_from == WEST)
pos_to = EAST
else
pos_to = WEST
pos_from = NORTH
if(EAST)
if(pos_from == NORTH)
pos_to = SOUTH
else
pos_to = NORTH
pos_from = WEST
if(WEST)
if(pos_from == NORTH)
pos_to = SOUTH
else
pos_to = NORTH
pos_from = EAST
/obj/item/projectile/ricochet/proc/ricochet_movement()//movement through empty space
if((x == 1 || x == world.maxx || y == 1 || y == world.maxy))
bulletdies()
return
ricochet_step()
bumped = 0
bouncin = 0
/obj/item/projectile/ricochet/proc/ricochet_jump()//movement through dense objects
if((x == 1 || x == world.maxx || y == 1 || y == world.maxy))
bulletdies()
return
ricochet_step(0)
/obj/structure/ricochet_trail //so pretty
name = "ricochet shot"
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "ricochet"
opacity = 0
density = 0
anchored = 1
layer = BELOW_PROJECTILE_LAYER
/obj/structure/ricochet_trail/dissolvable()
return 0
/obj/structure/ricochet_trail/New()
. = ..()
spawn(30)
qdel(src)
/obj/structure/ricochet_bump //oh so pretty
name = "ricochet shot"
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "ricochet_bounce"
opacity = 0
density = 0
anchored = 1
layer = ABOVE_PROJECTILE_LAYER
/obj/structure/ricochet_bump/dissolvable()
return 0
/obj/structure/ricochet_bump/New()
. = ..()
spawn(30)
qdel(src)