Skip to content

Sound events

Verified against: SLUS_212.15 (NTSC-U, SHA1 e9cb2cc49aa046b9e494313dce2f5038ed17b2f4): Ghidra, and the disc's scripts read with coney-tools (the MATERIAL, SA and CfgChar values).

Purpose

Every place the game itself starts a sound during play, with its trigger, how the sound is chosen, where it plays and how loud: animation sounds, footsteps, hits and contacts, cars, objects, pickups, the interface, the speech the game says by itself, and the ambience and music of a level. The sound engine these calls go into (tasks, voices, 3D volume, the music player, the speech-line rules) is on Sound; the data on Audio data.

Original structure

The game starts its sounds from the subsystems that raise them (humans, combat, objects, cars, the HUD, the AI's speech), each through one of a few players over the sound matrix, below; each section of Behaviour names the function that plays its sound. The sound engine's own classes are on Sound.

The players

Gameplay sounds go through a few players over the sound matrix, filled by the matrix script's NewMaterialSound / NewAnimSound calls. The matrix's tables are indexed by the script globals MATERIAL (material ids 1-190, the same ids as the collision triangles' materials: 1 NONE, 2 GLASS, 5 CONCRETE, 8 SHOE, 9 FIST, 10 TORSO, 13 CAR_HOOD, 17 HEAD, 26 HUMAN, ...) and SA (animation sound ids 0-161, below). A matrix entry has up to three columns, each a sound and a volume; its alternatives play in turn. Every player below plays positional, duckable sounds (the play call's last argument 1) at volume × the column's volume and pitch 1 unless stated. Confirmed (code):

Player Address What it plays Evidence
Sound_PlayMaterialPair(vol, m1, m2, pos, default) 0x00110830 entry [m1][m2]: column 2, then column 1 (column 1 at pitch Random_Unit() × 0.2 when m1 is 13 CAR_HOOD); no owner confirmed (code)
Sound_PlayMaterialPairPlain 0x00110940 the same without the CAR_HOOD pitch confirmed (code)
Sound_PlayMaterialHit 0x00110790 column 1 of [m1][m2] only confirmed (code)
Sound_PlayAnimSound(vol, id, pos) 0x00110a08 column 1 of animation entry id; no owner confirmed (code)
Human_PlayAnimSound(h, id, pos) 0x0021f548 animation entry id at the human, owned by him: not a player: column 1 at its volume; a player: column 1 and column 2 at 2 × volume × the combat factor (column 2 unowned), and column 3 the same while the camera is in combat framing confirmed (code)
Human_PlayImpactSound(vol, h, owner, victim, m1, m2, default) 0x00220ac8 entry [m1][m2] at h, owned by owner; with a victim knocked down, TORSO (10) and HEAD (17) on either side become 159 TORSO_PRONE; owner not a player: column 1; a player: column 1 and column 2 at 2 × vol × the owner's combat factor, and under combat framing also column 3 at a random pitch 1 ± n / 100, n in 0-19 (the audio generator 0x006eb8b0) confirmed (code)
Human_PlayFootstep(vol, pitch, h, bodyMaterial) 0x0021f290 footsteps confirmed (code)
Human_SayAnimLine(h, id, overLine, cut) 0x0021f410 animation entry id's column 1 as the human's speech line (vocal ids) confirmed (code)

A material lookup whose second material is 0 or 1 uses the caller's default (5, CONCRETE, at every call site on this page), and an empty entry falls back to [m1][default] (Sound). AudioManager_VolumeHook (0x00111650) is empty: its factor stays 1.

The combat factor (Human_GetSoundVolumeScale, 0x0021e3a8): game state +0x24c for a player while Camera_IsCombatFraming (0x00233c50) holds, else 1. +0x24c is the first argument of CfgBreathingSound (Cfg_SetBreathingSound, 0x0041d480); config_preload2.lua passes 1, so the factor is 1 in the shipped game. Combat framing: one player, and player 1 either locked on with a target or in the fight stance (Human_FightStanceMove) with a target while the camera mode 0x00510228 is above 1, and not in a grab (+0xc4 empty). Confirmed (code).

Female voices. Human +0x3b8 is copied at creation (Human_Init, 0x002184f0) from the character class's +0x14b, which is CfgChar's 13th argument (Cfg_SetCharacterClass, 0x00228af8). It is 1 for 61 of the 449 types, all of them women (char_lcgf, the Lizzies, hook_01 ...): the code reads it only to pick the _female animation sound for a vocal id. Confirmed (code); "female" is inferred from the types and the ids' names.

Data

The tables an event reads (the sound matrix's material pairs, the vocal and speech-command ids, the sound classes of the disc's sound list) are described where an event uses them, in Behaviour below; their formats are on Audio data.

Behaviour

What starts each sound, kind by kind.

The ground under a human

Human +0x1d8 is the material of the level triangle under him: Human_SnapToGround (0x0023eab8, each update's 1.5 m ray down from 1 m above the feet, Characters) and the landing test (Human_LandingTest, 0x0023e408, a floor contact with n.z > 0.65) store the hit's material (WorldManager_RayCast result +0x28, Collision). A cast that hits nothing leaves it unchanged; it starts at 0 (Human_Init), which the lookup treats as the default, CONCRETE. Confirmed (code).

Animation sounds

A clip event of type 11 sends the human message 0x8b with the event's value (Sound); Human_OnAnimSoundEvent (0x0021f700) acts on that SA id. "At the human" is the human's position in the transform table (0x00714b00 + index × 0x20). Confirmed (code) for every row.

Footsteps and body falls

Everything in this section is confirmed (code) at the cited addresses unless a line says otherwise.

Human_PlayFootstep(vol, pitch, h, body) plays Sound_PlayMaterialPair of [body][ground], with ground the ground material remapped first (Sound_RemapFootMaterial, 0x00110aa8: 18 TRAINRAIL → 106 GRAVEL, 6 ASHPHALT → 5 CONCRETE, 121 CARPET → 35 GRASS at half volume). The volume is vol × the remap's factor × the human's combat factor × 2 for a player. For body material 8 (SHOE), a human hidden in shadow (state 0x200000, Human_IsHiddenInShadow 0x00228168, the sneak) plays at half volume and without the player's doubling; classes 0x77 and 0x78 use the plain pair (no difference for body 8).

SA id Name Body material Volume Evidence
1 footstep 8 SHOE 1 confirmed (code)
3 footstep_run 8 SHOE 1.25 confirmed (code)
12 truekneedrop 34 KNEE 1 confirmed (code)
13 hit_ground 26 HUMAN 1 confirmed (code)
18 xhit_ground 10 TORSO 1 confirmed (code)
37 jump_land 164 FEET_LAND 1 confirmed (code)
40 light_hit_ground 161 HUMAN_LIGHT 1 confirmed (code)
43 thrown_hit_ground 162 HUMAN_HEAVY 1 confirmed (code)
67 light_land 163 FEET_LIGHT 1 confirmed (code)
69 land 101 FEET 1 confirmed (code)

Fixed material pairs

SA id Name Plays Evidence
46 kick_to_body Sound_PlayMaterialPair([8 SHOE][159 TORSO_PRONE]) at the human, volume 1, a player 2 confirmed (code)
65 kick_to_head Sound_PlayMaterialPair([8 SHOE][17 HEAD]), volume 1, a player 2 confirmed (code)
52 bottle_smash by the held object's material (its type's +100): 102 BRICK → SA 141 brick_smash, 60 POOLBALL → 142 cueball_smash, 37 BOTTLE → 52 itself, through Human_PlayAnimSound; when that plays nothing (no entry), the object's material against itself: not a player Sound_PlayMaterialHit([m][m]) volume 1, a player Sound_PlayMaterialPair([m][m]) at 2 × the combat factor. Nothing without a held world object confirmed (code)
86 head_wtand the held object's material m against 17 HEAD: not a player Sound_PlayMaterialHit([m][17]), a player Sound_PlayMaterialPair([m][17]) at 2 × the combat factor confirmed (code)
62 stab Human_PlayAnimSound(62), or SA 140 bottle_stab when the held object's +0xc4 is hash 0xc68a017c (the broken bottle, inferred) confirmed (code); the bottle inferred

Sounds without a speaker

SA ids Plays Evidence
4 short_fabric, 6 long_fabric, 15 fabric_friction Sound_PlayAnimSound at the human: a player at volume 2; anyone else at 1 only when his class +0x11b is 13 (Human_IsClass13 0x00223e20: the bosses and big fighters, CfgChar's third argument), else nothing confirmed (code)
5 swoosh_big, 8 swoosh_sml, 16 boss_swoosh1, 23 swoosh_punch3, 44 weapon_swoosh, 90 boss_swoosh2, 91 boss_swoosh3, 92 boss_swoosh Sound_PlayAnimSound: volume 1, a player 2 confirmed (code)
50 zoom_01 column 1 by PlaySound3DByHash at its column volume, no owner, no doubling confirmed (code)
66 fence_rattle_big, 68 fence_rattle_small column 1 owned by the human at its column volume (AudioManager_PlayOwned), no doubling: the fence climb confirmed (code)
83 sprayloop stops the human's sound at +0x168, plays column 1 owned by him and keeps it there (Human_SetSpeechHandle) confirmed (code)
60 uncuff Human_StartGrabSound (0x0021b228): starts the sound prepared in +0x180 (Human_PrepareGrabSound 0x0021b148 prepares SA 60's column 1 at the grab partner, from Human_StateUpdate and ContextActions_Pick), or, when none was prepared, Human_PlayAnimSound(60) confirmed (code)
87 stealth_hands, 88 stealth_baton, 89 stealth_knife while the human's sound at +0x17c is not alive: stop his line and play column 1 as a cutting speech line (Human_PlaySpeechCutting, volume 1), then Player_UpdateHiddenLoopSound (0x002301f0); otherwise Player_StartPreparedLine (0x0021f208) confirmed (code)
0 none nothing confirmed (code)
every other id Human_PlayAnimSound (the default; listed explicitly for 2, 11, 26, 33, 74, 94, 118-128) confirmed (code)

The spray loop's end

SA 83 sprayloop keeps its sound in the human's speech handle +0x168 (above), and nothing about the sound itself ends it: the clip that starts it also stops it. Clip event 0x45 sends the human message 0xc5 (Anim_FireFrameEvents 0x00101dd8), whose handler stops the sound in +0x168 when it is still alive (Sound_Stop) and resets the handle to the null handle (0x00598690, Human_SetSpeechHandle; Human_HandleMessage 0x00245920). Confirmed (code). The other ways that sound ends: the next SA 83, 14 / 71 (0x8e / 0xc7) on the same human stop it before starting their own; a cinematic's start stops every human's held sound (Scenes); Human_StopVoice (0x0021f058).

In Rembrandt's power move 59 (gen_grab_front_power10_p2, rate 0.75, Combat) the loop starts at frame 14 and event 0x45 stops it at frame 27: 17 updates (0.57 s) of spray. Confirmed (runtime), PCSX2 2.9.94, level99 lesson 6: +0x168 held a live handle from 59's update 19 to its update 36 and was empty from then on.

Coney (#224, implemented): HumanSoundEvents keeps the loop as the human's held sound (m_held, repo:src/audio/human_sound_events.cpp) and stops it on clip event 0x45 (HumanSound::Kind::StopHeld, from Human::takeSounds), on the next held sound, on a cinematic's start (GameSound), when gameplay is left, and when the human is removed (SoundHost::humanRemoved). Disc test (tests/platform/disc_level99_power_lesson_test.cpp): the spray is held for 17 updates of 59 and no human holds a sound after it, and a one-shot interface cue (the flash's use, cue 23) played during the spray, after it and in l99_c7 starts each time. The same test with the stops switched off (a loop that runs on, as before) also let the cue start: one stuck loop takes a task and a voice, which the engine's admission does not refuse a cue for, so it does not by itself explain the silence a user reported for the flash's use sound or for a cutscene's audio.

Vocal ids

Human_SayAnimLine(h, id, overLine, cut) (0x0021f410) plays the entry's column 1 as the human's speech line (Human_PlaySpeech 0x0021e400, or Human_PlaySpeechCutting 0x0021e698 when cut), at the column's volume, × 2 for a player. Nothing when the human cannot speak (+0x199 clear) or the entry has no sound. While a line plays (+0x178 alive) it plays only when overLine, and then stops that line first without force: a line that may not be cut (+0x194 clear: every HuSpeakNI line and every Warrior order) is neither stopped nor talked over, so the grunt is not heard and that line's script callback still runs when it ends; a cut-able line (HuSpeak's) is replaced by the grunt and its callback is lost. Confirmed (code) and (runtime): Cutting in on a line. As a speech line it follows Speech lines: nothing during a cinematic. Where a female id is given, a human with +0x3b8 = 1 uses it instead.

SA id (female id) overLine cut Notes Evidence
7 whistle, 149 sleep_snore, 150 sleep_grunt, 156 puke_big, 161 puke yes no confirmed (code)
9 grunt_pch (109) yes no confirmed (code)
22 grunt (108) yes no confirmed (code)
59 grunt_pain → plays 22 grunt (108) yes no the pain grunt is the grunt entry confirmed (code)
30 grunt_land, 54 grunt_strain, 72 grunt_hit_face yes no no female variant confirmed (code)
39 winded (111) yes no confirmed (code)
71 grab_back_grunt (112) yes no confirmed (code)
101 grab_grunt (110) yes no confirmed (code)
58 die (114) yes yes only while no scene plays (game state +0x410 clear) confirmed (code)
115 expire (116) no yes only when no line is playing confirmed (code)
28 grunt_x (113) yes no only after command 12 pain said nothing (below) confirmed (code)
32 grunt_lightlift (145) no no only after command 152 lightlift said nothing confirmed (code)
57 grunt_heavylift (144) no no only after command 151 heavylift said nothing confirmed (code)

Speech-command ids

Everything in this section is confirmed (code) at the cited addresses unless a line says otherwise.

These say a speech command through Human_SayCommand(vol, h, command, callback, interrupt, uncut, target, duckable) (0x002205e0; uncut 0 plays it as a cutting line; it returns the line's handle). The target for a look is the null handle (0x006ebd30) in every row. "Gesture" means only when Ambient_MayGesture allows; "1.5 at a player" means volume 1.5 when the human's target is a player, else 1.

SA id Command (number) Volume Interrupt Duckable Condition Evidence
28 grunt_x pain (12) 1.5 at a player yes yes then the vocal line above when no line came confirmed (code)
29 cmd_mount mount (14) 1.5 at a player yes yes gesture; never for a player while game state +0x268 is positive confirmed (code)
32 grunt_lightlift lightlift (152) 1 no yes then the vocal line confirmed (code)
35 cmd_wave, 97 cmd_point point (15) 1.5 at a player yes yes gesture confirmed (code)
41 agony agony (34) 1 no no while the human has interrogation lines (+0x590-+0x59c, Crimes), else yes confirmed (code)
56 cmd_throw throw (10), or throw2 (38) when the held object's type (+0x86) is 8 TYPE_MOLOTOV 1 (3, below) yes yes only with a target (a human or a flag) and brain +0x2d4 clear confirmed (code)
57 grunt_heavylift heavylift (151) 1 yes yes then the vocal line confirmed (code)
82 cmd_rage rage (160) 1 yes yes confirmed (code)
95 cmd_boss roar (167) 1 yes yes confirmed (code)
103 cmd_kiyap kiyap (176) 1.5 at a player yes yes gesture confirmed (code)
139 cmd_fire onfire (107) 1 yes yes only while his on-fire shout is on (human byte +0x19b, 1 at spawn, HuEnableOnFire); the byte is the shout's switch, not a burning state: its only readers are this event (0x00220044) and Human_StartBurning (0x002192d8), both gating command 107 confirmed (code)
146 sprayface sprayface (203) 1 yes yes confirmed (code)

cmd_throw in the level whose record +0x04 is 31 at checkpoint 6, for a gang member (brain +0x04 = 3): volume 3, and with a target he cannot see (Human_HasLineOfSight 0x00222288), instead the line vags/character/voices/<set>/warn/warn_o_01 of his voice set (+0x3b0) through Human_PlaySpeech at volume 4.

Ambient_MayGesture (0x00291ed0): true when a camera is within 30 m of the human and one of the first n slots of his brain's reaction kind (two handles per kind at 0x006cddf8; n is the brain's help level) is free: empty, or its human not speaking (+0x178 dead). The human then takes that slot. So at most two humans of a reaction kind make these gesture lines at a time. Confirmed (code).

Crew lines while tagging

Everything in this section is confirmed (code) at the cited addresses unless a line says otherwise.

Two tag lines come from a crew member, not the tagger, through Tag_SayNearbyLine(tagger, command) (0x00273a68). Confirmed (code):

When Command Caller Gate on the tagger
the cursor snaps back after more than 4 off-track updates (Crimes step 3) 80 tagcheer TagGame_Update (0x002748a8) his +0x19c set; no random chance
the stick game is finished (Tag_IsComplete) and was not stopped by the 300-cell cap (game +0x4fc = 0) 83 tagdone Tag_UpdatePlayer (0x00273c60), not Tag_End none (+0x19c is not read)
  1. Gate. Nothing unless the tagger is a war chief (+0x3ac = 1) and his player's last Warrior command (game state 0x0051489c +0x41a + his +0x1b0) is 2, defend.
  2. Candidates: the 16 member slots (gang +0x48) of the tagger's gang (his brain +0x20c), in slot order. A slot counts when it holds a human who is not the gang's leader (Gang_GetLeader 0x00165678, normally the tagger himself), not a player (+0x1b0 = −1), not busy (Human_IsBusy 0x00228258: busy means he has a record and either a state flag of 0x1f80974000 or record +0x108 ahead of the game time), whose actions are not blocked (0x00228228: no state flag of 0x7bf9e9f7ff0), whose brain has no queued actions (+0x2e ≤ 0), and who is within the tagger's far melee range (his brain +0x140, 5.0 m unless BrSetMeleeRange changed it; AI) of the tagger, by the squared distance between their positions.
  3. Pick: not the nearest. The first counting slot is taken; every later counting slot replaces it when Random_Int(100) (stream 0x006eb8a0) is 50 or more. So the last counting slot wins at 50 %, the one before at 25 %, and the first at 1/2^(n−1) of n.
  4. Speak: only the picked member is then tested: Ambient_MayGesture (above) and his own +0x19a (HuEnableTagDone) must both pass, or nobody speaks (no second choice). He says the command through Human_SayCommand(1.0, member, command, no callback, no interrupt, uncut 1, null target, duckable 1).

So +0x19c (HuEnableTagCheer, read on the tagger) gates only the cheer, while +0x19a (HuEnableTagDone, read on the speaker) gates both lines. Human_Init (0x00218008) sets +0x198 to +0x19c all to 1 (one register holding 1, stores at 0x0021810c-0x0021811c), so both are on for every human until a script clears them.

Hits and contacts

A strike on a human

Everything in this section is confirmed (code) at the cited addresses unless a line says otherwise.

A landed strike (Strike_Contact, 0x0021b290, Combat) on a human with health plays its hit sound in Hit_ResolveBlock (0x00220df0): Human_PlayImpactSound(1, attacker, attacker, victim, strike, struck, 5), nothing when the attacker's body +0x1a0 has +0x38 set. Confirmed (code):

  • strike by the attacker's striking shape (its bone id +0x31, Combat) and the hit's strength s (0-3: the reaction's bits 4-5 from Hit_PickReaction 0x00266d00, plus 1 when the attack's Anim Range flags (+0x0e, 0x00254e20) have 0x600 or the attacker's anim id is 11, at most 3):
    • head (bones 5-16): 17 HEAD;
    • forearms and hands (17-27): [111 JAB, 9 FIST, 112 BIGPUNCH, 112 BIGPUNCH][s] (0x00510190);
    • shins and feet (28-33): [8 SHOE, 8 SHOE, 113 BIGKICK, 113 BIGKICK][s] (0x005101a0);
    • anything else: 0 (the default row). A boss-class attacker (class +0x11b 13) striking with JAB, FIST or BIGPUNCH uses 183 BOSS_FIST.
  • struck: 108 BAG when the victim's class is 460 (punchbag); else 184 DEAD when he is down or dead (Human_IsDownOrDead 0x00227e60); else 127 BLOCK when he blocks or ducks (or is a boss-class human with flag 0x10 of +0xe0); else 17 HEAD for a boss-class victim; else by the shape struck: 17 HEAD for the head (bones 5-16), 10 TORSO otherwise (the spine, or no shape).

Before that, Strike_Contact adds Human_PlayImpactSound(1, attacker, attacker, victim, 26 HUMAN, 26 HUMAN, 5) when the attacker holds flag 0x1400000 (a charge or a thrown human, Combat) or the attacker's body shape has flag 0x2. A friendly hit by a player on a gang member (brain +0x04 = 3) who is idle and may gesture makes him say fuck_you (88; interrupt, duckable) when his health is above 10 %.

A strike on the level, an object or a car

Strike_Contact, confirmed (code):

  • The level mesh (no object): Human_PlayImpactSound(116, h, h, 0, 9 FIST, triangle material, 5) (the volume is clamped to 1 by the engine), unless the attacker holds 0x400800, is turn-limited (Human_IsTurnLimited4 0x00227f68, Human_IsTurnLimited6 0x00227f40), has state 0x4000000, or his anim id is 2, 4 or 0x1b2. Plus a particle burst.
  • A world object: Human_PlayImpactSound(1, h, h, 0, 9 FIST, or 26 HUMAN when holding 0x1400000, the object type's material (+100), 5), then the object takes the hit (a glass pane breaks: World objects).
  • A car: Human_PlayImpactSound(v, h, h, 0, 9 FIST, or 26 HUMAN when holding 0x1400000, 13 CAR_HOOD, 5) when the strike reached any part (the car's vtable +0x104 mask is not 0), with v 1, or 0.5 when the attacker is a player (whose doubling in the player makes it 1 again). A window it breaks adds its glass sound (Cars).

The body's contacts

Human_OnContact (0x00219d50), confirmed (code):

  • A thrown human against the level: the player's throw (Player_Throw 0x0026dd08) arms the victim's +0x3bd; his first level contact that comes while he holds 0x400800, is turn-limited 4, has state 0x4000000 or plays anim 2 or 4 (and +0x5b9 is clear and he is not turn-limited 6) plays Human_PlayImpactSound(v, h, h, 0, 26 HUMAN, triangle material, 5) with v 1 when he holds 0x400000, else 0.5, and disarms it.
  • A world object of type 29 (TYPE_MOVINGVEHICLE): kills the human and plays Sound_PlayMaterialPair(1, object material, 26 HUMAN) at him.
  • Type 34 (TYPE_CHATTERBOXTRAIN): a third of his maximum health, once per object, and the same pair.

Cars

Confirmed (code):

  • Part damage (Car_OnHit, 0x0038bea0): a part among 4, 5, 10-14, 16, 18 and 20 whose damage crosses 0.5 in this hit plays Sound_PlayMaterialPair(1, 129 CAR_DAMAGE, 129 CAR_DAMAGE) at the hit point.
  • Windows: a part's first break (Car_BreakWindow, 0x0038a830) sends message 0x3f to the shared car-damage particle system (Cars): kind 4 for windows 15, 17, 19 and 21, kind 6 for parts 6 and 7. Its glass shatter (SubGlass_Update, 0x003e4cb8) plays Sound_PlayMaterialPairAt (0x00117280, volume 1) at the burst, before any camera culling of the effect: [88 GLASS_SMALL][88 GLASS_SMALL] for a small burst or one whose record +0x0c is 0x10001 (kind 4, the windows), [2 GLASS][2 GLASS] otherwise (kind 6).
  • Explosion: a molotov's hit prepares vags/fire/car_explodes<n>, n random 1-3, at the car (Sound_PrepareAtByName, kept at car +0x12fc), and Car_DoExplode (0x0038ab50) starts it.
  • The rock (shocks): a hit by a human or by an object a human holds (not a thrown one) starts the car rocking away from the hit (Car_StartHitRock, 0x0038b1f8, the only caller is Car_OnHit; Cars: the rock; the rock itself is inferred from the fields it sets), strength 2 bare-handed, 4 for a human with flag 0x400000 and 3 for a held object, which plays vags/vehicles/shocks_squeak_0<n> (n random 1-3) at the car. It is skipped while the hitter's +0x568 is set (for a held object, the parts this swing has hit; inferred: once per swing). So a window smash plays a squeak with the glass; 0xe77006e7 and 0x90773671 are _02 and _03 (the hashes). (An earlier reading put this in the explosion; the explosion does not call it.)
  • Loose parts (Car_UpdateLoosePart, 0x00387f18): a part's impact above 4 m/s plays Sound_PlayMaterialPair(1 / (n + 1), 119 CAR_PART, triangle material) (n the part's byte +0x97) and (…, 120 CAR_PART_STREAM, …); each that plays nothing is replaced by the same material against 5 CONCRETE.
  • Car_PlaySound (0x0038d6d8) is only scene event 71 on a car (Sound).

Objects

Everything in this section is confirmed (code) at the cited addresses unless a line says otherwise.

World objects play material pairs of their type's material (CfgObj, type record +100) through Sound_PlayMaterialPair or Sound_PlayMaterialPairAt (0x00117280: volume 1, default 5), and fixed sounds by hash through Sound_PlayAtDefault / Sound_PlayAtDefault2 (0x00117190, 0x00117238: positional, volume and pitch 1, duckable). Glass panes, doors and barriers are on World objects. Confirmed (code):

  • A dropped or thrown object hitting the level (WorldObject_OnImpact, 0x003939a8): the triangle's material is kept in the object's +0xf4; n counts its impacts (+0x13c). A plain bounce plays only for the first three and above 2 m/s: [object][surface] at volume 1 / (n + 1). A hit that breaks the object (its +0x10d or +0x10e is 0) plays [object][object] at 1 (0.1 for material 86 CHAIR moving straight down), then [object][surface] at 0.5 / (n + 1) with default 116 BRICKWALL, or, when that plays nothing, with default 5. A held or struck object that does not break plays [object][surface] with default 116, falling back to 5. The first sound's far (30 m without one) is the radius of the AI noise it makes.
  • An object touching another or a car (WorldObject_OnContact, 0x00394050): [other][object] at 1 and the object against 13 CAR_HOOD and 14 CAR_HOOD_STREAM at 0.5 (at 1 when the contact has no other object).
  • A thrown object (ThrownObject_OnContact 0x00393538, ThrownObject_HitHumanTest 0x003928d0, ThrownObject_HitHuman 0x00392b88): against an object [thrown][struck] at 1 (0.5 for the second pair); against a human [object][26 HUMAN] at 0.5 or 1, or through Human_PlayImpactSound at the human with 127 BLOCK or 128 WEAPON_BLOCK when he blocks (0.25-1).
  • Debris and rubble (Rubble_Update 0x003f4188, SubDebris_Update 0x003c24e8, WoodSplinterBit_Update 0x00407ae0): [piece][surface] at 1 when a piece lands. OverheadWeapon_Break (0x003ffe90): the weapon's material against itself.
  • Breakables by class (Sound_PlayMaterialPairAt): DynCashreg, DynCbRadio, DynCtrlBox, the breakable doors (DynDoorBarBani, DynDoorBnstr, DynDoorFenceO, DynDoorParapet, DoorFence_OnHit), DynLizzies, DynMasks (with 88 GLASS_SMALL pairs), DynTable, DynWoodbridge, DynBreakableLight and the stained glass (SubStainedGlass_Update 0x003e5168, as car windows): their material against itself, or against 5, 35, 36, 106, 121 by the surface; WorldObject_HitEffectsByModel (0x003a6f68) against 106 GRAVEL and 103 CASHREG.
  • Fixed sounds by hash: the molotov (0x1be68950), the ride cart and train loops (0x326071de, 0x26ac304b, PartTrainSound_Update's table), urine spray (0x1927f7ba), rotating objects (0x5adc8f1e, 0xcd6754af, 0x546e0515), broken neon and lights (0xf164dfe0), the CB radio and walkie-talkie tables (0x006f3190, 0x005144e0), lock A (0xf4bad950, 0xe108f888), the fire plume, generator and subway sparks tables (0x00514578, 0x810e2b6f, 0x005145d8, 0x00514620), the motorbike gang (0x97116eb7), car steam (0xc1c45c2d), SubPla (0x813c858a), a swinging object (0x3fc9a583); by name: blood splatter vags/character/blood_02 (BloodSplatter_Update 0x003aeb78), small fires vags/fire/fire_small_loop (SubFadeFlame_Init 0x003c7de0), the level-51 bus vags/cutscenes/l51/bus_idle_02 (PartTruckSound_Update 0x003fce60). Swinging and sliding doors play their record's hashes (Sound_PlayHashAt 0x003a6ee8; the store door's first hit 0xcf6586b2).
  • Trains and sparks. PartTrainSound_Update (0x003db690) starts a sound only while its last one has ended and a camera is within 80 m: in the levels whose id is 0x1f or 0x57, one of vags/vehicles/train_pass1-5 (0x005145f0) when a camera is within 10 m or nothing blocks the 100 m ray from the train to the player; in every other level one of vags/vehicles/subway_squeak1-5 (0x00514608) when a camera is within 40 m. It picks one of the five at random each time (Random_Int(4) is 0 to 4) and moves it with the train. The subway sparks (PartSSubwaySparks_OnMessage 0x003db368, table 0x005145d8) and each sub_spark_effect burst (SubSparkEffect_Update 0x003e1648, table 0x00514620) play one of five entries at random, each entry vags/ambient/sparks/spark1 or spark6 (3:2 for the subway sparks, 2:3 for the bursts), banked in sound, armies, gallery and level81. Confirmed (code) at the addresses cited; the names are confirmed (name hash): each is the CRC-32 of the name, whose last 16 characters stand before its record in the sound list's debug copy (Xbox assets).
  • The hashes, by name (confirmed (name hash): the CRC-32 of each name matches, and the tables hold them in this order): 0x00514608 holds subway_squeak1-5 as 0xc2fff866, 0x5bf6a9dc, 0x2cf1994a, 0xb2950ce9, 0xc5923c7f; the sparks tables hold spark1 0x0c9417aa and spark6 0x92f08209; shocks_squeak_02 and _03 are 0xe77006e7 and 0x90773671. These are the nine sounds of level99's checkpoint 2 that had no name; that its trains squeak rather than pass fits level99 not being level 0x1f or 0x57 (inferred).

Speech the game says

Everything in this section is confirmed (code) at the cited addresses unless a line says otherwise.

Besides the animation ids and the scripts' SoundPlayCommand, the game's own code says speech commands through Human_SayCommand (0x002205e0, Saying a speech command) from 129 functions, listed below with the commands (number and name, Speech), the volume and the flags: I interrupt (cuts the speaker's current line; without it nothing is said while he speaks), C played as a cutting line (Human_PlaySpeechCutting), N not duckable, L the speaker looks at a target. "Gesture" means only when Ambient_MayGesture allows (above). Every call goes through the voice table, so a command the speaker's voice set has no line for says nothing. The triggers are the functions' own (their pages: AI, Combat, Crimes); a "variable" command is a parameter of the goal or action. Confirmed (code) for every call's arguments.

Address Function Commands (volume, flags) Evidence
0x002b6fa0 ArrestedGoal_Process within 4 m of a player, every 4 s, gesture: 126 unarrest_help from a gang member (brain 3), 72 scared from someone of a gang hostile to the arrested (1.5, -) confirmed (code)
0x002af278 AttackTargetGoal_Process 17 cheer2 (1, IC) confirmed (code)
0x002af0b8 AttackTarget_Cleanup 88 fuck_you (1, ICL) confirmed (code)
0x002e3630 AvoidEnemiesGoal_Process variable (var, -) confirmed (code)
0x002e8858 BigBrawlerGoal_OnAttackWarning 11 block or 14 mount, 50 % each (1.5, IC) confirmed (code)
0x002e8bc8 BigBrawlerGoal_OnHit 8 swear (1, -) confirmed (code)
0x002e8f78 BigBrawlerGoal_Process 87 kingohill (1.5, IC); 17 cheer2 (1.5, -C) confirmed (code)
0x002ee7b0 BigLedgeThrowerGoal_Process 87 kingohill (1.5, IC) confirmed (code)
0x002ed718 BigThrowerGoal_Process 17 cheer2 (1.5, IC) confirmed (code)
0x0030bc68 BossRoofTactic_UpdateBanter 144 cheer3 (1, IC) confirmed (code)
0x0028ca50 Brain_OnFoeDown the one who downed him, gesture, not wounded: 143 whoop or 15 point, 50 % each (1, 2 for a player, IC) confirmed (code)
0x002af928 Brain_Shout gesture, alternating: the brain's command (+0x2c, default 71 engage; 1.5 at a player), then for a cop brain 138 chase_cop (1, -) confirmed (code)
0x0028ac80 Brain_SpotPlayers 22 spot (1.5, ICL) confirmed (code)
0x002accc8 BumLogicGoal_Process 182 bum_hire (1, IC); 145 bum_beg (1, I) confirmed (code)
0x002ac458 Bum_GiveItem 148 kicked (1, IC) confirmed (code)
0x002ac5e0 Bum_TakeMoney 145 bum_beg (1, I); 147 bum_beg_resp (1, I); 2 follow (1, I) confirmed (code)
0x002acaf8 Bum_UpdateRadar 170 bum_beg_deal (1, I) confirmed (code)
0x002d6638 CallGangGoal_Process 169 surprise (1.5, IL); 22 spot (1.5, IC) confirmed (code)
0x002a81f8 CallPolice_OnCrimeSeen 9 scream (1, I) confirmed (code)
0x002a8190 CallPolice_SayOnce 127 catch_rat (1, I) confirmed (code)
0x002b1860 ChaseGoal_Process 23 search (1, -); 64 copresistco (1.5, I); 24 give_up (1.5, I) confirmed (code)
0x002b2410 ChaseSupportGoal_Process 23 search (1, -) confirmed (code)
0x002ffb30 CivilianBrain_OnEvent 205 help_girl (1.5, IC) confirmed (code)
0x0030eec0 ConfrontTactic_Process variable (1, -) confirmed (code)
0x002c61f8 CopInteractGoal_Process 192 shake_ho (1, I); 193 shake_ho_resp (1, I); 190 shake_bum (1, I); 191 shake_bum_resp (1, I) confirmed (code)
0x002d4fe8 CowerGoal_Process 9 scream (1, -L) confirmed (code)
0x002c8af0 DealerFleeGoal_Process 9 scream (1, I); variable (var, -) confirmed (code)
0x002c89a8 DealerFleeGoal_Start 9 scream (1, -) confirmed (code)
0x002c7248 DealerGoal_Say variable (1, ?); 95 offer (1, IL) confirmed (code)
0x002af670 EngageEnemyGoal_Start 71 engage (1, -) confirmed (code)
0x002678c8 Human_PlayGangDeathReaction 13 near (1, IC) confirmed (code)
0x00269b80 Hit_PlayBegReaction 73 beg (1, -C) confirmed (code)
0x00273a68 Tag_SayNearbyLine a crew member near a war-chief tagger says 80 tagcheer or 83 tagdone (1, -); Crew lines while tagging confirmed (code)
0x00274ee0 Revive_Finish 75 revive_thank (1, I) confirmed (code)
0x002752a0 Revive_Start 76 revive_reasure (1, I) confirmed (code)
0x00283a30 Player_UpdateMugHold 8 swear (1, I) confirmed (code)
0x002cfb90 InvestigateGoal_End not chasing, gesture: 24 give_up, or 184 give_up_ne (1, -) confirmed (code)
0x002d0100 InvestigateGoal_Process gesture: 183 ex_alert or 36 alert (1, I); 134 nosearch (1, I) confirmed (code)
0x002d1100 Riot_OnAttacked 17 cheer2 (1, IC) confirmed (code)
0x002d11f8 Riot_AfterFight 88 fuck_you (1, I) confirmed (code)
0x002d2600 HarassGoal_Process 88 fuck_you (1, -); variable (1, -) confirmed (code)
0x002d42c0 PlaySpecialIdleGoal_Process variable (1, ICL); variable (1.5, ICL) confirmed (code)
0x002d5798 Hostile_Attack 17 cheer2 (1.5, I) confirmed (code)
0x002d58b8 HostileGoal_Process 175 hostile (1.5, I) confirmed (code)
0x002d8028 PathScout_SayLine 23 search (1, -) confirmed (code)
0x002db918 MoveToUseFlagGoal_End 32 avoid (1, I) confirmed (code)
0x002dd210 DestroyItemGoal_Process variable (1, -) confirmed (code)
0x002dde50 DestroyCarGoal_Process variable (1, -) confirmed (code)
0x002e63e0 ShopkeeperGoal_OnPlayerAction 197 collect (1, I) confirmed (code)
0x002ea6f0 BigFighterGoal_StartBreak 34 agony (1.5, IC) confirmed (code)
0x002eabc8 BigFighterGoal_Process variable (1.5, IC); variable (1, -C); 71 engage (1, -); 14 mount (1.5, -C); 8 swear (1, -); 143 whoop (1.5, IC); 8 swear (1.5, -C) confirmed (code)
0x002ec780 BigFighterAGoal_Process variable (1.5, IC); 14 mount (1, -C); variable (1, -C); 71 engage (1, -); 8 swear (1, -) confirmed (code)
0x002ee3d0 BigLedgeThrowerGoal_PlayTaunt variable (1, IC) confirmed (code)
0x002ee608 BigLedgeThrowerGoal_MaybeTaunt 11 block (1, IC) confirmed (code)
0x002f2438 ShooterGoal_OnHit 12 pain (2, IC) confirmed (code)
0x002f28b8 StationaryShooterAGoal_Process 87 kingohill (1.5, IC) confirmed (code)
0x002f4c68 StationaryShooterBGoal_Say variable (1.5, -C) confirmed (code)
0x002f52e8 StationaryShooterBGoal_Process 87 kingohill (1.5, IC); 16 cheer1 (1, -); 16 cheer1 (1.5, -C) confirmed (code)
0x002f5988 StationaryShooterBGoal_OnHurt 40 fall (1, IC) confirmed (code)
0x002f7348 BigBullGoal_Process 8 swear (1, IC); 11 block (1, IC); variable (1, -C) confirmed (code)
0x002f8468 HideAndSeekGoal_Process 17 cheer2 (1, -); 71 engage (1, -); 143 whoop (1.5, -C); 15 point (1, -C) confirmed (code)
0x002f8e70 LeftTurfGoal_Process 71 engage (1, -L) confirmed (code)
0x003069f0 Tactic_SayAckLine variable (1, -) confirmed (code)
0x0030d3b8 BossBirdieTactic_OnEvent 34 agony (1.5, IC) confirmed (code)
0x0031b768 ShadowTactic_Process 135 shadow (1, -) confirmed (code)
0x0031c840 TauntTactic_Process 17 cheer2 (1, -) confirmed (code)
0x0031e770 VandalizeTactic_OnObjectBroken 143 whoop (1, I) confirmed (code)
0x003200c8 WanderTactic_TryPickUp 89 riot (1, -) confirmed (code)
0x00322050 ChargeSubTactic_Process 1 attack (1.5, IC) confirmed (code)
0x00322510 GuardSubTactic_Process variable (1.5, IC); 1 attack (1.5, IC) confirmed (code)
0x00322a40 LeaderSubTactic_Process 1 attack (1.5, IC) confirmed (code)
0x00323160 ThrowSubTactic_Process 10 throw (1.5, IC) confirmed (code)
0x002f9f78 FidgetAction_Start variable (var, -) confirmed (code)
0x002b3ab0 FightGoal_Process 17 cheer2 (1, -C) confirmed (code)
0x00416530 Flag_ActivitySound variable (1, I) confirmed (code)
0x002bd808 FollowAndDefendGoal_Process variable (1, -) confirmed (code)
0x0041c230 GameState_AddGuardingCop 22 spot (1, IC) confirmed (code)
0x00165d40 Gang_SaySpotLine variable (1.5, IC) confirmed (code)
0x002dacf8 GoalMoveToExitFlag_Process variable (1, I) confirmed (code)
0x002ab4b8 Goal_ProcessMove 89 riot (1, -); variable (1, IL); 125 mumble (1, -) confirmed (code)
0x002a83f8 Goal_ReportCrime 33 rat (1.5, I); 129 hurryup (1, I); 84 phone_cop (1.5, I); 9 scream (1, I) confirmed (code)
0x002c4360 Goal_ReportCrimeB 22 spot (1, IL) confirmed (code)
0x002bb858 GrabTargetGoal_Process 9 scream (1.5, -) confirmed (code)
0x0022c730 Grab_Link 8 swear (var, -) confirmed (code)
0x002c8ff8 HTLDefenseGoal_Process 74 holdline (1, -) confirmed (code)
0x002cc990 HideGoal_Process 69 hide (1, -); 168 hide_stealth (1, -); 206 hide_response (1, -) confirmed (code)
0x00265f70 Human_ApplyPendingDamage the attacker, after a hit that causes no reaction, when his anim is 9 or 0x4c, gesture: 60 % 17 cheer2 (11 block for anim 0x4c), else 8 swear (1, 1.5 when either is a player, -) confirmed (code)
0x0022ec18 Human_Arrest 25 arrested (1, I) confirmed (code)
0x00269f30 Human_BlockHit 11 block (var, -) confirmed (code)
0x00245920 Human_HandleMessage 34 agony (1, IC) confirmed (code)
0x0021f700 Human_OnAnimSoundEvent 12 pain (var, I); 152 lightlift (1, -); 34 agony (1, -N); 151 heavylift (1, I); variable (var, ?) confirmed (code)
0x0021ed28 Human_SayCopLine variable (1, I) confirmed (code)
0x00233890 Human_SayGoalLine variable (1, I) confirmed (code)
0x002207d0 Human_SayObjectLine 108 cb_wear (1, -); 110 hat_wear (1, -) confirmed (code)
0x00219238 Human_StartBurning 107 onfire (1, IC) confirmed (code)
0x00238db0 Human_Tag 37 nopaint (2, -) confirmed (code)
0x002c69b0 IssueWarningGoal_Process 32 avoid (1, IL); 36 alert (1, I) confirmed (code)
0x00412dc8 Item_TakeOwned variable (1, -) confirmed (code)
0x002c5160 LeaveAreaGoal_Process 46 cop1034f (1, IL) confirmed (code)
0x002ae2e8 MeleeGoal_ProcessTarget 71 engage (1, -) confirmed (code)
0x002da588 MoveToFlagGoal_Process 125 mumble (1, -) confirmed (code)
0x002c1858 PatrolGoal_Process 32 avoid (1, IL); 125 mumble (1, -) confirmed (code)
0x002a9508 PedInteractGoal_Process variable (1, I); 179 question (1, I); 180 answer (1, I); 181 bye (1, I) confirmed (code)
0x002aa760 PedReactionGoal_Process 9 scream (1, -); 9 scream (1, I) confirmed (code)
0x002aa598 PedReactionGoal_Start 9 scream (1, -); variable (1, I) confirmed (code)
0x002ad6c0 PeddlerGoal_Process variable (1, I) confirmed (code)
0x002fb8a0 PlaySoundAction_Update variable (var, I?) confirmed (code)
0x00303468 PlayerBrain_OnPrompt 146 give_me (1, -) confirmed (code)
0x002856b8 Player_UpdateMugging 39 mugcop (1, IC); 19 mug (1, IC); 31 no_item (1, IC); variable (1, I); variable (1, IC) confirmed (code)
0x00318130 PursueTactic_EndSearch 24 give_up (1, I) confirmed (code)
0x001f0420 RM_ChooseGangs_Render 17 cheer2 (20, -) confirmed (code)
0x002d1c38 RiotGoal_Process 89 riot (1, I) confirmed (code)
0x002d1288 RiotGoal_TryPickFight 17 cheer2 (1, IC) confirmed (code)
0x002e5fa0 ShopkeeperGoal_OnDisturbed 188 cower (1, I) confirmed (code)
0x002e6668 ShopkeeperGoal_Process 185 store_greet (1, I); 189 dead_meat (1, I); 137 mug_grunt (1, I); 187 phone_gang (1, I); 186 store_chat (1, I); variable (1, I) confirmed (code)
0x001140d8 Sound_PlayHumanCommand variable (1, ?NL) confirmed (code)
0x0021b290 Strike_Contact 88 fuck_you (1, I) confirmed (code)
0x002fb128 TauntAction_Start variable (var, -) confirmed (code)
0x002e7f50 TiredGoal_Process 150 energy (1.5, IC); 149 tired (1.5, IC); 8 swear (1, -) confirmed (code)
0x002e7c18 TiredGoal_StartBreak 34 agony (1.5, IC) confirmed (code)
0x002606e8 Uncuff_MashSuccess 67 unarrest_thank (1, I) confirmed (code)
0x00260ca8 Uncuff_Start 68 unarrest_reasure (1, I) confirmed (code)
0x002fb738 UsePhoneAction_Update variable (1, I) confirmed (code)
0x0041c338 WarChief_CheckCrewInRange variable (1, -) confirmed (code)
0x0041cc40 WarChief_SayCommand variable (1.5, IC); 3 defend (1.5, IC); 158 scatter (1.5, IC) confirmed (code)
0x00306040 WarriorBrain_OnPrompt 146 give_me (1, -) confirmed (code)
0x003052f0 WarriorBrain_Think 109 cb_whine (1.5, ICL) confirmed (code)
0x002bf118 WarriorVandalStealGoal_TryVandalise variable (1, -) confirmed (code)
0x002b52c0 WoundedGoal_Process 8 swear (0.75, I) confirmed (code)

Lines played by name or by voice-table hash, not by command, confirmed (code):

  • Gang warning barks and the spot line: Sound, Gang_SaySpotLine (0x00165d40).
  • Banter (overheard conversations of gangs under the HanginOut, Idle, MoveToFlag, TravelPath, UseFlag and Wander tactics, AI): Human_SayStateResponse(h, line, near, far) (0x002208f0) takes the line of the speaker's state-response voice set (+0x3b4) for statement (20) or response (21), the line number being the gang's counter +0x60c, moved on after each response by the responder's line count (Gang_CycleSpotLine). With the listener nearer (human +0x334) than that line's far − 20 m and no other near banter line alive (one game-wide, handle 0x0065ff40) it plays at volume 1; otherwise, with no far banter line alive (0x0065ff48), the statement2 / response2 line (77, 78), or the near line at 0.5 when there is none, plays when the listener is within far + 10 m. Both through Human_PlaySpeech, after stopping the speaker's line.
  • Bums at a flag (PedFlagGoal_Process, 0x002a68b0, flag activity 6, at a random interval): vags/character/bums/bum_bum1_00<n> or bum_bum2_00<n>, n random 0-5, volume 1.
  • Boss lines: BossBirdieTactic_Process (0x0030d208: command 17's line of one of three numbers, volume 4), InfoTactic_OnLeaderAnimStart (0x00315820), InfoTactic_Process (0x00315928), BossTactic_OnEvent (0x00309058), BigBrawlerGoal_Process, StationaryShooterGoal_Say (0x002f0930) and ShooterGoal_Say (0x002f2230): fixed lines of those fights.
  • Idle dialogue (Human_PlayIdleDialogLine, 0x00220430, from WarriorFollowTactic_Process): the human's next line of a name built from his voice set, the level's number, the checkpoint and his counter +0x196 (up to +0x197 lines, wrapping to 1). The lines live in vags/character/voices/<voice>/ as l<level>_c<checkpoint>_idle_<NN>. At spawn Human_Init (0x002184ec-0x00218560) looks up lines 01, 02 and 03 for the current level and checkpoint (Sound_FindByName, 0x00110d78): +0x197 starts as the number found (0-3) and +0x196 as 1 when any is found; HuSetIdleDialogMaxIter overrides the count. Confirmed (code).
  • Scene and clip events 12 and 70 (human messages 0x8c, 0xc6): a speech line by hash at volume 1; 14 and 71 (0x8e, 0xc7): a positional sound by hash at the human, replacing the sound in his +0x168; 69 (0xc5) stops that sound (Human_HandleMessage, 0x00245920).

Pick-ups, items and the interface

Confirmed (code). 2D sounds are PlaySound2DByHash / ByName with flags 0, 0 and duckable 1; interface cues are Sound_PlayInterfaceCue (2D, flags 0x12) by number from the SoundCfgInterfaceSound table (Sound and music).

Event Sound Where Evidence
A pick-up gives an inventory item (key, flash, spray can, money, loot, cuffs ...) the item's pick-up sound (item +0x24, Inventory), 2D Human_PickUpObject 0x0023bf00 confirmed (code)
Taking from a weapon pile (types 17-23, 47) cues 25-31 by pile type (17 BRICKPILE 25 ... 23 POOLBALLPILE 31; 47 BEERPILEHEAVY 27) at the object, positional human message 3, Human_HandleMessage confirmed (code)
Taking from a spray pile (type 44) item 3's pick-up sound, 2D the same confirmed (code)
Mugging: the money taken, the pocket handed over item 2's sound; the pocket item's sound, or item 3's or item 1's Player_UpdateMugging 0x002856b8, Mug_HandOverPocket 0x002334d0 (Crimes) confirmed (code)
The mugging camera starts, ends vags/misc/mug_intro (handle kept), then vags/misc/mug_outro after stopping it CamMug_Start 0x00137e08, CamMug_Update 0x00138b90 confirmed (code)
Buying from a dealer vags/interface/powerup DealerGoal_OnBuy 0x002c74d8 confirmed (code)
Using a flash; a revive completed cue 23 Flash_Use 0x00284280, Revive_Finish 0x00274ee0 confirmed (code)
Triangle on a context action (lock, key) cue 24 ContextAction_Use 0x0024d530, Player_TriangleAction 0x002811f0, Player_UseItemCommand 0x002843f8 confirmed (code)
The car-stereo theft's turns, done cue 34 per turn, cue 35 at the fourth Theft_UpdateStereo 0x0027e908 confirmed (code)
The lock-pick dial vags/misc/lock_spins_01 (shown), vags/misc/click_01 (judged) LockPickDial_Show 0x001b8428, LockPickDial_Judge 0x001b8d38 confirmed (code)
Rage full, rage starts, rage ends vags/interface/rage_indicator_02 once when the meter reaches its maximum; vags/misc/rage_mode_06; vags/misc/rage_ends_01 PlayerHUD_Update 0x00214138, GameState_PlayRageSound 0x004194b8, RageSound_PlayEnd 0x00419400 confirmed (code)
Wanted level, money count, objective, announcement, hint cues 2, 16, 17, 20, 21 HUD_SetWanted, HudMoney_Update, HUD_SetObjective, HUD_ShowAnnouncement, HintBox_Update (HUD) confirmed (code)
A Warrior command chosen on the stick cue 32 WarCommandDisplay_ReadStick 0x001a7040 confirmed (code)
The stopwatch's last seconds vags/interface/menu/menu_enter3, once a second StopWatch_Update 0x004233f8 confirmed (code)
The "go" sign vags/misc/bleep27 while it shows, one at a time, not while paused GoSign_Render 0x0019ed28 confirmed (code)
A counter panel's bonus vags/interface/menu/bonuspart_01 CounterPanels_SetValue 0x001c3280 confirmed (code)
The angry breathing CfgBreathingSound's sound, 2D, its handle kept Breathing_Start 0x00419030 confirmed (code)

The pick-up sound's lifetime

The sounds. config_preload2.lua gives the money, the flash, the spray can and the other power-ups the pick-up sound vags/interface/powerup and the mission items vags/interface/mission_item (Inventory items). From the disc (coney-tools audio list sounds, and the bank samples' frame flags read by a scratch script; counts and flags only), corroborated against the code's loop test (Sound_IsLooping 0x0010f2c8, class flag 0x01):

Sound Hash Kind Class, flags Priority Volume Rate Size ADPCM frame flags
vags/interface/powerup 0x7b3534e9 bank sample (in sound, armies, level3, level81, spookorama and four more banks, all alike) 4, 0x00: not looping, not positional 12 69 % 18,000 Hz 3,760 bytes, 235 frames frame 232 0x01 (end), frame 233 0x07, the rest 0
vags/interface/mission_item 0x814828dd bank sample (five banks) 4, 0x00 12 69 % 15,000 Hz 1,712 bytes, 107 frames frame 104 0x01, frame 105 0x07

So neither sound loops by its class, and each sample is a standard one-shot: the frame flagged 0x01 alone (end, without repeat) ends the voice there, and the frame after it, flagged 0x07 (loop start, repeat, end), is the usual silent padding frame that loops on itself if a voice ever reaches it (inferred from the SPU2's ADPCM flags; Coney's decodeAdpcm(..., stopAtEnd = true) stops at the first end flag, as it should).

How the original plays and releases it, confirmed (code):

  1. Human_PickUpObject (0x0023bf00; each item's call, e.g. at 0x0023c174) plays the item's sound with PlaySound2DByHash(mgr, hash, 0, 0, duckable 1) (0x0010fcd8): no position, the default (null) owner, and the returned handle is discarded (the next instruction reloads its registers): nobody can stop it, and nothing has to. The dealer's and the mugging's plays (table above) are 2D as well; whether they keep the handle was not checked.
  2. AudioManager_Play starts the bank sample on a free SPU2 voice (13-47) or a victim's (Starting a sound); being class 0x00, no loop is requested.
  3. Each update Tasks_Update (0x00112b10) frees a real task when its state is 2 or 3 or when the device reports its voice idle (AudioDevice_VoiceState, slot +0x108, 0x0014d168 → MS_GetVoiceState), which happens when the SPU2 reaches the end flag. A virtual task (no voice) is freed when its length, 0 whole seconds for these (AudioDevice_Duration rounds down), has passed, so at once.

So the original's pick-up sound ends on its own after about 0.37 s (powerup: 232 frames × 28 samples ÷ 18,000 Hz) or 0.2 s (mission_item), whatever happens to the picked-up object; it is not tied to the object, the human or the pause.

User item 22 (the pick-up sound looping until paused): nothing in the data or the original's code loops these sounds, so the loop is Coney's. Coney decodes the sample to its end flag and gives a bank sample loop points only for a looping class (repo:src/audio/sound_bank.cpp), so the data is not the cause either. The sound that loops is the one heard with every money pick-up after it: the HUD's money count (below). The list that follows was the plan before that was found; its step 1 is what found it. Coney fixes:

  1. Reproduce with --event-log and look at the sound events: many 0x7b3534e9 plays (one a step) mean the pick-up is re-triggered (a pick-up, purchase or mugging path firing every update, or a record not removed), not a loop; one play means a voice that never ends.
  2. For the one-play case, check that a mixer voice playing a PcmSound with no loop points ends at its last frame and that SoundEngine::update frees its task (!m_mixer.isPlaying(...)), and that a voice reused after a steal, or a looping sound's voice handle reused by the pick-up, keeps neither the old loop points nor the old task (the symptom fits a looping voice that lost its owner: pausing stops every voice, so it ends there).
  3. Test: play 0x7b3534e9 through GameSound::play2D on the offline device and step past 0.4 s: the voice has ended and the task is free; with every voice busy (a steal), the same holds; a looping class sound stopped by handle while a pick-up starts does not leave either playing.

The money count's sound

The sound loops. Interface cue 16 (0x10) is vags/misc/count_money2 (hash 0x6c7f4d7d; Sound and music), a bank sample of class 3 with class flags 0x01: looping, 2D, priority 12, volume 60 %, 22,050 Hz, 688 bytes (from the disc's sound list, coney-tools audio list sounds; counts and flags only). A voice playing it repeats until something stops it.

How the original keeps and stops it, confirmed (code) in HudMoney_Update (0x001becb0), once a frame per player panel (HUD: score and money):

  • The panel keeps the sound's handle at +0x50; the "no sound" value is the global at 0x00598690 (stored back at 0x001beff8).
  • While the shown money counts toward the inventory's (the shown value +0x44 differs from the value read, and no ±$N change is being held, +0x4c = 0): the kept handle is resolved (SoundHandle_Resolve, 0x0010f578, called at 0x001bef6c); only when it names no live sound is cue 0x10 played again (Sound_PlayInterfaceCue, 0x0010fc30, at 0x001bef84) and the new handle kept. So one looping voice plays for the whole count, and it is started again if it was lost (refused, stolen, or stopped) while the count goes on.
  • Otherwise (the count has reached the value, or a change is being held, below): when a handle is kept, the sound is stopped at once (Sound_Stop(mgr, handle, 0), 0x00110318, at 0x001befec) and the handle reset.
  • The hold. A new money value is first shown as the ±$N line for 1,000 ms (+0x4c = the clock +0x48 of 0x0050b734 plus 1,000) while the shown count stays put; only when that time has passed is the new value taken (+0x48) and the count, with its sound, starts (0x001bed0c-0x001bed34). The first change after the panel starts (+0xa20 still 0) is taken at once.
  • While it counts, the function also zeroes word +0x411c of the player's record (0x00600848[player], at 0x001bef70); what that word is was not looked at.

So the count's sound lasts exactly as long as the count (after the hold) and never outlives it.

Watched running, confirmed (runtime) on 2026-10-21 in PCSX2 (level99 checkpoint 1, player 0's panel at 0x00619d70): with the shown money +0x44 set to 200 over 0 in the inventory, the play at 0x001bef84 was hit once, on the count's first frame; the handle it returned stayed in +0x50 through all 35 shown values from 200 to 0 (about 1.2 s, many times the sample's length, so the voice was still live and looping); Sound_Stop at 0x001befec was hit once, on the first frame after the count reached 0, and +0x50 went back to 0xffffffff.

In Coney before the fix, the HUD played cue 16 once as a count started, as a fire-and-forget sound (PlayerPanel, repo:src/hud/player_panel.cpp, "Coney's choice"). Being a looping class, its voice never ended: each money pick-up, mugging or purchase left one more count_money2 voice looping until a bank change (the main menu) stopped it. That is user item 22, reproduced in a disc test (repo:tests/platform/disc_level99_money_sound_test.cpp: a $50 pick-up walked into on level99 left the sound live 5 s after the count). Coney fix, done: the panel keeps the handle, starts the cue on a counting frame when the kept sound is not playing, and stops it on the first frame without counting. The 1,000 ms hold before a count is a separate difference (Coney counts at once and shows the line meanwhile).

World one-shots

  • Wind gusts (WindManager_Update, 0x00407318): a gust starts at random (one chance in 0x00514794 × 60 per update); during it vags/ambient/environment/wind_blows_<NN> (NN 01-10 in turn) plays 2D when no player stands on covered ground, the garbage is on and not paused, the level is not 51 at checkpoint 8, the last gust sound has ended and 20 s have passed since it started. Confirmed (code).
  • Doors, glass, radios, props and other objects: World objects, Radios.

Covered ground

Human +0x5b7 is set while a player stands on a triangle with flag bit 5 (0x20; Human_SnapToGround through Human_SetCoverFlag5 0x002195e0, which also pauses the wind-blown garbage). It decides the ambient emitters' listener filter (0: only players not on covered ground hear the emitter; 1: only players on it), the × 0.25 owner duck of Task update and the wind gusts. Confirmed (code); that bit 5 marks indoor ground is inferred (level95's filter-1 emitters are room sounds such as tMusic_01, and the garbage stops).

level95: music, ambience and conversations

From level95.lua, level95_coney.lua and level95_clubhouse.lua, read with coney-tools (the bindings: Sound bindings). Confirmed (code) for the scripts' calls:

  • Matrix and bank: SndLoadMatrix('sound') in Main; the level bank is sound (Banks).
  • Music outside: SetupConeyEnvironment (run when the player leaves the clubhouse by a door) sets the system music's moods (SoundSetMusicTrack: 0 music/ambient_idle1 and music/2moog1a_loop, 1 music/120f_bit_biz_1, 2 music/2nd_trialloop_120b) and turns it on (SoundEnableSystemMusic(true)); level95_coney.lua sets the same. So outside the music is the system music: a random track of the current mood, looping.
  • Music inside: SetupClubhouseEnvironment turns the system music off; the music heard indoors is the tMusic_01 / tMusic_02 loop emitters (filter 1, name kind music, so ducked to 0.5 while a music channel plays). Opening the mission or subway menu plays MenuTrack looping at music volume 0.5 (the ambient track stopped); closing it stops the music and restores volume 1.
  • The ambient track outside (level95_coney.lua's soundbox): volume boxes call soundbox.Enter (message 3: stop the ambient track, CfgSetOutdoorMode(false)), soundbox.Exit (message 4: play the last outdoor track again, outdoor mode on) and, for outdoor boxes, soundbox.EnterOutdoor (play that box's track). The defaults are vags/ambient/city/distant_traffic_loop outside and vags/ambient/city/inside_room1_loop in rooms. Its setup also turns the effects on (SoundEnableEffects(true), SetNormalEffects).
  • Ambient emitters: AddAmbientSoundEmitters (from RegisterObjects) adds 66 emitters with AddAmbientSoundEmitter2 (41 of mode 4, one-shots; 24 of mode 3, loops; one of mode 1; listener filter 1, heard only on covered ground, for tElectric01, tElectric02, tMusic_01 and tMusic_02, 0 for the rest) and SetAmbientEmitterPositions for tDogs01, tDogs02, tENVIRO_02 and tENVIRO_03; t_pinball_machine (filter 1) is added and switched by EnableAmbientEmitter(events.PinballSound, ...) as Warriors play pinball. Every emitter follows Ambient emitters: range, plays, delays, mode and filter.
  • The clubhouse conversations are scripted (events): for each cluster of Warriors with enough talkers, events.ChatEvent runs after a random 1-5 s; it picks a Warrior who says SoundPlayCommand(h, 20 statement, 'events.FinishChatEvent', false, ...) (no interrupt) while the other looks at him, then the other says 21 response with the same callback, which queues the next chat. At the pinball machine a random one of three says 143 whoop or 202 pinball; at the workout cluster 201 workout. The lines come from the Warriors' voice sets (type 193, warr_sw, its CfgChar voice).
  • Outside, the street humans' own speech: gang banter (above), the civilians' and cops' goal lines (the table above: PedInteractGoal 179 question, 180 answer, 181 bye, crime reports, cop shakedowns, bums) and the dealers.

Coney's implementation

Coney plays these events in repo:src/audio/ (the engine and its players) and in the subsystems that raise them; the sections above say where Coney differs, such as the pick-up sound and the money count's sound.

Open questions

  • What the attacker's body +0x38 is (it silences his hits).