Skip to content

Commit 2c79d31

Browse files
authored
Merge pull request #5246 from MistakeNot4892/port/impacteffects
Porting various projectile impact effects and sounds from Polaris.
2 parents 89e439b + 4c80fd1 commit 2c79d31

File tree

20 files changed

+218
-41
lines changed

20 files changed

+218
-41
lines changed

code/_global_vars/sound.dm

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,11 @@ var/global/list/sweeping_sound = list(
128128
'sound/foley/sweeping5.ogg',
129129
'sound/foley/sweeping6.ogg',
130130
'sound/foley/sweeping7.ogg',
131-
)
131+
)
132+
133+
var/global/list/ricochet_sound = list(
134+
'sound/weapons/guns/ricochet1.ogg',
135+
'sound/weapons/guns/ricochet2.ogg',
136+
'sound/weapons/guns/ricochet3.ogg',
137+
'sound/weapons/guns/ricochet4.ogg'
138+
)

code/game/objects/effects/temporary.dm

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//temporary visual effects
22
/obj/effect/temp_visual
33
icon_state = "nothing"
4+
icon = 'icons/effects/effects.dmi'
45
anchored = TRUE
56
layer = ABOVE_HUMAN_LAYER
67
mouse_opacity = MOUSE_OPACITY_UNCLICKABLE
@@ -14,12 +15,10 @@
1415
QDEL_IN(src, duration)
1516

1617
/obj/effect/temp_visual/emp_burst
17-
icon = 'icons/effects/effects.dmi'
1818
icon_state = "empdisable"
1919

2020
/obj/effect/temp_visual/emppulse
2121
name = "electromagnetic pulse"
22-
icon = 'icons/effects/effects.dmi'
2322
icon_state = "emppulse"
2423
duration = 2 SECONDS
2524

@@ -49,4 +48,52 @@
4948
target_pixel_x = 16
5049
if(set_dir & WEST)
5150
target_pixel_x = -16
52-
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
51+
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
52+
53+
/obj/effect/temp_visual/impact_effect
54+
plane = ABOVE_LIGHTING_PLANE
55+
layer = ABOVE_LIGHTING_LAYER // So they're visible even in a shootout in maint.
56+
duration = 5
57+
icon_state = "impact_bullet"
58+
icon = 'icons/effects/impact_effects.dmi'
59+
60+
/obj/effect/temp_visual/impact_effect/Initialize(mapload, obj/item/projectile/P, _x, _y)
61+
default_pixel_x = _x
62+
default_pixel_y = _y
63+
pixel_x = default_pixel_x
64+
pixel_y = default_pixel_y
65+
. = ..()
66+
67+
/obj/effect/temp_visual/impact_effect/red_laser
68+
icon_state = "impact_laser"
69+
duration = 4
70+
71+
/obj/effect/temp_visual/impact_effect/blue_laser
72+
icon_state = "impact_laser_blue"
73+
duration = 4
74+
75+
/obj/effect/temp_visual/impact_effect/green_laser
76+
icon_state = "impact_laser_green"
77+
duration = 4
78+
79+
/obj/effect/temp_visual/impact_effect/purple_laser
80+
icon_state = "impact_laser_purple"
81+
duration = 4
82+
83+
// Colors itself based on the projectile.
84+
// Checks light_color and color.
85+
/obj/effect/temp_visual/impact_effect/monochrome_laser
86+
icon_state = "impact_laser_monochrome"
87+
duration = 4
88+
89+
/obj/effect/temp_visual/impact_effect/monochrome_laser/Initialize(mapload, obj/item/projectile/P, x, y)
90+
if(istype(P))
91+
if(P.light_color)
92+
color = P.light_color
93+
else if(P.color)
94+
color = P.color
95+
return ..()
96+
97+
/obj/effect/temp_visual/impact_effect/ion
98+
icon_state = "shieldsparkles"
99+
duration = 6

code/game/sound.dm

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -141,29 +141,29 @@ var/global/const/FALLOFF_SOUNDS = 0.5
141141
/proc/get_sfx(soundin)
142142
if(istext(soundin))
143143
switch(soundin)
144-
if ("shatter") soundin = pick(global.shatter_sound)
145-
if ("explosion") soundin = pick(global.explosion_sound)
146-
if ("sparks") soundin = pick(global.spark_sound)
147-
if ("rustle") soundin = pick(global.rustle_sound)
148-
if ("punch") soundin = pick(global.punch_sound)
144+
if ("shatter") soundin = pick(global.shatter_sound)
145+
if ("explosion") soundin = pick(global.explosion_sound)
146+
if ("sparks") soundin = pick(global.spark_sound)
147+
if ("rustle") soundin = pick(global.rustle_sound)
148+
if ("punch") soundin = pick(global.punch_sound)
149149
if ("light_strike") soundin = pick(global.light_strike_sound)
150-
if ("clownstep") soundin = pick(global.clown_sound)
151-
if ("swing_hit") soundin = pick(global.swing_hit_sound)
152-
if ("hiss") soundin = pick(global.hiss_sound)
153-
if ("pageturn") soundin = pick(global.page_sound)
154-
if ("fracture") soundin = pick(global.fracture_sound)
155-
if ("light_bic") soundin = pick(global.lighter_sound)
156-
if ("keyboard") soundin = pick(global.keyboard_sound)
157-
if ("keystroke") soundin = pick(global.keystroke_sound)
158-
if ("switch") soundin = pick(global.switch_sound)
159-
if ("button") soundin = pick(global.button_sound)
160-
if ("chop") soundin = pick(global.chop_sound)
161-
if ("glasscrack") soundin = pick(global.glasscrack_sound)
162-
if ("tray_hit") soundin = pick(global.tray_hit_sound)
163-
if ("sweeping") soundin = pick(global.sweeping_sound)
150+
if ("clownstep") soundin = pick(global.clown_sound)
151+
if ("swing_hit") soundin = pick(global.swing_hit_sound)
152+
if ("hiss") soundin = pick(global.hiss_sound)
153+
if ("pageturn") soundin = pick(global.page_sound)
154+
if ("fracture") soundin = pick(global.fracture_sound)
155+
if ("light_bic") soundin = pick(global.lighter_sound)
156+
if ("keyboard") soundin = pick(global.keyboard_sound)
157+
if ("keystroke") soundin = pick(global.keystroke_sound)
158+
if ("switch") soundin = pick(global.switch_sound)
159+
if ("button") soundin = pick(global.button_sound)
160+
if ("chop") soundin = pick(global.chop_sound)
161+
if ("glasscrack") soundin = pick(global.glasscrack_sound)
162+
if ("tray_hit") soundin = pick(global.tray_hit_sound)
163+
if ("sweeping") soundin = pick(global.sweeping_sound)
164+
if("ricochet") soundin = pick(global.ricochet_sound)
164165
return soundin
165166

166-
167167
///Volume to play DTMF key sounds at. They're pretty loud, so 15 is fine.
168168
#define VOL_DTMF_KEY 15
169169

code/game/turfs/walls/_wall.dm

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,10 @@ var/global/list/wall_fullblend_objects = list(
129129

130130
var/proj_damage = Proj.get_structure_damage()
131131

132-
if(Proj.ricochet_sounds && prob(15))
133-
playsound(src, pick(Proj.ricochet_sounds), 100, 1)
132+
if(prob(15))
133+
var/list/ricochet_sounds = Proj.get_ricochet_sounds()
134+
if(length(ricochet_sounds))
135+
playsound(src, pick(ricochet_sounds), 100, 1)
134136

135137
if(reinf_material)
136138
if(Proj.atom_damage_type == BURN)

code/modules/clothing/chameleon.dm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,14 @@ CHAMELEON_VERB(/obj/item/clothing/chameleon, "Change Accessory Appearance")
332332
P.icon = initial(copy_projectile.icon)
333333
P.icon_state = initial(copy_projectile.icon_state)
334334
P.pass_flags = initial(copy_projectile.pass_flags)
335+
P.fire_sound = initial(copy_projectile.fire_sound)
336+
P.silenced = copy_projectile.silenced
337+
P.hitsound = initial(copy_projectile.hitsound)
338+
P.hitsound_non_mob = initial(copy_projectile.hitsound_non_mob)
335339
P.hitscan = initial(copy_projectile.hitscan)
336340
P.step_delay = initial(copy_projectile.step_delay)
341+
P.speed = initial(copy_projectile.speed)
342+
P.range = initial(copy_projectile.range)
337343
P.muzzle_type = initial(copy_projectile.muzzle_type)
338344
P.tracer_type = initial(copy_projectile.tracer_type)
339345
P.impact_type = initial(copy_projectile.impact_type)

code/modules/mob/living/living_defense.dm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242

4343
// For visuals and blood splatters etc
4444
/mob/living/proc/bullet_impact_visuals(var/obj/item/projectile/P, var/def_zone, var/damage)
45-
var/list/impact_sounds = LAZYACCESS(P.impact_sounds, get_bullet_impact_effect_type(def_zone))
45+
var/list/all_impact_sounds = P.get_impact_sounds()
46+
var/list/impact_sounds = LAZYACCESS(all_impact_sounds, get_bullet_impact_effect_type(def_zone))
4647
if(length(impact_sounds))
4748
playsound(src, pick(impact_sounds), 75)
4849
if(get_bullet_impact_effect_type(def_zone) != BULLET_IMPACT_MEAT)

code/modules/projectiles/projectile.dm

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
var/proj_trail_icon_state = "trail"
2626
/// Any extant trail effects.
2727
var/list/proj_trails
28+
/// An effect to spawn when a non-hitscan projectile collides with a target.
29+
var/impact_effect_type
30+
/// A sound to play when striking a non-mob (hitsound is used for mobs)
31+
var/hitsound_non_mob
2832

2933
var/bumped = 0 //Prevents it from hitting more than one guy at once
3034
var/def_zone = "" //Aiming at
@@ -73,9 +77,7 @@
7377

7478
var/fire_sound
7579
var/fire_sound_vol = 50
76-
var/miss_sounds
77-
var/ricochet_sounds
78-
var/list/impact_sounds //for different categories, IMPACT_MEAT etc
80+
var/fire_sound_vol_silenced = 10
7981
var/shrapnel_type = /obj/item/shard/shrapnel
8082

8183
var/vacuum_traversal = 1 //Determines if the projectile can exist in vacuum, if false, the projectile will be deleted if it enters vacuum.
@@ -131,6 +133,10 @@
131133

132134
//called when the projectile stops flying because it collided with something
133135
/obj/item/projectile/proc/on_impact(var/atom/A)
136+
137+
impact_sounds(A)
138+
impact_visuals(A)
139+
134140
if(damage && atom_damage_type == BURN)
135141
var/turf/T = get_turf(A)
136142
if(T)
@@ -208,6 +214,7 @@
208214

209215
//Called when the projectile intercepts a mob. Returns 1 if the projectile hit the mob, 0 if it missed and should keep flying.
210216
/obj/item/projectile/proc/attack_mob(var/mob/living/target_mob, var/distance, var/special_miss_modifier=0)
217+
SHOULD_CALL_PARENT(TRUE)
211218
if(!istype(target_mob))
212219
return
213220

@@ -234,13 +241,18 @@
234241
if(result == PROJECTILE_FORCE_MISS)
235242
if(!silenced)
236243
target_mob.visible_message("<span class='notice'>\The [src] misses [target_mob] narrowly!</span>")
244+
var/list/miss_sounds = get_miss_sounds()
237245
if(LAZYLEN(miss_sounds))
238246
playsound(target_mob.loc, pick(miss_sounds), 60, 1)
239247
return FALSE
240248

241249
//hit messages
242250
if(silenced)
243-
to_chat(target_mob, "<span class='danger'>You've been hit in the [parse_zone(def_zone)] by \the [src]!</span>")
251+
to_chat(target_mob, SPAN_DANGER("You've been hit in the [parse_zone(def_zone)] by \the [src]!"))
252+
if(hitsound)
253+
var/impact_volume = get_impact_volume_by_damage()
254+
if(impact_volume)
255+
playsound(target_mob, hitsound, impact_volume, 1, -1)
244256
else
245257
target_mob.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
246258

@@ -672,3 +684,62 @@
672684

673685
/obj/item/projectile/proc/update_effect(var/obj/effect/projectile/effect)
674686
return
687+
688+
/obj/item/projectile/proc/get_projectile_damage(mob/living/target)
689+
return damage
690+
691+
692+
// Makes a brief effect sprite appear when the projectile hits something solid.
693+
/obj/item/projectile/proc/impact_visuals(atom/A, hit_x, hit_y)
694+
// Hitscan things have their own impact sprite.
695+
if(!impact_effect_type || hitscan)
696+
return
697+
if(isnull(hit_x) && isnull(hit_y))
698+
if(trajectory)
699+
// Effect goes where the projectile 'stopped'.
700+
hit_x = A.pixel_x + trajectory.return_px()
701+
hit_y = A.pixel_y + trajectory.return_py()
702+
else if(A == original)
703+
// Otherwise it goes where the person who fired clicked.
704+
hit_x = A.pixel_x + p_x - 16
705+
hit_y = A.pixel_y + p_y - 16
706+
else
707+
// Otherwise it'll be random.
708+
hit_x = A.pixel_x + rand(-8, 8)
709+
hit_y = A.pixel_y + rand(-8, 8)
710+
new impact_effect_type(get_turf(A), src, hit_x, hit_y)
711+
712+
/obj/item/projectile/proc/get_impact_volume_by_damage()
713+
if(damage || agony)
714+
var/value_to_use = damage > agony ? damage : agony
715+
// Multiply projectile damage by 1.2, then CLAMP the value between 30 and 100.
716+
// This was 0.67 but in practice it made all projectiles that did 45 or less damage play at 30,
717+
// which is hard to hear over the gunshots, and is rather rare for a projectile to do that much.
718+
return clamp((value_to_use) * 1.2, 30, 100)
719+
return 50 //if the projectile doesn't do damage or agony, play its hitsound at 50% volume.
720+
721+
/obj/item/projectile/proc/impact_sounds(atom/A)
722+
723+
var/play_volume = clamp(get_impact_volume_by_damage() + 20, 0, 100)
724+
if(play_volume <= 0)
725+
return
726+
if(silenced)
727+
play_volume = min(play_volume, 5)
728+
729+
var/play_sound
730+
if(ismob(A)) // Mob sounds are handled in attack_mob().
731+
play_sound = hitsound
732+
else
733+
play_sound = hitsound_non_mob
734+
if(!play_sound)
735+
return
736+
playsound(A, play_sound, play_volume, 1, -1)
737+
738+
/obj/item/projectile/proc/get_miss_sounds()
739+
return
740+
741+
/obj/item/projectile/proc/get_ricochet_sounds()
742+
return
743+
744+
/obj/item/projectile/proc/get_impact_sounds()
745+
return

code/modules/projectiles/projectile/beams.dm

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
icon_state = "laser"
44
temperature = T0C + 300
55
fire_sound='sound/weapons/Laser.ogg'
6-
impact_sounds = list(BULLET_IMPACT_MEAT = SOUNDS_LASER_MEAT, BULLET_IMPACT_METAL = SOUNDS_LASER_METAL)
76
pass_flags = PASS_FLAG_TABLE | PASS_FLAG_GLASS | PASS_FLAG_GRILLE
87
damage = 40
98
atom_damage_type = BURN
@@ -14,11 +13,20 @@
1413
invisibility = INVISIBILITY_ABSTRACT //beam projectiles are invisible as they are rendered by the effect engine
1514
penetration_modifier = 0.3
1615
distance_falloff = 2.5
16+
hitsound = 'sound/weapons/sear.ogg'
17+
hitsound_non_mob = 'sound/weapons/searwall.ogg'
1718

1819
muzzle_type = /obj/effect/projectile/muzzle/laser
1920
tracer_type = /obj/effect/projectile/tracer/laser
2021
impact_type = /obj/effect/projectile/impact/laser
2122

23+
/obj/item/projectile/beam/get_impact_sounds()
24+
var/static/list/impact_sounds = list(
25+
(BULLET_IMPACT_MEAT) = SOUNDS_LASER_MEAT,
26+
(BULLET_IMPACT_METAL) = SOUNDS_LASER_METAL
27+
)
28+
return impact_sounds
29+
2230
/obj/item/projectile/beam/megabot
2331
damage = 45
2432
distance_falloff = 0.5

code/modules/projectiles/projectile/bullets.dm

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,31 @@
99
embed = 1
1010
space_knockback = 1
1111
penetration_modifier = 1.0
12+
impact_effect_type = /obj/effect/temp_visual/impact_effect
13+
muzzle_type = /obj/effect/projectile/muzzle/bullet
14+
hitsound_non_mob = "ricochet"
15+
1216
var/mob_passthrough_check = 0
1317
var/caliber
1418

15-
muzzle_type = /obj/effect/projectile/muzzle/bullet
16-
miss_sounds = list('sound/weapons/guns/miss1.ogg','sound/weapons/guns/miss2.ogg','sound/weapons/guns/miss3.ogg','sound/weapons/guns/miss4.ogg')
17-
ricochet_sounds = list('sound/weapons/guns/ricochet1.ogg', 'sound/weapons/guns/ricochet2.ogg',
18-
'sound/weapons/guns/ricochet3.ogg', 'sound/weapons/guns/ricochet4.ogg')
19-
impact_sounds = list(BULLET_IMPACT_MEAT = SOUNDS_BULLET_MEAT, BULLET_IMPACT_METAL = SOUNDS_BULLET_METAL)
19+
/obj/item/projectile/bullet/get_miss_sounds()
20+
var/static/list/miss_sounds = list(
21+
'sound/weapons/guns/miss1.ogg',
22+
'sound/weapons/guns/miss2.ogg',
23+
'sound/weapons/guns/miss3.ogg',
24+
'sound/weapons/guns/miss4.ogg'
25+
)
26+
27+
/obj/item/projectile/bullet/get_ricochet_sounds()
28+
return global.ricochet_sound
29+
30+
/obj/item/projectile/bullet/get_impact_sounds()
31+
32+
var/static/list/impact_sounds = list(
33+
(BULLET_IMPACT_MEAT) = SOUNDS_BULLET_MEAT,
34+
(BULLET_IMPACT_METAL) = SOUNDS_BULLET_METAL
35+
)
36+
return impact_sounds
2037

2138
/obj/item/projectile/bullet/get_autopsy_descriptors()
2239
. = ..()
@@ -34,7 +51,6 @@
3451
else
3552
mob_passthrough_check = 0
3653
. = ..()
37-
3854
if(. == 1 && isliving(target_mob))
3955
var/mob/living/squish = target_mob
4056
if(!squish.isSynthetic())

0 commit comments

Comments
 (0)