feat: enhance bowling physics, audio, ball weight selection, and visitor cast routines
- Bowling feel: impulse contact solver, string pinsetter cycle, in-world lengthwise return rack and visible ball return lift - Ball weights: 4/5/6/7 kg selection with equal launch work physics, momentum balance, and projected picking - Audio: dedicated MCI channels with 7 synthesized waveaudio cues (release, rolling, impacts, applause, pinsetter, return) - First-person animations: 33-frame player underarm throw/follow-through sequence (player-underarm-v2) - Visitors: 10 persistent shared cast identities with exclusive reservations, activity transitions, and chair sit/rise animations - Tests & verification: comprehensive native regression test suites and updated documentation - Synchronize binaries and update launcher hash to 536E23BED4055562BC63871826FF44FFED037923A9BE8E0F591131DB4FBD104B
This commit is contained in:
parent
24d66ddf0e
commit
7e081beeca
51 changed files with 5270 additions and 411 deletions
BIN
assets/animations/bowling/player-underarm-v2.bin
Normal file
BIN
assets/animations/bowling/player-underarm-v2.bin
Normal file
Binary file not shown.
BIN
assets/audio/bowling/applause.wav
Normal file
BIN
assets/audio/bowling/applause.wav
Normal file
Binary file not shown.
BIN
assets/audio/bowling/pins-heavy.wav
Normal file
BIN
assets/audio/bowling/pins-heavy.wav
Normal file
Binary file not shown.
BIN
assets/audio/bowling/pins-light.wav
Normal file
BIN
assets/audio/bowling/pins-light.wav
Normal file
Binary file not shown.
BIN
assets/audio/bowling/pinsetter.wav
Normal file
BIN
assets/audio/bowling/pinsetter.wav
Normal file
Binary file not shown.
BIN
assets/audio/bowling/release.wav
Normal file
BIN
assets/audio/bowling/release.wav
Normal file
Binary file not shown.
BIN
assets/audio/bowling/return.wav
Normal file
BIN
assets/audio/bowling/return.wav
Normal file
Binary file not shown.
BIN
assets/audio/bowling/rolling.wav
Normal file
BIN
assets/audio/bowling/rolling.wav
Normal file
Binary file not shown.
BIN
assets/sprites/bowling/player-underarm-v2.gif
Normal file
BIN
assets/sprites/bowling/player-underarm-v2.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 185 KiB |
25
assets/sprites/bowling/player-underarm-v2.json
Normal file
25
assets/sprites/bowling/player-underarm-v2.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"generator": "built-in image_gen",
|
||||
"source": "player-underarm-v2.png",
|
||||
"brief": "First-person right-handed underarm bowling: low pendulum swing beside thigh, backswing leaves view, hand behind/below blue ball, ankle-height release, palm-up follow-through; dark rolled sleeve; transparent 4 by 3 atlas. Replaces rejected forward-pushing draft.",
|
||||
"selected_cells": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11
|
||||
],
|
||||
"frames": 33,
|
||||
"frame_size": [
|
||||
256,
|
||||
256
|
||||
],
|
||||
"release_frame": 21,
|
||||
"audio": "Original seeded PCM synthesis, no sampled third-party recordings."
|
||||
}
|
||||
BIN
assets/sprites/bowling/player-underarm-v2.png
Normal file
BIN
assets/sprites/bowling/player-underarm-v2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 571 KiB |
BIN
bin/poker.exe
BIN
bin/poker.exe
Binary file not shown.
|
|
@ -8,7 +8,7 @@ namespace AssemblerCasinoLauncher
|
|||
{
|
||||
static class Program
|
||||
{
|
||||
const string ExpectedPokerSha256 = "3D0237E09CAED350548457BFAB24C4D67D6FAFC3D689C2D87C8BE360B64EC0AF";
|
||||
const string ExpectedPokerSha256 = "536E23BED4055562BC63871826FF44FFED037923A9BE8E0F591131DB4FBD104B";
|
||||
|
||||
[STAThread]
|
||||
static void Main()
|
||||
|
|
|
|||
Binary file not shown.
BIN
dist/Assembler Casino.exe
vendored
BIN
dist/Assembler Casino.exe
vendored
Binary file not shown.
142
docs/BOWLING.md
142
docs/BOWLING.md
|
|
@ -35,19 +35,115 @@ the committed parameters without additional random error.
|
|||
Player and bot alternate complete frames. A second ball uses the remaining rack;
|
||||
strikes, spares and tenth-frame bonuses use the shared native bowling scorer.
|
||||
The lane monitor shows the two scores and current phase. Tab toggles a cumulative
|
||||
ten-frame score sheet; unresolved bonuses stay blank rather than inventing a total.
|
||||
ten-frame score sheet with every roll, X for a strike, / for a spare and - for a
|
||||
miss; unresolved cumulative bonuses stay blank rather than inventing a total.
|
||||
The sheet pauses the current throw. Escape or the Exit command returns to the room.
|
||||
After a completed match, click or Space starts a fresh match.
|
||||
|
||||
The player game uses an arcade, not regulation-grade, collision approximation:
|
||||
16-ms fixed steps, a rolling ball disc, ten pin discs, transferred pin impulses
|
||||
and pin friction. Gutters latch once entered. Pins knocked by the ball can knock
|
||||
other pins; removed pins cannot be scored again. The opponent uses the identical
|
||||
solver, with private lane RNG choosing only its launch aim and power. The camera
|
||||
follows the rolling ball; the bot uses a full-body shared-cast throwing animation.
|
||||
The blue ball is a native shaded sphere with a procedural marble surface and
|
||||
The player game uses an arcade, not regulation-grade, collision approximation.
|
||||
Each 16-ms fixed tick has four 4-ms collision substeps. Normal impulses include
|
||||
relative velocity, restitution and the ball/pin mass ratio; overlap correction
|
||||
does not apply a second impulse to opening contacts. Billiards-style contact
|
||||
resolution is reused without changing the billiards module. Contact normals and
|
||||
pin axes retain fractional precision and are renormalized after yaw: even tiny
|
||||
negative impulses cannot turn an ellipsoid into a clipped rectangular slab. Fallen pins still
|
||||
collide and transfer momentum. Kickbacks and the back cushion return pins to the
|
||||
deck; friction damps sliding and spin, increasing after the initial collision
|
||||
cascade. Bounds include the tilted pin's full silhouette. Gutters latch once entered.
|
||||
|
||||
The match uses a shopping-centre-style string pinsetter with cords intentionally
|
||||
not drawn. Invisible slack tethers allow about 0.5 world units of travel from
|
||||
each spot, damping outward motion only at the limit rather than pulling pins
|
||||
back during the roll. Constraints run after every 4-ms contact substep.
|
||||
A separate 5.2-second reset cycle closes a smooth metal pin shield, raises and
|
||||
straightens the pins behind it, holds them aloft, lowers only the remaining pins
|
||||
after the first ball (or all ten for a fresh rack), then opens the shield. A
|
||||
first-ball miss leaves the standing rack alone, without running the motor.
|
||||
Knocked-down pins remain physically represented aloft behind the hood, rather
|
||||
than disappearing halfway up. The close camera eases back to frame the machine.
|
||||
Rendering this cycle never changes scoring or advances the turn twice.
|
||||
The sequence is based on Brunswick StringPin's documented standing-pin, strike,
|
||||
second-ball and gutter cycles, with a front shield as on contemporary string machines:
|
||||
https://brunswickbowling.com/uploads/document-library/Service-Manuals/Pinsetters/StringPin/BB_Service_Operations_Manual_StringPin_55-900004-000_En_Rev-06-16.pdf
|
||||
Video reference: https://www.youtube.com/watch?v=EUwpfHz1Fp4
|
||||
|
||||
Impact excites a separate spring/gravity rocking angle: a small nudge can recover,
|
||||
while a pin crossing the fall threshold is scored. Pins keep falling and hitting
|
||||
one another after the ball passes; scoring waits for settlement with a bounded
|
||||
timeout. Oriented ray/ellipsoid surfaces follow each pin's fall direction and
|
||||
rolling yaw. This remains a floor-plane impulse solver with angular toppling,
|
||||
not an unconstrained 3D rigid-body simulation. Other exhibition lanes retain
|
||||
their existing automatic simulation; player and match opponent share the new
|
||||
solver. Removed pins cannot be scored twice.
|
||||
|
||||
Private lane RNG chooses only the opponent's launch aim and power. The player
|
||||
has a 33-frame first-person underarm sequence: the backswing leaves the view,
|
||||
the camera bends toward the low release, and the actual ball begins moving at
|
||||
the release event. The held-ball sprite is never drawn over the rolling sphere.
|
||||
The rejected forward-push draft is not shipped. Direction/power controls remain
|
||||
unchanged, with the power meter on the left, away from the player's arm.
|
||||
The camera follows the ball and returns to the approach as the reset finishes.
|
||||
The bot uses a full-body shared-cast throwing animation.
|
||||
Each ball is a native shaded sphere with a procedural marble surface and
|
||||
rotating finger-hole details, not a new neural or image runtime.
|
||||
|
||||
After every roll, including a first-ball miss and the last ball of the match,
|
||||
the lane enters a 2.8-second ball-return phase. The ball disappears into the rear
|
||||
pit, travels through the hidden return, then visibly emerges from the paired
|
||||
return hood, rolls along the metal guides and stops in the tray. The camera
|
||||
turns toward the correct left/right return unit and eases back to the approach;
|
||||
the player's held-ball pose rises into view only after the tray ball is hidden.
|
||||
The returning ball retains its committed colour; its storage slot stays empty.
|
||||
Input during return cannot launch or lock the next throw. The existing scorer
|
||||
advances exactly once before presentation; the final result overlay waits until
|
||||
the ball has returned. Tab pauses this phase and its motor sound; Escape still
|
||||
restores the saved room position and camera. The room's four return machines
|
||||
have native hood/rail geometry and collision around their extended trays.
|
||||
The return cycle does not change launch parameters or scores.
|
||||
|
||||
### Ball Mass
|
||||
|
||||
Before a match, the camera faces the actual paired return's ball storage rack.
|
||||
Four balls (4 kg green, 5 kg red, 6 kg blue, 7 kg amber) rest lengthwise on two
|
||||
metal rails beside the separate automatic return track. Click a sphere or its
|
||||
projected weight plate to take it; Space takes the default/current ball. Keys
|
||||
1-4 also select a ball. The weight command during aiming reopens this same rack.
|
||||
Sphere picking and plates use the same world projection on either lane side.
|
||||
The chosen ball's slot is empty while it is held, rolled or returned. A cached
|
||||
single-frame palette transform colours only blue ball pixels in the hand atlas,
|
||||
preserving skin, sleeve and alpha without duplicating the full animation pack.
|
||||
Selecting a mass consumes its own event; it never also locks direction.
|
||||
The default and opponent use 6 kg. The committed mass is frozen
|
||||
for the whole throw; changing the next selection cannot alter an in-flight ball.
|
||||
|
||||
Each pin has mass 1600 grams, within the USBC standard pin range:
|
||||
https://bowl.com/welcome/how-bowling-pins-are-made
|
||||
The normal impulse solver uses Q16 inverse masses proportional to 1600/mass_g,
|
||||
with signed 64-bit products to avoid overflow. It retains restitution 0.5 and
|
||||
mass-weighted separation. A heavier ball loses a smaller fraction of its incoming
|
||||
velocity at an otherwise identical contact. No random accuracy penalty, strike
|
||||
bonus or mass-dependent floor-friction multiplier is added.
|
||||
|
||||
The gauge fixes the launch work W, calibrated to the original 6 kg release:
|
||||
v_reference = 3 + 6 * power/100 m/s, W = 0.5 * 6 * v_reference^2 joules.
|
||||
Actual speed is v_reference * sqrt(6 / mass_kg). The launch direction is normalized
|
||||
so aiming away from the centre does not add extra speed. This is translational
|
||||
launch work, not a complete model of arm biomechanics or rolling rotational energy.
|
||||
Greater mass is therefore not an unconditional advantage: lighter balls launch
|
||||
faster at equal work, while heavier balls resist collision deflection better.
|
||||
|
||||
The opponent and two nearby spectators use their existing persistent identities
|
||||
and react to the result. Their restaurant duplicates are suppressed during the
|
||||
match. Strikes, spares and strong throws trigger shared-cast cheering; misses
|
||||
leave conversational poses rather than forcing a celebration.
|
||||
|
||||
Seven dedicated MCI waveaudio channels provide release, rolling, light/heavy pin
|
||||
impacts, applause, the pinsetter motor and ball return. Impacts are driven by contact energy and rate-limited,
|
||||
not triggered by rendering. The current sound-volume setting, including mute,
|
||||
is applied before playback. Opening the score sheet stops the rolling channel;
|
||||
leaving the match closes every alias. Effects are original seeded offline PCM
|
||||
synthesis, not recordings taken from another game.
|
||||
|
||||
## Visitor Simulation
|
||||
|
||||
Each occupied lane owns a timer, rack mask, two players, frame counters and roll
|
||||
|
|
@ -64,6 +160,16 @@ the other hall assets. No city mesh or rooftop OpenGL pass is used here.
|
|||
## Sources And Rebuild
|
||||
|
||||
- `src_graphics/bowling*.inc`: native room and lane simulation.
|
||||
- `bowling_physics.inc`, `bowling_deck.inc`, `bowling_pinsetter.inc`, `bowling_return.inc`,
|
||||
`bowling_weight.inc`,
|
||||
`bowling_pin_shape.inc`, `bowling_scorecard.inc`,
|
||||
`bowling_performance.inc`, `bowling_audio.inc`: match physics and presentation.
|
||||
- `tools/generators/pack_bowling_feel.py`: first-person atlas normalization,
|
||||
offline in-betweens and original PCM Foley.
|
||||
- `assets/sprites/bowling/player-underarm-v2.png` and `.json`: retained built-in
|
||||
imagegen source and generation brief. The packed 33-frame ANM1 asset lives in
|
||||
`assets/animations/bowling/player-underarm-v2.bin`.
|
||||
- `assets/audio/bowling/`: seven distributable WAV effects.
|
||||
- `tools/generators/pack_bowling.py`: offline atlas packing, frame normalization,
|
||||
in-between frames and furniture/collision tables.
|
||||
- `assets/sprites/bowling/`: retained image-generation sources.
|
||||
|
|
@ -88,6 +194,26 @@ The additional `bowling_play_test.inc` covers LMB/Space input through native win
|
|||
events, stage separation, deterministic impacts at two frame deltas, gutters,
|
||||
empty/remaining racks, alternating turns, spare feedback, perfect games and the
|
||||
tenth-frame bonuses, unresolved score cells, scene captures and exit restoration.
|
||||
`bowling_feel_test.inc` additionally checks recoverable rocking, strong toppling,
|
||||
opening and repeated fallen-pin contacts, late settlement, tenth-frame glyphs,
|
||||
63 aim/power launches, invisible travel limits, complete tilted-body bounds,
|
||||
automatic guard/hoist/respots, first-miss idle, duplicate-score prevention,
|
||||
tiny-impact axis/silhouette regressions, per-substep travel limits,
|
||||
eight pinsetter captures,
|
||||
33 native hand captures and real muted MCI playback/cleanup.
|
||||
`bowling_return_test.inc` covers the paired return positions and camera turns,
|
||||
visible rise/coast, held-ball handoff, blocked throw input, pause/resume, final-ball
|
||||
return before results, unchanged scores/turns, tray collision and exit restoration.
|
||||
Eight native return captures also produce `build/hall-expansion/bowling-native-return.gif`.
|
||||
`bowling_weight_test.inc` checks world-projected sphere/plate selection on both
|
||||
lane pairs, non-overlapping kg labels, storage-rail collision, colour and alpha
|
||||
preservation in source/scratch hand pixels, native mouse/key input, immutable
|
||||
shot mass, bot independence, equal launch work, momentum balance, restitution and
|
||||
non-increasing translational contact energy. An additional 84 complete high-power
|
||||
throws across all four masses verify settlement and deck bounds without replacing
|
||||
the simulated outcomes.
|
||||
The handoff and follow-through convention follows the USBC release guidance:
|
||||
https://bowl.com/welcome/developing-your-release-f7b6dd1aff6c612e4aea7fce9dbb9194
|
||||
The complete hall suite includes the same bowling checks alongside existing
|
||||
stairs, doors, rooftop, fortune-room, bar and cabaret regressions. `--parity`
|
||||
compares the tested procedures with the shipping assembly object.
|
||||
|
|
|
|||
|
|
@ -42,6 +42,58 @@ pick it up, throw, return, sit and alternate turns while keeping their identity.
|
|||
The historical twelve-slot NPC journal is preserved for save compatibility;
|
||||
its appearance mapping resolves to the ten shared visual identities.
|
||||
|
||||
## Main Hall Routines
|
||||
|
||||
The main hall now has ten simultaneous visitors with fixed identities, rather
|
||||
than six slots changing people at the entrance. The first six legacy poker-mind
|
||||
records retain their size and personality indices; four extra world actors use
|
||||
the same bounded entity accessor. The twelve-entry contract journal is retained
|
||||
without changing existing profile saves. Ten of its identities are currently
|
||||
represented in the hall; old entries are not deleted or reassigned.
|
||||
|
||||
Each visitor has a preferred game, walking speed, session length, private
|
||||
ambient wallet and private RNG. Weighted destinations replace the single shared
|
||||
route. Short abstract game sessions produce a win/loss reaction, after which
|
||||
guests continue playing or take a break. These are ambient outcomes, not full
|
||||
hands played by the actual card-game engines. Neither the player's bankroll,
|
||||
casino RNG, achievements nor contract progress is touched.
|
||||
|
||||
There are twelve reservable places: five game approaches, two bar positions,
|
||||
two existing lounge chairs, two audience positions and the entrance. Guests
|
||||
order, drink, rest, converse with a nearby stationary guest and watch the stage.
|
||||
Only short nearby remarks are displayed. Stale remarks clear on arrival.
|
||||
Rest/drinks ease negative mood. Out-of-funds guests leave through the entrance,
|
||||
wait offstage and return as the same person with a new ambient budget.
|
||||
|
||||
BFS and body clearance still use the real room geometry. A visitor reserves a
|
||||
place before walking and releases it after a successful change of destination.
|
||||
Blocked guests pause with staggered retries; persistent obstruction releases
|
||||
the reservation and permits replanning. Gait only advances on actual movement.
|
||||
Seated poses align with the two existing chairs and pause navigation during the
|
||||
stand-up transition. Visitor canvas dimensions remain unchanged.
|
||||
|
||||
Pathfinding checks quarter points along each tile edge, not just free tile
|
||||
centres, so approaches cannot cut through the expanded chair collision. Seating
|
||||
has its own bounded 800 ms clock: starting a conversation resets the activity
|
||||
clock but cannot replay the sit-down animation. The visual seat anchor blends
|
||||
smoothly in both directions; walking frames require actual movement velocity.
|
||||
|
||||
Routines currently belong to the main hall. Other floors keep their existing
|
||||
ambient controllers and shared appearance assets; this is not yet a persistent
|
||||
cross-floor population simulation. Hall routines pause outside walking mode or
|
||||
outside the main hall, including while a modal conversation is open.
|
||||
|
||||
`check_hall_expansion.py --npc-only` compiles production MASM and checks eight
|
||||
simulated minutes: fixed identities, exclusive reservations, reachable positions,
|
||||
activity transitions, walking progress, player-bank/RNG isolation, modal/floor
|
||||
pause and bounded recovery from a player blocking the path. It also captures
|
||||
native order, drinking, seated, win and loss poses. Full hall checks include the
|
||||
same cases; no neural model or new runtime dependency is needed.
|
||||
The chair regression also walks a visitor to a real chair at 16 ms ticks, checks
|
||||
the complete sit/rise frame sequence and monotonic anchor motion, and starts a
|
||||
seated conversation without restarting the transition. Native captures and GIFs
|
||||
are written as `build/hall-expansion/npc-chair-*`.
|
||||
|
||||
## Assets
|
||||
|
||||
- `assets/sprites/characters/person-00-source-v1.png` through `person-09-source-v1.png`:
|
||||
|
|
|
|||
BIN
poker.exe
BIN
poker.exe
Binary file not shown.
BIN
poker.obj
BIN
poker.obj
Binary file not shown.
|
|
@ -1,7 +1,10 @@
|
|||
; Native room, automatic lane simulation and full-body visitors; no AI service.
|
||||
InitBowling3D PROC uses esi edi
|
||||
mov bpActive3D,0
|
||||
mov bpWeightKg3D,6
|
||||
mov bpBotWeightKg3D,6
|
||||
call InitBowlingBallSurface3D
|
||||
call InitBowlingSetterSurface3D
|
||||
mov bwClock3D,-1
|
||||
mov bwMonitorClock3D,-1
|
||||
mov bwSeat3D,0
|
||||
|
|
@ -48,12 +51,18 @@ LoadBowling3D PROC
|
|||
invoke LoadAnimPack3D,OFFSET bwArt3D,OFFSET bwArtPath3D
|
||||
invoke ValidateCityPack3D,OFFSET bwArt3D,256,256,14
|
||||
call LoadCharacterCast3D
|
||||
invoke LoadAnimPack3D,OFFSET bpHandArt3D,OFFSET bpHandPath3D
|
||||
invoke ValidateCityPack3D,OFFSET bpHandArt3D,256,256,33
|
||||
mov bpRackHandFrame3D,-1
|
||||
mov bpRackHandKg3D,-1
|
||||
call RefreshBowlingMonitors3D
|
||||
bw_load_done:
|
||||
ret
|
||||
LoadBowling3D ENDP
|
||||
|
||||
FreeBowling3D PROC
|
||||
call BowlingAudioClose3D
|
||||
invoke FreeAnimPack3D,OFFSET bpHandArt3D
|
||||
invoke FreeAnimPack3D,OFFSET bwArt3D
|
||||
invoke FreeAnimPack3D,OFFSET bwMotionArt3D
|
||||
invoke FreeAnimPack3D,OFFSET bwSeatedArt3D
|
||||
|
|
@ -62,6 +71,24 @@ FreeBowling3D ENDP
|
|||
|
||||
ResolveBowlingSurface3D PROC material:DWORD
|
||||
mov eax,material
|
||||
cmp eax,255
|
||||
jb bw_material_base
|
||||
cmp eax,257
|
||||
ja bw_material_missing
|
||||
sub eax,254
|
||||
shl eax,14
|
||||
add eax,OFFSET bpBallSurface3D
|
||||
mov ecx,64
|
||||
mov edx,64
|
||||
ret
|
||||
bw_material_base:
|
||||
cmp eax,254
|
||||
jne @F
|
||||
mov eax,OFFSET bpSetterSurface3D
|
||||
mov ecx,64
|
||||
mov edx,64
|
||||
ret
|
||||
@@:
|
||||
cmp eax,253
|
||||
jne @F
|
||||
mov eax,OFFSET bpBallSurface3D
|
||||
|
|
@ -173,6 +200,36 @@ BowlingCanWalk3D PROC uses esi edi px:DWORD,py:DWORD
|
|||
cmp py,FP_1*223/10
|
||||
jb bw_walk_block
|
||||
bw_walk_furniture:
|
||||
cmp py,FP_1*252/10
|
||||
jb bw_walk_existing_props
|
||||
cmp py,FP_1*266/10
|
||||
ja bw_walk_existing_props
|
||||
xor esi,esi
|
||||
bw_walk_return_tray:
|
||||
imul eax,esi,FP_1*38/10
|
||||
add eax,FP_1*395/100
|
||||
sub eax,px
|
||||
mov edi,eax
|
||||
cdq
|
||||
xor eax,edx
|
||||
sub eax,edx
|
||||
cmp py,26*FP_1
|
||||
jb @F
|
||||
cmp eax,FP_1*4/10
|
||||
jbe bw_walk_block
|
||||
@@:
|
||||
; The adjacent storage rails keep the automatic return path clear.
|
||||
mov eax,edi
|
||||
neg eax
|
||||
cmp eax,FP_1*25/100
|
||||
jl @F
|
||||
cmp eax,FP_1*85/100
|
||||
jle bw_walk_block
|
||||
@@:
|
||||
inc esi
|
||||
cmp esi,4
|
||||
jb bw_walk_return_tray
|
||||
bw_walk_existing_props:
|
||||
lea esi,bwCollision3D
|
||||
mov edi,BOWL_COLLISION_COUNT
|
||||
bw_walk_prop:
|
||||
|
|
|
|||
119
src_graphics/bowling_audio.inc
Normal file
119
src_graphics/bowling_audio.inc
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
BowlingAudioOpen3D PROC uses esi
|
||||
call BowlingAudioClose3D
|
||||
; Offscreen mechanics probes have no playback device or foreground window.
|
||||
cmp h3DWnd,0
|
||||
je bp_audio_open_done
|
||||
xor esi,esi
|
||||
bp_audio_open:
|
||||
invoke mciSendStringA,bpAudioOpens[esi*4],0,0,0
|
||||
inc esi
|
||||
cmp esi,7
|
||||
jb bp_audio_open
|
||||
mov bpAudioReady3D,1
|
||||
mov bpAudioVolume3D,-1
|
||||
bp_audio_open_done:
|
||||
ret
|
||||
BowlingAudioOpen3D ENDP
|
||||
|
||||
BowlingAudioClose3D PROC uses esi
|
||||
cmp bpAudioReady3D,0
|
||||
je bp_audio_close_done
|
||||
xor esi,esi
|
||||
bp_audio_close:
|
||||
invoke mciSendStringA,bpAudioCloses[esi*4],0,0,0
|
||||
inc esi
|
||||
cmp esi,7
|
||||
jb bp_audio_close
|
||||
bp_audio_close_done:
|
||||
mov bpAudioReady3D,0
|
||||
mov bpAudioRolling3D,0
|
||||
mov bpAudioReturning3D,0
|
||||
ret
|
||||
BowlingAudioClose3D ENDP
|
||||
|
||||
BowlingAudioUpdate3D PROC uses ebx esi
|
||||
cmp bpAudioReady3D,0
|
||||
je bp_audio_done
|
||||
mov eax,settingsVolume
|
||||
cmp eax,bpAudioVolume3D
|
||||
je bp_audio_state
|
||||
mov bpAudioVolume3D,eax
|
||||
xor esi,esi
|
||||
bp_audio_gain:
|
||||
mov eax,settingsVolume
|
||||
imul eax,70
|
||||
test esi,esi
|
||||
jnz @F
|
||||
imul eax,settingsVolume,35
|
||||
@@:
|
||||
invoke FormatNumber,eax,OFFSET bpText3D
|
||||
invoke CopyCString,OFFSET bpAudioCommand,bpAudioPrefixes[esi*4]
|
||||
invoke AppendCString,OFFSET bpAudioCommand,OFFSET bpText3D
|
||||
invoke mciSendStringA,OFFSET bpAudioCommand,0,0,0
|
||||
inc esi
|
||||
cmp esi,7
|
||||
jb bp_audio_gain
|
||||
bp_audio_state:
|
||||
xor ebx,ebx
|
||||
cmp bpState3D,BP_ROLL
|
||||
jne @F
|
||||
cmp bpScoreOpen3D,0
|
||||
jne @F
|
||||
cmp bpEndTicks3D,0
|
||||
jne @F
|
||||
mov ebx,1
|
||||
@@:
|
||||
cmp ebx,bpAudioRolling3D
|
||||
je bp_audio_return
|
||||
mov bpAudioRolling3D,ebx
|
||||
test ebx,ebx
|
||||
jz bp_audio_stop_roll
|
||||
cmp bpAudioReleased3D,0
|
||||
jne @F
|
||||
mov bpAudioReleased3D,1
|
||||
invoke mciSendStringA,OFFSET bpReleasePlay,0,0,0
|
||||
@@:
|
||||
mov eax,OFFSET bpRollPlay
|
||||
jmp bp_audio_send_roll
|
||||
bp_audio_stop_roll:
|
||||
mov eax,OFFSET bpRollStop
|
||||
bp_audio_send_roll:
|
||||
invoke mciSendStringA,eax,0,0,0
|
||||
bp_audio_return:
|
||||
xor ebx,ebx
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne @F
|
||||
cmp bpScoreOpen3D,0
|
||||
jne @F
|
||||
cmp bpTime3D,2000
|
||||
jae @F
|
||||
mov ebx,1
|
||||
@@:
|
||||
cmp ebx,bpAudioReturning3D
|
||||
je bp_audio_impact
|
||||
mov bpAudioReturning3D,ebx
|
||||
mov eax,OFFSET bpReturnStop
|
||||
test ebx,ebx
|
||||
jz @F
|
||||
invoke FormatNumber,bpTime3D,OFFSET bpText3D
|
||||
invoke CopyCString,OFFSET bpAudioCommand,OFFSET bpReturnPlay
|
||||
invoke AppendCString,OFFSET bpAudioCommand,OFFSET bpText3D
|
||||
mov eax,OFFSET bpAudioCommand
|
||||
@@:
|
||||
invoke mciSendStringA,eax,0,0,0
|
||||
bp_audio_impact:
|
||||
cmp bpImpactCooldown3D,0
|
||||
jne bp_audio_done
|
||||
cmp bpImpactEnergy3D,768
|
||||
jb bp_audio_done
|
||||
mov eax,OFFSET bpLightPlay
|
||||
cmp bpImpactEnergy3D,4000
|
||||
jb @F
|
||||
mov eax,OFFSET bpImpactPlay
|
||||
@@:
|
||||
invoke mciSendStringA,eax,0,0,0
|
||||
mov bpImpactCooldown3D,140
|
||||
mov bpImpactEnergy3D,0
|
||||
bp_audio_done:
|
||||
ret
|
||||
BowlingAudioUpdate3D ENDP
|
||||
35
src_graphics/bowling_audio_data.inc
Normal file
35
src_graphics/bowling_audio_data.inc
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
.data
|
||||
bpRollOpen db 'open "assets/audio/bowling/rolling.wav" type waveaudio alias bowlroll',0
|
||||
bpImpactOpen db 'open "assets/audio/bowling/pins-heavy.wav" type waveaudio alias bowlpins',0
|
||||
bpReleaseOpen db 'open "assets/audio/bowling/release.wav" type waveaudio alias bowlrelease',0
|
||||
bpClapOpen db 'open "assets/audio/bowling/applause.wav" type waveaudio alias bowlclap',0
|
||||
bpLightOpen db 'open "assets/audio/bowling/pins-light.wav" type waveaudio alias bowllight',0
|
||||
bpResetOpen db 'open "assets/audio/bowling/pinsetter.wav" type waveaudio alias bowlreset',0
|
||||
bpReturnOpen db 'open "assets/audio/bowling/return.wav" type waveaudio alias bowlreturn',0
|
||||
bpReturnPlay db 'play bowlreturn from ',0
|
||||
bpReturnStop db 'stop bowlreturn',0
|
||||
bpRollPlay db 'play bowlroll from 0',0
|
||||
bpRollStop db 'stop bowlroll',0
|
||||
bpImpactPlay db 'play bowlpins from 0',0
|
||||
bpReleasePlay db 'play bowlrelease from 0',0
|
||||
bpClapPlay db 'play bowlclap from 0',0
|
||||
bpLightPlay db 'play bowllight from 0',0
|
||||
bpResetPlay db 'play bowlreset from 0',0
|
||||
bpRollClose db 'close bowlroll',0
|
||||
bpImpactClose db 'close bowlpins',0
|
||||
bpReleaseClose db 'close bowlrelease',0
|
||||
bpClapClose db 'close bowlclap',0
|
||||
bpLightClose db 'close bowllight',0
|
||||
bpResetClose db 'close bowlreset',0
|
||||
bpReturnClose db 'close bowlreturn',0
|
||||
bpAudioOpens dd OFFSET bpRollOpen,OFFSET bpImpactOpen,OFFSET bpReleaseOpen,OFFSET bpClapOpen,OFFSET bpLightOpen,OFFSET bpResetOpen,OFFSET bpReturnOpen
|
||||
bpAudioCloses dd OFFSET bpRollClose,OFFSET bpImpactClose,OFFSET bpReleaseClose,OFFSET bpClapClose,OFFSET bpLightClose,OFFSET bpResetClose,OFFSET bpReturnClose
|
||||
bpVolumeRoll db 'setaudio bowlroll volume to ',0
|
||||
bpVolumePins db 'setaudio bowlpins volume to ',0
|
||||
bpVolumeRelease db 'setaudio bowlrelease volume to ',0
|
||||
bpVolumeClap db 'setaudio bowlclap volume to ',0
|
||||
bpVolumeLight db 'setaudio bowllight volume to ',0
|
||||
bpVolumeReset db 'setaudio bowlreset volume to ',0
|
||||
bpVolumeReturn db 'setaudio bowlreturn volume to ',0
|
||||
bpAudioPrefixes dd OFFSET bpVolumeRoll,OFFSET bpVolumePins,OFFSET bpVolumeRelease,OFFSET bpVolumeClap,OFFSET bpVolumeLight,OFFSET bpVolumeReset,OFFSET bpVolumeReturn
|
||||
bpAudioCommand db 80 dup(0)
|
||||
|
|
@ -2,7 +2,7 @@ HALL_BOWLING equ 5
|
|||
INTERACT_BOWL_SEAT equ 53
|
||||
INTERACT_BOWL_WATCH equ 54
|
||||
BW_MATERIAL equ 230
|
||||
BW_LAST_MATERIAL equ 253
|
||||
BW_LAST_MATERIAL equ 257
|
||||
BW_LANES equ 8
|
||||
BW_LANE_STEP equ FP_1*19/10
|
||||
InitBowling3D PROTO
|
||||
|
|
@ -22,6 +22,7 @@ RenderBowlingLanes3D PROTO
|
|||
RenderBowlingVisitors3D PROTO
|
||||
DrawBowlingPin3D PROTO :DWORD,:DWORD,:DWORD
|
||||
DrawBowlingBall3D PROTO :DWORD,:DWORD,:DWORD
|
||||
DrawBowlingBallAt3D PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||
BowlingImpact3D PROTO :DWORD
|
||||
BowlingRegisterRoll3D PROTO :DWORD,:DWORD
|
||||
BowlingScore3D PROTO :DWORD
|
||||
|
|
|
|||
149
src_graphics/bowling_deck.inc
Normal file
149
src_graphics/bowling_deck.inc
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
; Invisible slack constraints engage only at the end of a pin's free travel.
|
||||
BowlingPlayTether3D PROC uses ebx esi pin:DWORD
|
||||
local deltaX:DWORD,deltaY:DWORD,length8:DWORD,nx:DWORD,ny:DWORD,outward:DWORD
|
||||
mov esi,pin
|
||||
mov eax,bpPinX3D[esi*4]
|
||||
sub eax,bwPinX3D[esi*4]
|
||||
mov deltaX,eax
|
||||
sar eax,8
|
||||
imul eax,eax
|
||||
mov ebx,eax
|
||||
mov eax,bpPinY3D[esi*4]
|
||||
sub eax,bwPinY3D[esi*4]
|
||||
mov deltaY,eax
|
||||
sar eax,8
|
||||
imul eax,eax
|
||||
add eax,ebx
|
||||
cmp eax,128*128
|
||||
jbe bp_tether_done
|
||||
invoke PoolSqrt3D,eax
|
||||
mov length8,eax
|
||||
mov eax,deltaX
|
||||
imul eax,256
|
||||
cdq
|
||||
idiv length8
|
||||
mov nx,eax
|
||||
mov eax,deltaY
|
||||
imul eax,256
|
||||
cdq
|
||||
idiv length8
|
||||
mov ny,eax
|
||||
mov eax,nx
|
||||
imul eax,128
|
||||
sar eax,8
|
||||
add eax,bwPinX3D[esi*4]
|
||||
mov bpPinX3D[esi*4],eax
|
||||
mov eax,ny
|
||||
imul eax,128
|
||||
sar eax,8
|
||||
add eax,bwPinY3D[esi*4]
|
||||
mov bpPinY3D[esi*4],eax
|
||||
mov eax,bpPinVX3D[esi*4]
|
||||
imul nx
|
||||
shrd eax,edx,16
|
||||
mov ebx,eax
|
||||
mov eax,bpPinVY3D[esi*4]
|
||||
imul ny
|
||||
shrd eax,edx,16
|
||||
add eax,ebx
|
||||
test eax,eax
|
||||
jle bp_tether_done
|
||||
imul eax,4
|
||||
cdq
|
||||
mov ecx,5
|
||||
idiv ecx
|
||||
mov outward,eax
|
||||
imul nx
|
||||
shrd eax,edx,16
|
||||
sub bpPinVX3D[esi*4],eax
|
||||
mov eax,outward
|
||||
imul ny
|
||||
shrd eax,edx,16
|
||||
sub bpPinVY3D[esi*4],eax
|
||||
bp_tether_done:
|
||||
ret
|
||||
BowlingPlayTether3D ENDP
|
||||
|
||||
; Bound the complete pin silhouette, including its horizontal neck/head.
|
||||
BowlingPlayDeckBounds3D PROC uses ebx esi pin:DWORD
|
||||
local extension:DWORD,lo:DWORD,hi:DWORD
|
||||
mov esi,pin
|
||||
mov ecx,bpPinTilt3D[esi*4]
|
||||
shr ecx,8
|
||||
mov eax,tableSin[ecx*4]
|
||||
imul eax,35
|
||||
cdq
|
||||
mov ecx,100
|
||||
idiv ecx
|
||||
mov extension,eax
|
||||
imul bpPinAxisX3D[esi*4]
|
||||
shrd eax,edx,16
|
||||
mov lo,-FP_1*82/100
|
||||
mov hi,FP_1*82/100
|
||||
test eax,eax
|
||||
js bp_deck_left_extent
|
||||
sub hi,eax
|
||||
jmp bp_deck_x
|
||||
bp_deck_left_extent:
|
||||
sub lo,eax
|
||||
bp_deck_x:
|
||||
mov eax,bpPinX3D[esi*4]
|
||||
cmp eax,lo
|
||||
jge bp_deck_right
|
||||
mov eax,lo
|
||||
mov bpPinX3D[esi*4],eax
|
||||
cmp bpPinVX3D[esi*4],0
|
||||
jge bp_deck_y_extent
|
||||
jmp bp_deck_bounce_x
|
||||
bp_deck_right:
|
||||
cmp eax,hi
|
||||
jle bp_deck_y_extent
|
||||
mov eax,hi
|
||||
mov bpPinX3D[esi*4],eax
|
||||
cmp bpPinVX3D[esi*4],0
|
||||
jle bp_deck_y_extent
|
||||
bp_deck_bounce_x:
|
||||
mov eax,bpPinVX3D[esi*4]
|
||||
neg eax
|
||||
cdq
|
||||
mov ecx,5
|
||||
idiv ecx
|
||||
mov bpPinVX3D[esi*4],eax
|
||||
bp_deck_y_extent:
|
||||
mov eax,extension
|
||||
imul bpPinAxisY3D[esi*4]
|
||||
shrd eax,edx,16
|
||||
mov lo,FP_1*308/100
|
||||
mov hi,FP_1*547/100
|
||||
test eax,eax
|
||||
js bp_deck_back_extent
|
||||
sub hi,eax
|
||||
jmp bp_deck_y
|
||||
bp_deck_back_extent:
|
||||
sub lo,eax
|
||||
bp_deck_y:
|
||||
mov eax,bpPinY3D[esi*4]
|
||||
cmp eax,lo
|
||||
jge bp_deck_front
|
||||
mov eax,lo
|
||||
mov bpPinY3D[esi*4],eax
|
||||
cmp bpPinVY3D[esi*4],0
|
||||
jge bp_deck_done
|
||||
jmp bp_deck_bounce_y
|
||||
bp_deck_front:
|
||||
cmp eax,hi
|
||||
jle bp_deck_done
|
||||
mov eax,hi
|
||||
mov bpPinY3D[esi*4],eax
|
||||
cmp bpPinVY3D[esi*4],0
|
||||
jle bp_deck_done
|
||||
bp_deck_bounce_y:
|
||||
mov eax,bpPinVY3D[esi*4]
|
||||
neg eax
|
||||
cdq
|
||||
mov ecx,5
|
||||
idiv ecx
|
||||
mov bpPinVY3D[esi*4],eax
|
||||
bp_deck_done:
|
||||
ret
|
||||
BowlingPlayDeckBounds3D ENDP
|
||||
120
src_graphics/bowling_performance.inc
Normal file
120
src_graphics/bowling_performance.inc
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
DrawBowlingPlayerHand3D PROC uses ebx esi
|
||||
local offsetY:DWORD
|
||||
mov offsetY,120
|
||||
cmp bpHandArt3D.pixels,0
|
||||
je bp_hand_done
|
||||
cmp bpScoreOpen3D,0
|
||||
jne bp_hand_done
|
||||
mov esi,bpLane3D
|
||||
cmp bwTurn3D[esi*4],0
|
||||
jne bp_hand_done
|
||||
xor ebx,ebx
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne @F
|
||||
cmp bpAfterReturn3D,BP_FINISHED
|
||||
je bp_hand_done
|
||||
mov eax,bpTime3D
|
||||
sub eax,2100
|
||||
jle bp_hand_done
|
||||
invoke BowlingPinsetterEase3D,eax,700
|
||||
neg eax
|
||||
add eax,FP_1
|
||||
imul eax,300
|
||||
sar eax,16
|
||||
add eax,120
|
||||
mov offsetY,eax
|
||||
jmp bp_hand_draw
|
||||
@@:
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
je bp_hand_draw
|
||||
cmp bpState3D,BP_POWER
|
||||
je bp_hand_draw
|
||||
cmp bpState3D,BP_RELEASE
|
||||
jne bp_hand_follow
|
||||
mov eax,bpTime3D
|
||||
xor edx,edx
|
||||
mov ecx,33
|
||||
div ecx
|
||||
cmp eax,20
|
||||
jbe @F
|
||||
mov eax,20
|
||||
@@:
|
||||
mov ebx,eax
|
||||
jmp bp_hand_draw
|
||||
bp_hand_follow:
|
||||
cmp bpState3D,BP_ROLL
|
||||
jne bp_hand_done
|
||||
cmp bpTime3D,396
|
||||
jae bp_hand_done
|
||||
mov eax,bpTime3D
|
||||
xor edx,edx
|
||||
mov ecx,33
|
||||
div ecx
|
||||
add eax,21
|
||||
cmp eax,32
|
||||
jbe @F
|
||||
mov eax,32
|
||||
@@:
|
||||
mov ebx,eax
|
||||
bp_hand_draw:
|
||||
mov eax,bpShotWeightKg3D
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
je bp_hand_selected
|
||||
cmp bpState3D,BP_POWER
|
||||
jne @F
|
||||
bp_hand_selected:
|
||||
mov eax,bpWeightKg3D
|
||||
@@:
|
||||
invoke BowlingTintHand3D,ebx,eax
|
||||
invoke DrawAnimSprite3D,OFFSET bpTintedHand3D,0,320,offsetY,320,320
|
||||
bp_hand_done:
|
||||
ret
|
||||
DrawBowlingPlayerHand3D ENDP
|
||||
|
||||
RenderBowlingReactions3D PROC uses ebx esi edi
|
||||
local phase:DWORD
|
||||
mov phase,CAST_TALK
|
||||
cmp bpReactionTime3D,0
|
||||
je @F
|
||||
mov eax,bpReaction3D
|
||||
mov phase,eax
|
||||
@@:
|
||||
xor esi,esi
|
||||
bp_crowd_person:
|
||||
lea ebx,[esi+6]
|
||||
test esi,esi
|
||||
jnz bp_crowd_draw
|
||||
mov edi,bpLane3D
|
||||
cmp bwTurn3D[edi*4],1
|
||||
jne bp_crowd_draw
|
||||
cmp bpState3D,BP_SETTLE
|
||||
je bp_crowd_draw
|
||||
cmp bpState3D,BP_FINISHED
|
||||
jne bp_crowd_next
|
||||
bp_crowd_draw:
|
||||
invoke ConfigureCharacter3D,OFFSET bwSmallActor3D,ebx,phase,animationClock3D,0,0
|
||||
mov eax,bpCentre3D
|
||||
mov ecx,FP_1*16/10
|
||||
test esi,esi
|
||||
jnz @F
|
||||
mov ecx,FP_1*9/10
|
||||
@@:
|
||||
cmp esi,1
|
||||
jne @F
|
||||
neg ecx
|
||||
@@:
|
||||
add eax,ecx
|
||||
mov bwSmallActor3D.posX,eax
|
||||
mov eax,FP_1*218/10
|
||||
test esi,esi
|
||||
jnz @F
|
||||
mov eax,23*FP_1
|
||||
@@:
|
||||
mov bwSmallActor3D.posY,eax
|
||||
invoke DrawCityObject3D,OFFSET bwSmallActor3D,0
|
||||
bp_crowd_next:
|
||||
inc esi
|
||||
cmp esi,3
|
||||
jb bp_crowd_person
|
||||
ret
|
||||
RenderBowlingReactions3D ENDP
|
||||
482
src_graphics/bowling_physics.inc
Normal file
482
src_graphics/bowling_physics.inc
Normal file
|
|
@ -0,0 +1,482 @@
|
|||
; Symmetric normal impulses and overlap correction follow the existing billiards
|
||||
; solver. Four 4-ms substeps prevent tunnelling; angular rocking is separate.
|
||||
include src_graphics\bowling_deck.inc
|
||||
|
||||
NormalizeBowlingPinAxis3D PROC uses esi pin:DWORD
|
||||
local axisLength:REAL8
|
||||
mov esi,pin
|
||||
mov eax,bpPinAxisX3D[esi*4]
|
||||
or eax,bpPinAxisY3D[esi*4]
|
||||
jnz bp_axis_length
|
||||
mov bpPinAxisY3D[esi*4],-FP_1
|
||||
ret
|
||||
bp_axis_length:
|
||||
fild bpPinAxisX3D[esi*4]
|
||||
fmul st,st
|
||||
fild bpPinAxisY3D[esi*4]
|
||||
fmul st,st
|
||||
faddp st(1),st
|
||||
fsqrt
|
||||
fstp axisLength
|
||||
fild bpPinAxisX3D[esi*4]
|
||||
fdiv axisLength
|
||||
fmul roofFloatFP3D
|
||||
fistp bpPinAxisX3D[esi*4]
|
||||
fild bpPinAxisY3D[esi*4]
|
||||
fdiv axisLength
|
||||
fmul roofFloatFP3D
|
||||
fistp bpPinAxisY3D[esi*4]
|
||||
ret
|
||||
NormalizeBowlingPinAxis3D ENDP
|
||||
|
||||
BowlingPlayHit3D PROC pin:DWORD,vx:DWORD,vy:DWORD
|
||||
invoke BowlingPlayKick3D,pin,vx,vy
|
||||
ret
|
||||
BowlingPlayHit3D ENDP
|
||||
|
||||
BowlingPlayKick3D PROC uses ebx esi edi pin:DWORD,vx:DWORD,vy:DWORD
|
||||
local energy:DWORD
|
||||
mov esi,pin
|
||||
cmp esi,10
|
||||
jae bp_kick_done
|
||||
; Preserve fractional impulses: signed pre-rounding can collapse the basis.
|
||||
fild vx
|
||||
fmul st,st
|
||||
fild vy
|
||||
fmul st,st
|
||||
faddp st(1),st
|
||||
fsqrt
|
||||
fistp energy
|
||||
mov eax,energy
|
||||
cmp eax,128
|
||||
jb bp_kick_done
|
||||
cmp eax,bpImpactEnergy3D
|
||||
jbe @F
|
||||
mov bpImpactEnergy3D,eax
|
||||
@@:
|
||||
cmp eax,128
|
||||
jb bp_kick_done
|
||||
mov edx,bpPhysicsTicks3D
|
||||
mov bpPinContactTick3D[esi*4],edx
|
||||
mov ecx,2
|
||||
cdq
|
||||
idiv ecx
|
||||
cmp eax,2000
|
||||
jbe @F
|
||||
mov eax,2000
|
||||
@@:
|
||||
add bpPinTiltV3D[esi*4],eax
|
||||
mov eax,bpPinTiltV3D[esi*4]
|
||||
cmp eax,2400
|
||||
jle @F
|
||||
mov bpPinTiltV3D[esi*4],2400
|
||||
@@:
|
||||
cmp bpPinTilt3D[esi*4],64*256
|
||||
jae bp_kick_done
|
||||
mov eax,vx
|
||||
mov ecx,FP_1
|
||||
imul ecx
|
||||
idiv energy
|
||||
mov bpPinAxisX3D[esi*4],eax
|
||||
mov eax,vy
|
||||
imul ecx
|
||||
idiv energy
|
||||
mov bpPinAxisY3D[esi*4],eax
|
||||
invoke NormalizeBowlingPinAxis3D,esi
|
||||
mov eax,vx
|
||||
sub eax,vy
|
||||
sar eax,10
|
||||
mov bpPinSpin3D[esi*4],eax
|
||||
bp_kick_done:
|
||||
ret
|
||||
BowlingPlayKick3D ENDP
|
||||
|
||||
BowlingPlayContact3D PROC uses ebx esi edi a:DWORD,b:DWORD
|
||||
local deltaX:DWORD,deltaY:DWORD,radius:DWORD,distance:DWORD,nx:DWORD,ny:DWORD
|
||||
local impulse:DWORD,changeA:DWORD,changeB:DWORD,ix:DWORD,iy:DWORD,massSum:DWORD
|
||||
local contactLength:REAL8
|
||||
mov esi,a
|
||||
mov edi,b
|
||||
mov eax,bpRadius3D[esi*4]
|
||||
add eax,bpRadius3D[edi*4]
|
||||
mov radius,eax
|
||||
shl eax,8
|
||||
mov ebx,eax
|
||||
mov eax,bpPinX3D[edi*4]
|
||||
sub eax,bpPinX3D[esi*4]
|
||||
cmp eax,ebx
|
||||
jg bp_contact_done
|
||||
neg ebx
|
||||
cmp eax,ebx
|
||||
jl bp_contact_done
|
||||
mov deltaX,eax
|
||||
mov eax,bpPinY3D[edi*4]
|
||||
sub eax,bpPinY3D[esi*4]
|
||||
cmp eax,ebx
|
||||
jl bp_contact_done
|
||||
neg ebx
|
||||
cmp eax,ebx
|
||||
jg bp_contact_done
|
||||
mov deltaY,eax
|
||||
sar eax,8
|
||||
imul eax,eax
|
||||
mov ebx,deltaX
|
||||
sar ebx,8
|
||||
imul ebx,ebx
|
||||
add eax,ebx
|
||||
mov ebx,radius
|
||||
imul ebx,ebx
|
||||
cmp eax,ebx
|
||||
jae bp_contact_done
|
||||
fild deltaX
|
||||
fmul st,st
|
||||
fild deltaY
|
||||
fmul st,st
|
||||
faddp st(1),st
|
||||
fsqrt
|
||||
fst contactLength
|
||||
fistp distance
|
||||
cmp distance,0
|
||||
jne @F
|
||||
mov deltaX,1
|
||||
mov deltaY,0
|
||||
mov distance,1
|
||||
fild distance
|
||||
fstp contactLength
|
||||
@@:
|
||||
mov eax,radius
|
||||
shl eax,8
|
||||
cmp distance,eax
|
||||
jae bp_contact_done
|
||||
fild deltaX
|
||||
fdiv contactLength
|
||||
fmul roofFloatFP3D
|
||||
fistp nx
|
||||
fild deltaY
|
||||
fdiv contactLength
|
||||
fmul roofFloatFP3D
|
||||
fistp ny
|
||||
mov eax,bpInvMass3D[esi*4]
|
||||
add eax,bpInvMass3D[edi*4]
|
||||
mov massSum,eax
|
||||
mov eax,bpPinVX3D[edi*4]
|
||||
sub eax,bpPinVX3D[esi*4]
|
||||
imul nx
|
||||
shrd eax,edx,16
|
||||
mov ebx,eax
|
||||
mov eax,bpPinVY3D[edi*4]
|
||||
sub eax,bpPinVY3D[esi*4]
|
||||
imul ny
|
||||
shrd eax,edx,16
|
||||
add eax,ebx
|
||||
test eax,eax
|
||||
jns bp_contact_separate
|
||||
neg eax
|
||||
mov ecx,FP_1*3/2
|
||||
imul ecx
|
||||
idiv massSum
|
||||
mov impulse,eax
|
||||
imul bpInvMass3D[esi*4]
|
||||
shrd eax,edx,16
|
||||
mov changeA,eax
|
||||
mov eax,impulse
|
||||
imul bpInvMass3D[edi*4]
|
||||
shrd eax,edx,16
|
||||
mov changeB,eax
|
||||
mov eax,changeA
|
||||
imul nx
|
||||
shrd eax,edx,16
|
||||
sub bpPinVX3D[esi*4],eax
|
||||
neg eax
|
||||
mov ix,eax
|
||||
mov eax,changeA
|
||||
imul ny
|
||||
shrd eax,edx,16
|
||||
sub bpPinVY3D[esi*4],eax
|
||||
neg eax
|
||||
invoke BowlingPlayKick3D,esi,ix,eax
|
||||
mov eax,changeB
|
||||
imul nx
|
||||
shrd eax,edx,16
|
||||
add bpPinVX3D[edi*4],eax
|
||||
mov ix,eax
|
||||
mov eax,changeB
|
||||
imul ny
|
||||
shrd eax,edx,16
|
||||
add bpPinVY3D[edi*4],eax
|
||||
invoke BowlingPlayKick3D,edi,ix,eax
|
||||
bp_contact_separate:
|
||||
mov eax,radius
|
||||
shl eax,8
|
||||
sub eax,distance
|
||||
jle bp_contact_done
|
||||
imul eax,3
|
||||
sar eax,2
|
||||
mov impulse,eax
|
||||
imul bpInvMass3D[esi*4]
|
||||
idiv massSum
|
||||
mov changeA,eax
|
||||
mov eax,impulse
|
||||
imul bpInvMass3D[edi*4]
|
||||
idiv massSum
|
||||
mov changeB,eax
|
||||
mov eax,changeA
|
||||
imul nx
|
||||
shrd eax,edx,16
|
||||
sub bpPinX3D[esi*4],eax
|
||||
mov eax,changeA
|
||||
imul ny
|
||||
shrd eax,edx,16
|
||||
sub bpPinY3D[esi*4],eax
|
||||
mov eax,changeB
|
||||
imul nx
|
||||
shrd eax,edx,16
|
||||
add bpPinX3D[edi*4],eax
|
||||
mov eax,changeB
|
||||
imul ny
|
||||
shrd eax,edx,16
|
||||
add bpPinY3D[edi*4],eax
|
||||
bp_contact_done:
|
||||
ret
|
||||
BowlingPlayContact3D ENDP
|
||||
|
||||
BowlingPlayStep3D PROC uses ebx esi edi
|
||||
local substep:DWORD,rack:DWORD
|
||||
mov esi,bpLane3D
|
||||
mov eax,bwRack3D[esi*4]
|
||||
or eax,1024
|
||||
mov rack,eax
|
||||
mov eax,bpBallX3D
|
||||
mov bpPinX3D[40],eax
|
||||
mov eax,bpBallY3D
|
||||
mov bpPinY3D[40],eax
|
||||
mov eax,bpBallVX3D
|
||||
mov bpPinVX3D[40],eax
|
||||
mov eax,bpBallVY3D
|
||||
mov bpPinVY3D[40],eax
|
||||
mov substep,0
|
||||
bp_physics_substep:
|
||||
xor esi,esi
|
||||
bp_physics_integrate:
|
||||
bt rack,esi
|
||||
jnc bp_physics_integrate_next
|
||||
mov eax,bpPinVX3D[esi*4]
|
||||
sar eax,2
|
||||
add bpPinX3D[esi*4],eax
|
||||
mov eax,bpPinVY3D[esi*4]
|
||||
sar eax,2
|
||||
add bpPinY3D[esi*4],eax
|
||||
cmp esi,10
|
||||
jne bp_physics_integrate_next
|
||||
cmp bpPinY3D[40],FP_1*28/10
|
||||
jge @F
|
||||
mov bpPinVX3D[40],0
|
||||
mov bpPinVY3D[40],0
|
||||
@@:
|
||||
mov eax,bpPinX3D[40]
|
||||
cdq
|
||||
xor eax,edx
|
||||
sub eax,edx
|
||||
cmp eax,FP_1*74/100
|
||||
jbe bp_physics_integrate_next
|
||||
mov bpGutter3D,1
|
||||
mov eax,FP_1*87/100
|
||||
cmp bpPinX3D[40],0
|
||||
jge @F
|
||||
neg eax
|
||||
@@:
|
||||
mov bpPinX3D[40],eax
|
||||
mov bpPinVX3D[40],0
|
||||
bp_physics_integrate_next:
|
||||
inc esi
|
||||
cmp esi,BP_BODY_COUNT
|
||||
jb bp_physics_integrate
|
||||
xor esi,esi
|
||||
bp_physics_pair_a:
|
||||
bt rack,esi
|
||||
jnc bp_physics_pair_next_a
|
||||
lea edi,[esi+1]
|
||||
bp_physics_pair_b:
|
||||
bt rack,edi
|
||||
jnc bp_physics_pair_next_b
|
||||
cmp edi,10
|
||||
jne @F
|
||||
cmp bpGutter3D,0
|
||||
jne bp_physics_pair_next_b
|
||||
@@:
|
||||
invoke BowlingPlayContact3D,esi,edi
|
||||
bp_physics_pair_next_b:
|
||||
inc edi
|
||||
cmp edi,BP_BODY_COUNT
|
||||
jb bp_physics_pair_b
|
||||
bp_physics_pair_next_a:
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_physics_pair_a
|
||||
xor esi,esi
|
||||
bp_physics_substep_limits:
|
||||
bt rack,esi
|
||||
jnc @F
|
||||
invoke BowlingPlayTether3D,esi
|
||||
invoke BowlingPlayDeckBounds3D,esi
|
||||
@@:
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_physics_substep_limits
|
||||
inc substep
|
||||
cmp substep,4
|
||||
jb bp_physics_substep
|
||||
xor esi,esi
|
||||
bp_physics_pin:
|
||||
bt rack,esi
|
||||
jnc bp_physics_pin_next
|
||||
mov ecx,246
|
||||
mov eax,bpPhysicsTicks3D
|
||||
sub eax,bpPinContactTick3D[esi*4]
|
||||
cmp eax,10
|
||||
jb @F
|
||||
bt bpHitMask3D,esi
|
||||
jnc @F
|
||||
mov ecx,224
|
||||
@@:
|
||||
mov eax,bpPinVX3D[esi*4]
|
||||
imul eax,ecx
|
||||
sar eax,8
|
||||
mov bpPinVX3D[esi*4],eax
|
||||
mov eax,bpPinVY3D[esi*4]
|
||||
imul eax,ecx
|
||||
sar eax,8
|
||||
mov bpPinVY3D[esi*4],eax
|
||||
mov eax,bpPinTilt3D[esi*4]
|
||||
cmp eax,24*256
|
||||
jae bp_physics_topple
|
||||
mov edx,eax
|
||||
sar edx,6
|
||||
sub bpPinTiltV3D[esi*4],edx
|
||||
jmp bp_physics_tilt
|
||||
bp_physics_topple:
|
||||
add bpPinTiltV3D[esi*4],160
|
||||
bp_physics_tilt:
|
||||
mov edx,bpPinTiltV3D[esi*4]
|
||||
imul edx,245
|
||||
sar edx,8
|
||||
mov bpPinTiltV3D[esi*4],edx
|
||||
add eax,edx
|
||||
test eax,eax
|
||||
jns @F
|
||||
xor eax,eax
|
||||
mov bpPinTiltV3D[esi*4],0
|
||||
@@:
|
||||
cmp eax,128*256
|
||||
jbe @F
|
||||
mov eax,128*256
|
||||
mov edx,bpPinTiltV3D[esi*4]
|
||||
neg edx
|
||||
sar edx,2
|
||||
cmp edx,-80
|
||||
jl bp_physics_bounce
|
||||
xor edx,edx
|
||||
bp_physics_bounce:
|
||||
mov bpPinTiltV3D[esi*4],edx
|
||||
@@:
|
||||
mov bpPinTilt3D[esi*4],eax
|
||||
cmp eax,64*256
|
||||
jb bp_physics_pin_next
|
||||
bts bpHitMask3D,esi
|
||||
mov bpRadius3D[esi*4],48
|
||||
; Slow rolling yaw, independent of the fall's vertical angle.
|
||||
mov ecx,bpPinSpin3D[esi*4]
|
||||
and ecx,511
|
||||
mov eax,bpPinAxisX3D[esi*4]
|
||||
imul tableCos[ecx*4]
|
||||
shrd eax,edx,16
|
||||
mov ebx,eax
|
||||
mov eax,bpPinAxisY3D[esi*4]
|
||||
imul tableSin[ecx*4]
|
||||
shrd eax,edx,16
|
||||
sub ebx,eax
|
||||
mov eax,bpPinAxisX3D[esi*4]
|
||||
imul tableSin[ecx*4]
|
||||
shrd eax,edx,16
|
||||
mov edi,eax
|
||||
mov eax,bpPinAxisY3D[esi*4]
|
||||
imul tableCos[ecx*4]
|
||||
shrd eax,edx,16
|
||||
add eax,edi
|
||||
mov bpPinAxisY3D[esi*4],eax
|
||||
mov bpPinAxisX3D[esi*4],ebx
|
||||
invoke NormalizeBowlingPinAxis3D,esi
|
||||
mov eax,bpPinSpin3D[esi*4]
|
||||
imul eax,230
|
||||
test eax,eax
|
||||
jns @F
|
||||
add eax,255
|
||||
@@:
|
||||
sar eax,8
|
||||
mov bpPinSpin3D[esi*4],eax
|
||||
bp_physics_pin_next:
|
||||
bt rack,esi
|
||||
jnc @F
|
||||
invoke BowlingPlayTether3D,esi
|
||||
invoke BowlingPlayDeckBounds3D,esi
|
||||
@@:
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_physics_pin
|
||||
mov eax,bpPinX3D[40]
|
||||
mov bpBallX3D,eax
|
||||
mov eax,bpPinY3D[40]
|
||||
mov bpBallY3D,eax
|
||||
mov eax,bpPinVX3D[40]
|
||||
mov bpBallVX3D,eax
|
||||
mov eax,bpPinVY3D[40]
|
||||
mov bpBallVY3D,eax
|
||||
inc bpPhysicsTicks3D
|
||||
cmp bpBallY3D,3*FP_1
|
||||
jge @F
|
||||
inc bpEndTicks3D
|
||||
@@:
|
||||
ret
|
||||
BowlingPlayStep3D ENDP
|
||||
|
||||
BowlingPlayReady3D PROC uses esi
|
||||
cmp bpPhysicsTicks3D,900
|
||||
jae bp_physics_ready
|
||||
cmp bpEndTicks3D,100
|
||||
jb bp_physics_not_ready
|
||||
xor esi,esi
|
||||
bp_physics_quiet:
|
||||
mov eax,bpPinVX3D[esi*4]
|
||||
cdq
|
||||
xor eax,edx
|
||||
sub eax,edx
|
||||
cmp eax,96
|
||||
ja bp_physics_not_ready
|
||||
mov eax,bpPinTilt3D[esi*4]
|
||||
cmp eax,128*256
|
||||
jae @F
|
||||
cmp eax,24*256
|
||||
jae bp_physics_not_ready
|
||||
mov eax,bpPinTiltV3D[esi*4]
|
||||
cdq
|
||||
xor eax,edx
|
||||
sub eax,edx
|
||||
cmp eax,32
|
||||
ja bp_physics_not_ready
|
||||
@@:
|
||||
mov eax,bpPinVY3D[esi*4]
|
||||
cdq
|
||||
xor eax,edx
|
||||
sub eax,edx
|
||||
cmp eax,96
|
||||
ja bp_physics_not_ready
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_physics_quiet
|
||||
bp_physics_ready:
|
||||
mov eax,1
|
||||
ret
|
||||
bp_physics_not_ready:
|
||||
xor eax,eax
|
||||
ret
|
||||
BowlingPlayReady3D ENDP
|
||||
296
src_graphics/bowling_pin_shape.inc
Normal file
296
src_graphics/bowling_pin_shape.inc
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
; The existing ray/ellipsoid renderer, evaluated in a pin-local orthonormal basis.
|
||||
DrawBowlingEllipsoid3D PROC uses ebx esi edi centreX:DWORD,centreY:DWORD,centreZ:DWORD,radiusX:DWORD,radiusY:DWORD,radiusZ:DWORD,material:DWORD
|
||||
local leftPx:DWORD,rightPx:DWORD,topPx:DWORD,bottomPx:DWORD,column:DWORD,row:DWORD
|
||||
local centrePx:DWORD,centreDepth:DWORD,pixelDepth:DWORD,temp:DWORD,texU:DWORD,texV:DWORD
|
||||
local texture:DWORD,texWidth:DWORD,texHeight:DWORD,shade:DWORD,color:DWORD
|
||||
local worldOX:DWORD,worldOY:DWORD,worldOZ:DWORD,worldRZ:REAL4,boundRadius:DWORD
|
||||
local ox:REAL4,oy:REAL4,oz:REAL4,rayX:REAL4,rayY:REAL4,rayZ:REAL4
|
||||
local quadraticC:REAL4,quadraticA:REAL4,quadraticB:REAL4,discriminant:REAL4,hitTime:REAL4
|
||||
invoke ResolveCitySurface3D,material
|
||||
test eax,eax
|
||||
jz bp_shape_done
|
||||
mov texture,eax
|
||||
mov texWidth,ecx
|
||||
mov texHeight,edx
|
||||
invoke ProjectCityPoint3D,centreX,centreY
|
||||
cmp edx,FP_1/8
|
||||
jle bp_shape_done
|
||||
mov centrePx,eax
|
||||
mov centreDepth,edx
|
||||
mov eax,radiusX
|
||||
cmp eax,radiusZ
|
||||
jge @F
|
||||
mov eax,radiusZ
|
||||
@@:
|
||||
mov boundRadius,eax
|
||||
shl eax,1
|
||||
imul eax,SCREEN_H
|
||||
cdq
|
||||
idiv centreDepth
|
||||
mov ecx,centrePx
|
||||
sub ecx,eax
|
||||
mov leftPx,ecx
|
||||
add eax,centrePx
|
||||
mov rightPx,eax
|
||||
mov eax,viewEye3D
|
||||
sub eax,centreZ
|
||||
sub eax,boundRadius
|
||||
imul eax,SCREEN_H
|
||||
cdq
|
||||
idiv centreDepth
|
||||
add eax,viewHorizon3D
|
||||
sub eax,4
|
||||
mov topPx,eax
|
||||
mov eax,viewEye3D
|
||||
sub eax,centreZ
|
||||
add eax,boundRadius
|
||||
imul eax,SCREEN_H
|
||||
cdq
|
||||
idiv centreDepth
|
||||
add eax,viewHorizon3D
|
||||
add eax,4
|
||||
mov bottomPx,eax
|
||||
cmp leftPx,0
|
||||
jge @F
|
||||
mov leftPx,0
|
||||
@@:
|
||||
cmp rightPx,SCREEN_W-1
|
||||
jle @F
|
||||
mov rightPx,SCREEN_W-1
|
||||
@@:
|
||||
cmp topPx,0
|
||||
jge @F
|
||||
mov topPx,0
|
||||
@@:
|
||||
cmp bottomPx,SCREEN_H-1
|
||||
jle @F
|
||||
mov bottomPx,SCREEN_H-1
|
||||
@@:
|
||||
mov eax,leftPx
|
||||
cmp eax,rightPx
|
||||
jge bp_shape_done
|
||||
mov eax,topPx
|
||||
cmp eax,bottomPx
|
||||
jge bp_shape_done
|
||||
mov eax,playerX
|
||||
sub eax,centreX
|
||||
mov worldOX,eax
|
||||
mov eax,playerY
|
||||
sub eax,centreY
|
||||
mov worldOY,eax
|
||||
mov eax,viewEye3D
|
||||
sub eax,centreZ
|
||||
mov worldOZ,eax
|
||||
fild worldOX
|
||||
fimul bpRenderUX3D
|
||||
fild worldOY
|
||||
fimul bpRenderUY3D
|
||||
faddp st(1),st
|
||||
fdiv roofFloatFP3D
|
||||
fidiv radiusX
|
||||
fstp ox
|
||||
fild worldOX
|
||||
fimul bpRenderVX3D
|
||||
fild worldOY
|
||||
fimul bpRenderVY3D
|
||||
faddp st(1),st
|
||||
fild worldOZ
|
||||
fimul bpRenderVZ3D
|
||||
faddp st(1),st
|
||||
fdiv roofFloatFP3D
|
||||
fidiv radiusY
|
||||
fstp oy
|
||||
fild worldOX
|
||||
fimul bpRenderNX3D
|
||||
fild worldOY
|
||||
fimul bpRenderNY3D
|
||||
faddp st(1),st
|
||||
fild worldOZ
|
||||
fimul bpRenderNZ3D
|
||||
faddp st(1),st
|
||||
fdiv roofFloatFP3D
|
||||
fidiv radiusZ
|
||||
fstp oz
|
||||
fld ox
|
||||
fmul st,st
|
||||
fld oy
|
||||
fmul st,st
|
||||
faddp st(1),st
|
||||
fld oz
|
||||
fmul st,st
|
||||
faddp st(1),st
|
||||
fld1
|
||||
fsubp st(1),st
|
||||
fstp quadraticC
|
||||
mov eax,topPx
|
||||
mov row,eax
|
||||
bp_shape_row:
|
||||
mov eax,viewHorizon3D
|
||||
sub eax,row
|
||||
mov temp,eax
|
||||
fild temp
|
||||
fmul roofFloatFP3D
|
||||
fdiv roofFloat4803D
|
||||
fstp worldRZ
|
||||
mov eax,row
|
||||
imul eax,SCREEN_W*4
|
||||
mov ebx,leftPx
|
||||
lea edi,[eax+ebx*4]
|
||||
mov column,ebx
|
||||
bp_shape_pixel:
|
||||
mov ebx,column
|
||||
fild cityRayX3D[ebx*4]
|
||||
fimul bpRenderUX3D
|
||||
fild cityRayY3D[ebx*4]
|
||||
fimul bpRenderUY3D
|
||||
faddp st(1),st
|
||||
fdiv roofFloatFP3D
|
||||
fidiv radiusX
|
||||
fstp rayX
|
||||
fild cityRayX3D[ebx*4]
|
||||
fimul bpRenderVX3D
|
||||
fild cityRayY3D[ebx*4]
|
||||
fimul bpRenderVY3D
|
||||
faddp st(1),st
|
||||
fld worldRZ
|
||||
fimul bpRenderVZ3D
|
||||
faddp st(1),st
|
||||
fdiv roofFloatFP3D
|
||||
fidiv radiusY
|
||||
fstp rayY
|
||||
fild cityRayX3D[ebx*4]
|
||||
fimul bpRenderNX3D
|
||||
fild cityRayY3D[ebx*4]
|
||||
fimul bpRenderNY3D
|
||||
faddp st(1),st
|
||||
fld worldRZ
|
||||
fimul bpRenderNZ3D
|
||||
faddp st(1),st
|
||||
fdiv roofFloatFP3D
|
||||
fidiv radiusZ
|
||||
fstp rayZ
|
||||
fld rayX
|
||||
fmul st,st
|
||||
fld rayY
|
||||
fmul st,st
|
||||
faddp st(1),st
|
||||
fld rayZ
|
||||
fmul st,st
|
||||
faddp st(1),st
|
||||
fstp quadraticA
|
||||
fld rayX
|
||||
fmul ox
|
||||
fld rayY
|
||||
fmul oy
|
||||
faddp st(1),st
|
||||
fld rayZ
|
||||
fmul oz
|
||||
faddp st(1),st
|
||||
fstp quadraticB
|
||||
fld quadraticB
|
||||
fmul st,st
|
||||
fld quadraticA
|
||||
fmul quadraticC
|
||||
fsubp st(1),st
|
||||
fst discriminant
|
||||
ftst
|
||||
fnstsw ax
|
||||
sahf
|
||||
fstp st(0)
|
||||
jb bp_shape_next
|
||||
fld discriminant
|
||||
fsqrt
|
||||
fadd quadraticB
|
||||
fchs
|
||||
fdiv quadraticA
|
||||
fst hitTime
|
||||
fmul roofFloatFP3D
|
||||
fistp pixelDepth
|
||||
mov eax,pixelDepth
|
||||
cmp eax,4096
|
||||
jle bp_shape_next
|
||||
cmp eax,cityDepthBuffer3D[edi]
|
||||
jae bp_shape_next
|
||||
fld hitTime
|
||||
fmul rayX
|
||||
fadd ox
|
||||
fld1
|
||||
faddp st(1),st
|
||||
fmul roofFloatHalfTex3D
|
||||
fistp texU
|
||||
fld hitTime
|
||||
fmul rayZ
|
||||
fadd oz
|
||||
fchs
|
||||
fld1
|
||||
faddp st(1),st
|
||||
fmul roofFloatHalfTex3D
|
||||
fistp texV
|
||||
fld hitTime
|
||||
fmul rayZ
|
||||
fadd oz
|
||||
fmul roofFloatShade3D
|
||||
fadd roofFloatAmbient3D
|
||||
fistp shade
|
||||
mov eax,texV
|
||||
and eax,255
|
||||
mov ecx,texHeight
|
||||
imul eax,ecx
|
||||
shr eax,8
|
||||
imul eax,texWidth
|
||||
mov edx,texU
|
||||
and edx,255
|
||||
imul edx,texWidth
|
||||
shr edx,8
|
||||
add eax,edx
|
||||
mov esi,texture
|
||||
mov eax,[esi+eax*4]
|
||||
mov color,eax
|
||||
movzx eax,al
|
||||
imul eax,shade
|
||||
shr eax,8
|
||||
mov ebx,eax
|
||||
mov eax,color
|
||||
shr eax,8
|
||||
and eax,255
|
||||
imul eax,shade
|
||||
and eax,0FF00h
|
||||
or ebx,eax
|
||||
mov eax,color
|
||||
shr eax,16
|
||||
and eax,255
|
||||
imul eax,shade
|
||||
and eax,0FF00h
|
||||
shl eax,8
|
||||
or eax,ebx
|
||||
cmp roofCityPass3D,0
|
||||
je bp_shape_color_ready
|
||||
invoke ShadeRoofCityPixel3D,eax,pixelDepth,256,material
|
||||
mov ecx,edi
|
||||
shr ecx,2
|
||||
mov edx,roofPixelGlow3D
|
||||
mov roofGlowMask3D[ecx],dl
|
||||
bp_shape_color_ready:
|
||||
mov screenBuffer[edi],eax
|
||||
cmp hallLevel3D,HALL_ROOF
|
||||
jne @F
|
||||
mov ecx,edi
|
||||
shr ecx,2
|
||||
mov edx,roofCityPass3D
|
||||
mov roofCityMask3D[ecx],dl
|
||||
@@:
|
||||
mov eax,pixelDepth
|
||||
mov cityDepthBuffer3D[edi],eax
|
||||
bp_shape_next:
|
||||
add edi,4
|
||||
inc column
|
||||
mov eax,column
|
||||
cmp eax,rightPx
|
||||
jbe bp_shape_pixel
|
||||
inc row
|
||||
mov eax,row
|
||||
cmp eax,bottomPx
|
||||
jbe bp_shape_row
|
||||
bp_shape_done:
|
||||
ret
|
||||
DrawBowlingEllipsoid3D ENDP
|
||||
204
src_graphics/bowling_pinsetter.inc
Normal file
204
src_graphics/bowling_pinsetter.inc
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
InitBowlingSetterSurface3D PROC uses ebx esi edi
|
||||
lea edi,bpSetterSurface3D
|
||||
xor esi,esi
|
||||
bp_setter_surface_row:
|
||||
xor ebx,ebx
|
||||
bp_setter_surface_pixel:
|
||||
mov eax,esi
|
||||
and eax,15
|
||||
mov edx,002C363Dh
|
||||
test eax,eax
|
||||
jnz @F
|
||||
mov edx,00141B20h
|
||||
@@:
|
||||
cmp eax,1
|
||||
jne @F
|
||||
mov edx,00414C54h
|
||||
@@:
|
||||
mov eax,ebx
|
||||
and eax,3
|
||||
imul eax,00010101h
|
||||
add eax,edx
|
||||
or eax,0FF000000h
|
||||
stosd
|
||||
inc ebx
|
||||
cmp ebx,64
|
||||
jb bp_setter_surface_pixel
|
||||
inc esi
|
||||
cmp esi,64
|
||||
jb bp_setter_surface_row
|
||||
ret
|
||||
InitBowlingSetterSurface3D ENDP
|
||||
|
||||
; Smooth motor travel, clamped at both mechanical stops.
|
||||
BowlingPinsetterEase3D PROC ticks:DWORD,duration:DWORD
|
||||
local phase:DWORD
|
||||
mov eax,ticks
|
||||
test eax,eax
|
||||
jle bp_ease_zero
|
||||
cmp eax,duration
|
||||
jae bp_ease_full
|
||||
imul eax,FP_1
|
||||
cdq
|
||||
idiv duration
|
||||
mov phase,eax
|
||||
imul eax
|
||||
shrd eax,edx,16
|
||||
mov ecx,3*FP_1
|
||||
sub ecx,phase
|
||||
sub ecx,phase
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
ret
|
||||
bp_ease_zero:
|
||||
xor eax,eax
|
||||
ret
|
||||
bp_ease_full:
|
||||
mov eax,FP_1
|
||||
ret
|
||||
BowlingPinsetterEase3D ENDP
|
||||
|
||||
; Strings stay invisible; the guard closes before the hoist starts.
|
||||
BowlingPinsetterGate3D PROC
|
||||
cmp bpState3D,BP_RESET
|
||||
jne bp_gate_open
|
||||
mov eax,bpTime3D
|
||||
cmp eax,4400
|
||||
jae bp_gate_open
|
||||
cmp eax,400
|
||||
jb bp_gate_closing
|
||||
sub eax,4000
|
||||
invoke BowlingPinsetterEase3D,eax,400
|
||||
mov ecx,FP_1*87/100
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
add eax,FP_1*13/100
|
||||
ret
|
||||
bp_gate_closing:
|
||||
invoke BowlingPinsetterEase3D,eax,400
|
||||
mov ecx,FP_1*87/100
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
neg eax
|
||||
add eax,FP_1
|
||||
ret
|
||||
bp_gate_open:
|
||||
mov eax,FP_1
|
||||
ret
|
||||
BowlingPinsetterGate3D ENDP
|
||||
|
||||
; All physical pins remain present aloft, including the knocked-down ones.
|
||||
BowlingPinsetterPose3D PROC uses ebx esi edi pin:DWORD
|
||||
local progress:DWORD
|
||||
mov esi,pin
|
||||
mov edi,bpLane3D
|
||||
mov ebx,bwRack3D[edi*4]
|
||||
mov eax,bpPinX3D[esi*4]
|
||||
mov bpVisualPinX3D,eax
|
||||
mov eax,bpPinY3D[esi*4]
|
||||
mov bpVisualPinY3D,eax
|
||||
mov eax,bpPinTilt3D[esi*4]
|
||||
mov bpVisualPinTilt3D,eax
|
||||
mov bpVisualPinLift3D,0
|
||||
cmp bpState3D,BP_RESET
|
||||
jne bp_setter_mask
|
||||
cmp bwNewRack3D[edi*4],0
|
||||
je @F
|
||||
mov ebx,1023
|
||||
@@:
|
||||
mov eax,bpTime3D
|
||||
cmp eax,2200
|
||||
jae bp_setter_lower
|
||||
sub eax,400
|
||||
invoke BowlingPinsetterEase3D,eax,1300
|
||||
mov progress,eax
|
||||
mov ecx,FP_1*11/10
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
mov bpVisualPinLift3D,eax
|
||||
mov eax,bwPinX3D[esi*4]
|
||||
sub eax,bpVisualPinX3D
|
||||
imul progress
|
||||
shrd eax,edx,16
|
||||
add bpVisualPinX3D,eax
|
||||
mov eax,bwPinY3D[esi*4]
|
||||
sub eax,bpVisualPinY3D
|
||||
imul progress
|
||||
shrd eax,edx,16
|
||||
add bpVisualPinY3D,eax
|
||||
mov eax,FP_1
|
||||
sub eax,progress
|
||||
imul bpVisualPinTilt3D
|
||||
shrd eax,edx,16
|
||||
mov bpVisualPinTilt3D,eax
|
||||
jmp bp_setter_mask
|
||||
bp_setter_lower:
|
||||
cmp bwNewRack3D[edi*4],0
|
||||
jne bp_setter_new_pose
|
||||
bt bpHitMask3D,esi
|
||||
jnc bp_setter_new_pose
|
||||
mov bpVisualPinLift3D,FP_1*11/10
|
||||
mov bpVisualPinTilt3D,0
|
||||
mov eax,bwPinX3D[esi*4]
|
||||
mov bpVisualPinX3D,eax
|
||||
mov eax,bwPinY3D[esi*4]
|
||||
mov bpVisualPinY3D,eax
|
||||
jmp bp_setter_mask
|
||||
bp_setter_new_pose:
|
||||
mov eax,bwPinX3D[esi*4]
|
||||
mov bpVisualPinX3D,eax
|
||||
mov eax,bwPinY3D[esi*4]
|
||||
mov bpVisualPinY3D,eax
|
||||
mov bpVisualPinTilt3D,0
|
||||
mov eax,bpTime3D
|
||||
sub eax,2200
|
||||
invoke BowlingPinsetterEase3D,eax,1500
|
||||
neg eax
|
||||
add eax,FP_1
|
||||
mov ecx,FP_1*11/10
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
mov bpVisualPinLift3D,eax
|
||||
bp_setter_mask:
|
||||
bt ebx,esi
|
||||
setc al
|
||||
movzx eax,al
|
||||
ret
|
||||
BowlingPinsetterPose3D ENDP
|
||||
|
||||
RenderBowlingPinsetter3D PROC uses ebx esi
|
||||
local lo:DWORD,hi:DWORD,light:DWORD,gate:DWORD,top:DWORD
|
||||
mov eax,bpCentre3D
|
||||
sub eax,FP_1*82/100
|
||||
mov lo,eax
|
||||
add eax,FP_1*164/100
|
||||
mov hi,eax
|
||||
invoke DrawRoofSolid3D,lo,hi,FP_1*28/10,FP_1*52/10,FP_1,FP_1*16/10,254
|
||||
mov eax,lo
|
||||
add eax,FP_1*6/100
|
||||
invoke DrawRoofSolid3D,lo,eax,FP_1*52/10,FP_1*53/10,0,FP_1*16/10,238
|
||||
mov eax,hi
|
||||
sub eax,FP_1*6/100
|
||||
invoke DrawRoofSolid3D,eax,hi,FP_1*52/10,FP_1*53/10,0,FP_1*16/10,238
|
||||
call BowlingPinsetterGate3D
|
||||
mov gate,eax
|
||||
add eax,FP_1*9/10
|
||||
mov top,eax
|
||||
invoke DrawRoofSolid3D,lo,hi,FP_1*53/10,FP_1*534/100,gate,top,254
|
||||
mov eax,gate
|
||||
add eax,FP_1*4/100
|
||||
invoke DrawCityVertical3D,1,FP_1*535/100,lo,hi,gate,eax,238
|
||||
mov light,242
|
||||
cmp bpState3D,BP_RESET
|
||||
jne @F
|
||||
test bpTime3D,100h
|
||||
jz @F
|
||||
mov light,243
|
||||
@@:
|
||||
mov eax,bpCentre3D
|
||||
sub eax,FP_1/10
|
||||
mov ebx,bpCentre3D
|
||||
add ebx,FP_1/10
|
||||
invoke DrawCityVertical3D,1,FP_1*536/100,eax,ebx,FP_1*12/10,FP_1*124/100,light
|
||||
ret
|
||||
RenderBowlingPinsetter3D ENDP
|
||||
|
|
@ -23,6 +23,8 @@ BeginBowlingPlay3D PROC uses esi lane:DWORD
|
|||
mov paused3D,0
|
||||
mov bwSeat3D,0
|
||||
call ResetBowlingPlay3D
|
||||
mov bpState3D,BP_SELECT_BALL
|
||||
call BowlingAudioOpen3D
|
||||
mov eax,1
|
||||
ret
|
||||
bp_begin_no:
|
||||
|
|
@ -56,6 +58,8 @@ ResetBowlingPlay3D PROC uses ebx esi edi
|
|||
mov bpScoreOpen3D,0
|
||||
mov bpLast3D,0
|
||||
mov bpLastKind3D,0
|
||||
mov bpReactionTime3D,0
|
||||
mov bpAfterReturn3D,BP_DIRECTION
|
||||
call BowlingPlayRack3D
|
||||
call ClearKeys3D
|
||||
mov mouseClick3D,0
|
||||
|
|
@ -77,6 +81,7 @@ BowlingPlayStartAim3D ENDP
|
|||
LeaveBowlingPlay3D PROC uses esi
|
||||
cmp bpActive3D,0
|
||||
je bp_leave_done
|
||||
call BowlingAudioClose3D
|
||||
mov esi,bpLane3D
|
||||
mov bwBusy3D[esi*4],0
|
||||
mov bwRack3D[esi*4],1023
|
||||
|
|
@ -109,180 +114,78 @@ bp_rack_pin:
|
|||
mov bpPinY3D[esi*4],eax
|
||||
mov bpPinVX3D[esi*4],0
|
||||
mov bpPinVY3D[esi*4],0
|
||||
mov bpPinTilt3D[esi*4],0
|
||||
mov bpPinTiltV3D[esi*4],0
|
||||
mov bpPinAxisX3D[esi*4],0
|
||||
mov bpPinAxisY3D[esi*4],-FP_1
|
||||
mov bpPinSpin3D[esi*4],0
|
||||
mov bpPinContactTick3D[esi*4],0
|
||||
mov bpRadius3D[esi*4],24
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_rack_pin
|
||||
mov bpHitMask3D,0
|
||||
mov bpGutter3D,0
|
||||
mov bpAccumulator3D,0
|
||||
mov bpBallX3D,0
|
||||
mov bpBallY3D,FP_1*225/10
|
||||
mov bpPhysicsTicks3D,0
|
||||
mov bpEndTicks3D,0
|
||||
mov bpImpactEnergy3D,0
|
||||
mov bpImpactCooldown3D,0
|
||||
mov bpAudioReleased3D,0
|
||||
mov bpBallX3D,FP_1/2
|
||||
mov bpBallY3D,24*FP_1
|
||||
ret
|
||||
BowlingPlayRack3D ENDP
|
||||
|
||||
BowlingPlayLaunch3D PROC
|
||||
local speed:DWORD,aimX:DWORD,aimLength:REAL8
|
||||
mov bpState3D,BP_RELEASE
|
||||
mov bpTime3D,0
|
||||
mov bpAccumulator3D,0
|
||||
call BowlingApplyBallMass3D
|
||||
mov eax,bpLockedPower3D
|
||||
imul eax,6*FP_1
|
||||
cdq
|
||||
mov ecx,100
|
||||
idiv ecx
|
||||
add eax,3*FP_1
|
||||
imul eax,16
|
||||
cdq
|
||||
mov ecx,1000
|
||||
idiv ecx
|
||||
mov ecx,eax
|
||||
neg eax
|
||||
mov bpBallVY3D,eax
|
||||
mov speed,eax
|
||||
; The gauge fixes launch work, calibrated to the existing six-kilogram ball.
|
||||
; v = v_reference * sqrt(m_reference / m); no mass-dependent aim noise.
|
||||
fild bpReferenceKg3D
|
||||
fidiv bpShotWeightKg3D
|
||||
fsqrt
|
||||
fimul speed
|
||||
fist bpLaunchSpeed3D
|
||||
fimul bpTickMs3D
|
||||
fidiv bpSecondMs3D
|
||||
fistp speed
|
||||
mov eax,bpLockedAim3D
|
||||
imul ecx
|
||||
mov ecx,18*FP_1
|
||||
idiv ecx
|
||||
mov bpBallVX3D,eax
|
||||
sub eax,bpBallX3D
|
||||
mov aimX,eax
|
||||
fild aimX
|
||||
fmul st,st
|
||||
fild bpLaneDistance3D
|
||||
fmul st,st
|
||||
faddp st(1),st
|
||||
fsqrt
|
||||
fstp aimLength
|
||||
fild aimX
|
||||
fdiv aimLength
|
||||
fimul speed
|
||||
fistp bpBallVX3D
|
||||
fild bpLaneDistance3D
|
||||
fdiv aimLength
|
||||
fimul speed
|
||||
fchs
|
||||
fistp bpBallVY3D
|
||||
ret
|
||||
BowlingPlayLaunch3D ENDP
|
||||
|
||||
BowlingPlayHit3D PROC uses esi pin:DWORD,vx:DWORD,vy:DWORD
|
||||
mov esi,pin
|
||||
mov ecx,esi
|
||||
mov eax,1
|
||||
shl eax,cl
|
||||
test bpHitMask3D,eax
|
||||
jnz bp_hit_done
|
||||
or bpHitMask3D,eax
|
||||
mov eax,vx
|
||||
mov bpPinVX3D[esi*4],eax
|
||||
mov eax,vy
|
||||
mov bpPinVY3D[esi*4],eax
|
||||
bp_hit_done:
|
||||
ret
|
||||
BowlingPlayHit3D ENDP
|
||||
|
||||
; 16-ms fixed steps, lane-relative 16.16 discs. No random hit selection.
|
||||
BowlingPlayStep3D PROC uses ebx esi edi
|
||||
local deltaX:DWORD,deltaY:DWORD,impulseX:DWORD,rackMask:DWORD
|
||||
mov esi,bpLane3D
|
||||
mov eax,bwRack3D[esi*4]
|
||||
mov rackMask,eax
|
||||
mov eax,bpBallVX3D
|
||||
add bpBallX3D,eax
|
||||
mov eax,bpBallVY3D
|
||||
add bpBallY3D,eax
|
||||
mov eax,bpBallX3D
|
||||
cdq
|
||||
xor eax,edx
|
||||
sub eax,edx
|
||||
cmp eax,FP_1*74/100
|
||||
jbe bp_step_pins
|
||||
mov bpGutter3D,1
|
||||
mov eax,FP_1*87/100
|
||||
cmp bpBallX3D,0
|
||||
jge @F
|
||||
neg eax
|
||||
@@:
|
||||
mov bpBallX3D,eax
|
||||
mov bpBallVX3D,0
|
||||
bp_step_pins:
|
||||
xor esi,esi
|
||||
bp_step_pin:
|
||||
mov ecx,esi
|
||||
mov ebx,1
|
||||
shl ebx,cl
|
||||
test rackMask,ebx
|
||||
jz bp_step_next_pin
|
||||
test bpHitMask3D,ebx
|
||||
jnz bp_step_move_pin
|
||||
cmp bpGutter3D,0
|
||||
jne bp_step_next_pin
|
||||
mov eax,bpPinX3D[esi*4]
|
||||
sub eax,bpBallX3D
|
||||
mov deltaX,eax
|
||||
sar eax,8
|
||||
imul eax,eax
|
||||
mov edi,eax
|
||||
mov eax,bpPinY3D[esi*4]
|
||||
sub eax,bpBallY3D
|
||||
sar eax,8
|
||||
imul eax,eax
|
||||
add eax,edi
|
||||
cmp eax,56*56
|
||||
ja bp_step_next_pin
|
||||
mov eax,deltaX
|
||||
sar eax,3
|
||||
add eax,bpBallVX3D
|
||||
mov impulseX,eax
|
||||
mov eax,bpBallVY3D
|
||||
imul eax,3
|
||||
sar eax,2
|
||||
invoke BowlingPlayHit3D,esi,impulseX,eax
|
||||
bp_step_move_pin:
|
||||
mov eax,bpPinVX3D[esi*4]
|
||||
add bpPinX3D[esi*4],eax
|
||||
imul eax,245
|
||||
sar eax,8
|
||||
mov bpPinVX3D[esi*4],eax
|
||||
mov eax,bpPinVY3D[esi*4]
|
||||
add bpPinY3D[esi*4],eax
|
||||
imul eax,245
|
||||
sar eax,8
|
||||
mov bpPinVY3D[esi*4],eax
|
||||
xor edi,edi
|
||||
bp_step_chain:
|
||||
mov ecx,edi
|
||||
mov ebx,1
|
||||
shl ebx,cl
|
||||
test rackMask,ebx
|
||||
jz bp_step_chain_next
|
||||
test bpHitMask3D,ebx
|
||||
jnz bp_step_chain_next
|
||||
mov eax,bpPinX3D[edi*4]
|
||||
sub eax,bpPinX3D[esi*4]
|
||||
mov deltaX,eax
|
||||
sar eax,8
|
||||
imul eax,eax
|
||||
mov ebx,eax
|
||||
mov eax,bpPinY3D[edi*4]
|
||||
sub eax,bpPinY3D[esi*4]
|
||||
mov deltaY,eax
|
||||
sar eax,8
|
||||
imul eax,eax
|
||||
add eax,ebx
|
||||
cmp eax,49*49
|
||||
ja bp_step_chain_next
|
||||
mov eax,deltaX
|
||||
sar eax,8
|
||||
imul bpPinVX3D[esi*4]
|
||||
mov ebx,eax
|
||||
mov eax,deltaY
|
||||
sar eax,8
|
||||
imul bpPinVY3D[esi*4]
|
||||
add eax,ebx
|
||||
jle bp_step_chain_next
|
||||
mov eax,bpPinVX3D[esi*4]
|
||||
sar eax,1
|
||||
mov ebx,deltaX
|
||||
sar ebx,3
|
||||
add eax,ebx
|
||||
mov impulseX,eax
|
||||
mov eax,bpPinVY3D[esi*4]
|
||||
sar eax,1
|
||||
mov ebx,deltaY
|
||||
sar ebx,3
|
||||
add eax,ebx
|
||||
invoke BowlingPlayHit3D,edi,impulseX,eax
|
||||
bp_step_chain_next:
|
||||
inc edi
|
||||
cmp edi,10
|
||||
jb bp_step_chain
|
||||
bp_step_next_pin:
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_step_pin
|
||||
ret
|
||||
BowlingPlayStep3D ENDP
|
||||
include src_graphics\bowling_physics.inc
|
||||
include src_graphics\bowling_audio.inc
|
||||
include src_graphics\bowling_return.inc
|
||||
include src_graphics\bowling_weight.inc
|
||||
|
||||
BowlingPlayFinishRoll3D PROC uses esi
|
||||
mov eax,bpHitMask3D
|
||||
|
|
@ -296,6 +199,12 @@ bp_finish_count:
|
|||
jmp bp_finish_count
|
||||
bp_finish_register:
|
||||
mov bpLast3D,ecx
|
||||
mov bpReaction3D,CAST_TALK
|
||||
cmp ecx,7
|
||||
jb @F
|
||||
mov bpReaction3D,CAST_CHEER
|
||||
@@:
|
||||
mov bpReactionTime3D,6500
|
||||
mov bpLastKind3D,0
|
||||
mov esi,bpLane3D
|
||||
cmp bwBall3D[esi*4],1
|
||||
|
|
@ -313,7 +222,17 @@ bp_finish_strike:
|
|||
jne bp_finish_register_score
|
||||
mov bpLastKind3D,1
|
||||
bp_finish_register_score:
|
||||
invoke BowlingRegisterRoll3D,bpLane3D,ecx
|
||||
cmp bpLastKind3D,0
|
||||
je @F
|
||||
mov bpReaction3D,CAST_CHEER
|
||||
@@:
|
||||
cmp bpReaction3D,CAST_CHEER
|
||||
jne @F
|
||||
cmp bpAudioReady3D,0
|
||||
je @F
|
||||
invoke mciSendStringA,OFFSET bpClapPlay,0,0,0
|
||||
@@:
|
||||
invoke BowlingRegisterRoll3D,bpLane3D,bpLast3D
|
||||
mov bpState3D,BP_SETTLE
|
||||
mov bpTime3D,0
|
||||
mov bwMonitorClock3D,-1
|
||||
|
|
@ -356,7 +275,16 @@ bp_next_ready:
|
|||
BowlingPlayNext3D ENDP
|
||||
|
||||
HandleBowlingPlay3D PROC uses ebx esi
|
||||
local click:DWORD,elapsed:DWORD
|
||||
local click:DWORD,elapsed:DWORD,mousePress:DWORD
|
||||
mov eax,deltaTime3D
|
||||
sub bpImpactCooldown3D,eax
|
||||
jns @F
|
||||
mov bpImpactCooldown3D,0
|
||||
@@:
|
||||
sub bpReactionTime3D,eax
|
||||
jns @F
|
||||
mov bpReactionTime3D,0
|
||||
@@:
|
||||
invoke Pressed3D,9
|
||||
test eax,eax
|
||||
jz @F
|
||||
|
|
@ -364,6 +292,7 @@ HandleBowlingPlay3D PROC uses ebx esi
|
|||
@@:
|
||||
mov eax,mouseClick3D
|
||||
mov click,eax
|
||||
mov mousePress,eax
|
||||
mov mouseClick3D,0
|
||||
cmp click,0
|
||||
je @F
|
||||
|
|
@ -383,6 +312,7 @@ HandleBowlingPlay3D PROC uses ebx esi
|
|||
cmp click,0
|
||||
je bp_handle_done
|
||||
call ResetBowlingPlay3D
|
||||
mov bpState3D,BP_SELECT_BALL
|
||||
ret
|
||||
bp_handle_clock:
|
||||
mov eax,deltaTime3D
|
||||
|
|
@ -393,8 +323,23 @@ bp_handle_clock:
|
|||
mov elapsed,eax
|
||||
add bpClock3D,eax
|
||||
add bpTime3D,eax
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
jne @F
|
||||
cmp mousePress,0
|
||||
jne bp_handle_rack_mouse
|
||||
cmp click,0
|
||||
je bp_handle_rack_mouse
|
||||
mov bpState3D,BP_DIRECTION
|
||||
ret
|
||||
bp_handle_rack_mouse:
|
||||
invoke HandleBowlingWeight3D,mousePress
|
||||
jmp bp_handle_done
|
||||
@@:
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_handle_power
|
||||
invoke HandleBowlingWeight3D,mousePress
|
||||
test eax,eax
|
||||
jnz bp_handle_done
|
||||
mov eax,bpClock3D
|
||||
xor edx,edx
|
||||
mov ecx,4
|
||||
|
|
@ -437,7 +382,7 @@ bp_handle_release:
|
|||
cmp bpState3D,BP_RELEASE
|
||||
jne bp_handle_roll
|
||||
mov esi,bpLane3D
|
||||
mov ecx,350
|
||||
mov ecx,BP_RELEASE_MS
|
||||
cmp bwTurn3D[esi*4],0
|
||||
je @F
|
||||
mov ecx,2400
|
||||
|
|
@ -457,25 +402,52 @@ bp_handle_fixed_step:
|
|||
jb bp_handle_roll_end
|
||||
sub bpAccumulator3D,16
|
||||
call BowlingPlayStep3D
|
||||
cmp bpBallY3D,3*FP_1
|
||||
jl bp_handle_impact_done
|
||||
call BowlingPlayReady3D
|
||||
test eax,eax
|
||||
jnz bp_handle_impact_done
|
||||
jmp bp_handle_fixed_step
|
||||
bp_handle_roll_end:
|
||||
cmp bpBallY3D,3*FP_1
|
||||
jl bp_handle_impact_done
|
||||
cmp bpTime3D,12000
|
||||
jb bp_handle_done
|
||||
jmp bp_handle_done
|
||||
bp_handle_impact_done:
|
||||
call BowlingPlayFinishRoll3D
|
||||
ret
|
||||
bp_handle_settle:
|
||||
cmp bpState3D,BP_SETTLE
|
||||
jne bp_handle_bot
|
||||
cmp bpTime3D,1800
|
||||
jne bp_handle_reset
|
||||
cmp bpTime3D,1600
|
||||
jb bp_handle_done
|
||||
call BowlingPlayNext3D
|
||||
cmp bpHitMask3D,0
|
||||
jne @F
|
||||
mov esi,bpLane3D
|
||||
cmp bwNewRack3D[esi*4],0
|
||||
jne @F
|
||||
call CompleteBowlingRoll3D
|
||||
ret
|
||||
@@:
|
||||
mov bpState3D,BP_RESET
|
||||
mov bpTime3D,0
|
||||
cmp bpAudioReady3D,0
|
||||
je bp_handle_done
|
||||
invoke mciSendStringA,OFFSET bpResetPlay,0,0,0
|
||||
jmp bp_handle_done
|
||||
bp_handle_reset:
|
||||
cmp bpState3D,BP_RESET
|
||||
jne bp_handle_bot
|
||||
cmp bpTime3D,BP_RESET_MS
|
||||
jb bp_handle_done
|
||||
call CompleteBowlingRoll3D
|
||||
ret
|
||||
bp_handle_bot:
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne bp_handle_bot_ready
|
||||
cmp bpTime3D,BP_RETURN_MS
|
||||
jb bp_handle_done
|
||||
mov eax,bpAfterReturn3D
|
||||
mov bpState3D,eax
|
||||
mov bpTime3D,0
|
||||
call ClearKeys3D
|
||||
jmp bp_handle_done
|
||||
bp_handle_bot_ready:
|
||||
cmp bpState3D,BP_BOT
|
||||
jne bp_handle_done
|
||||
cmp bpTime3D,1100
|
||||
|
|
@ -501,6 +473,7 @@ bp_handle_bot:
|
|||
mov bpLockedPower3D,eax
|
||||
call BowlingPlayLaunch3D
|
||||
bp_handle_done:
|
||||
call BowlingAudioUpdate3D
|
||||
ret
|
||||
HandleBowlingPlay3D ENDP
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,37 @@ BP_ROLL equ 3
|
|||
BP_SETTLE equ 4
|
||||
BP_BOT equ 5
|
||||
BP_FINISHED equ 6
|
||||
BP_RESET equ 7
|
||||
BP_RETURN equ 8
|
||||
BP_SELECT_BALL equ 9
|
||||
BP_RELEASE_MS equ 700
|
||||
BP_RESET_MS equ 5200
|
||||
BP_RETURN_MS equ 2800
|
||||
BP_BODY_COUNT equ 11
|
||||
BP_BALL_BODY equ 10
|
||||
BP_PIN_GRAMS equ 1600
|
||||
PoolSqrt3D PROTO :DWORD
|
||||
BowlingPlayContact3D PROTO :DWORD,:DWORD
|
||||
BowlingPlayKick3D PROTO :DWORD,:DWORD,:DWORD
|
||||
NormalizeBowlingPinAxis3D PROTO :DWORD
|
||||
BowlingPlayReady3D PROTO
|
||||
BowlingPlayTether3D PROTO :DWORD
|
||||
BowlingPlayDeckBounds3D PROTO :DWORD
|
||||
BowlingRollGlyph3D PROTO :DWORD,:DWORD,:DWORD
|
||||
BowlingAudioOpen3D PROTO
|
||||
BowlingAudioClose3D PROTO
|
||||
BowlingAudioUpdate3D PROTO
|
||||
DrawBowlingPlayerHand3D PROTO
|
||||
RenderBowlingReactions3D PROTO
|
||||
RenderBowlingPinsetter3D PROTO
|
||||
BowlingPinsetterPose3D PROTO :DWORD
|
||||
BowlingPinsetterEase3D PROTO :DWORD,:DWORD
|
||||
BowlingPinsetterGate3D PROTO
|
||||
CompleteBowlingRoll3D PROTO
|
||||
BowlingReturnCamera3D PROTO :DWORD
|
||||
BowlingReturnBallPose3D PROTO
|
||||
RenderBowlingReturnMachine3D PROTO :DWORD
|
||||
RenderBowlingReturnedBall3D PROTO
|
||||
BeginBowlingPlay3D PROTO :DWORD
|
||||
LeaveBowlingPlay3D PROTO
|
||||
ResetBowlingPlay3D PROTO
|
||||
|
|
@ -23,7 +54,17 @@ DrawBowlingPlayPin3D PROTO :DWORD,:DWORD
|
|||
BowlingFrameTotal3D PROTO :DWORD,:DWORD
|
||||
DrawBowlingPlayScores3D PROTO
|
||||
InitBowlingBallSurface3D PROTO
|
||||
InitBowlingSetterSurface3D PROTO
|
||||
DrawBowlingGaugeLine3D PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||
BowlingApplyBallMass3D PROTO
|
||||
HandleBowlingWeight3D PROTO :DWORD
|
||||
DrawBowlingWeight3D PROTO
|
||||
BowlingBallMaterial3D PROTO :DWORD
|
||||
BowlingRackCamera3D PROTO
|
||||
RenderBowlingBallRack3D PROTO :DWORD,:DWORD
|
||||
BowlingRackScreen3D PROTO :DWORD
|
||||
BowlingTintBallPixel3D PROTO :DWORD,:DWORD
|
||||
BowlingTintHand3D PROTO :DWORD,:DWORD
|
||||
.data
|
||||
bpActive3D dd 0
|
||||
bpLane3D dd 1
|
||||
|
|
@ -35,6 +76,23 @@ bpAim3D dd 0
|
|||
bpPower3D dd 50
|
||||
bpLockedAim3D dd 0
|
||||
bpLockedPower3D dd 50
|
||||
bpWeightKg3D dd 6
|
||||
bpBotWeightKg3D dd 6
|
||||
bpShotWeightKg3D dd 6
|
||||
bpBallGrams3D dd 6000
|
||||
bpLaunchSpeed3D dd 0
|
||||
bpReferenceKg3D dd 6
|
||||
bpLaneDistance3D dd FP_1*193/10
|
||||
bpTickMs3D dd 16
|
||||
bpSecondMs3D dd 1000
|
||||
bpRackHitX3D dd 4 dup(0)
|
||||
bpRackHitY3D dd 4 dup(0)
|
||||
bpRackHitRadius3D dd 4 dup(0)
|
||||
bpRackHandFrame3D dd -1
|
||||
bpRackHandKg3D dd -1
|
||||
bpTintedHand3D AnimPack3D <>
|
||||
bpBallMaterials3D dd 255,256,253,257
|
||||
bpBallColors3D dd 0057C78Ch,00D26B65h,005B8DE8h,00D8AB55h
|
||||
bpLast3D dd 0
|
||||
bpLastKind3D dd 0
|
||||
bpGutter3D dd 0
|
||||
|
|
@ -45,19 +103,66 @@ bpBallY3D dd 0
|
|||
bpBallVX3D dd 0
|
||||
bpBallVY3D dd 0
|
||||
bpHitMask3D dd 0
|
||||
bpPinX3D dd 10 dup(0)
|
||||
bpPinY3D dd 10 dup(0)
|
||||
bpPinVX3D dd 10 dup(0)
|
||||
bpPinVY3D dd 10 dup(0)
|
||||
; Inverse masses are Q16, normalized to a 1600-gram pin. Last body is the ball.
|
||||
bpPinX3D dd BP_BODY_COUNT dup(0)
|
||||
bpPinY3D dd BP_BODY_COUNT dup(0)
|
||||
bpPinVX3D dd BP_BODY_COUNT dup(0)
|
||||
bpPinVY3D dd BP_BODY_COUNT dup(0)
|
||||
bpInvMass3D dd 10 dup(FP_1),BP_PIN_GRAMS*FP_1/6000
|
||||
bpRadius3D dd 10 dup(24),31
|
||||
bpPinTilt3D dd 10 dup(0)
|
||||
bpPinTiltV3D dd 10 dup(0)
|
||||
bpPinAxisX3D dd 10 dup(0)
|
||||
bpPinAxisY3D dd 10 dup(-FP_1)
|
||||
bpPinSpin3D dd 10 dup(0)
|
||||
bpPinContactTick3D dd 10 dup(0)
|
||||
bpPhysicsTicks3D dd 0
|
||||
bpEndTicks3D dd 0
|
||||
bpImpactEnergy3D dd 0
|
||||
bpImpactCooldown3D dd 0
|
||||
bpReaction3D dd 0
|
||||
bpReactionTime3D dd 0
|
||||
bpAudioReady3D dd 0
|
||||
bpAudioRolling3D dd 0
|
||||
bpAudioReturning3D dd 0
|
||||
bpAudioReleased3D dd 0
|
||||
bpAudioVolume3D dd -1
|
||||
bpHandArt3D AnimPack3D <>
|
||||
bpHandPath3D db "assets\animations\bowling\player-underarm-v2.bin",0
|
||||
bpGlyph3D db 0,0
|
||||
bpPinSectionHeight3D dd FP_1*14/100,FP_1*27/100,FP_1*285/1000,FP_1*35/100
|
||||
bpPinSectionRadius3D dd FP_1*90/1000,FP_1*37/1000,FP_1*39/1000,FP_1*55/1000
|
||||
bpPinSectionLength3D dd FP_1*145/1000,FP_1*65/1000,FP_1*16/1000,FP_1*65/1000
|
||||
bpPinSectionMaterial3D dd 239,239,240,239
|
||||
bpRenderNX3D dd 0
|
||||
bpRenderNY3D dd 0
|
||||
bpRenderNZ3D dd FP_1
|
||||
bpRenderUX3D dd FP_1
|
||||
bpRenderUY3D dd 0
|
||||
bpRenderVX3D dd 0
|
||||
bpRenderVY3D dd FP_1
|
||||
bpRenderVZ3D dd 0
|
||||
bpVisualPinX3D dd 0
|
||||
bpVisualPinY3D dd 0
|
||||
bpVisualPinTilt3D dd 0
|
||||
bpVisualPinLift3D dd 0
|
||||
bpAfterReturn3D dd BP_DIRECTION
|
||||
bpReturnedX3D dd 0
|
||||
bpReturnedY3D dd 0
|
||||
bpReturnedZ3D dd 0
|
||||
bpReturnedPhase3D dd 0
|
||||
include src_graphics\bowling_audio_data.inc
|
||||
bpCentre3D dd 0
|
||||
bpHomeX3D dd 0
|
||||
bpHomeY3D dd 0
|
||||
bpHomeAngle3D dd 0
|
||||
bpText3D db 24 dup(0)
|
||||
bpMonitorTexts3D dd OFFSET bpDirectionText,OFFSET bpPowerText,OFFSET bpRollText,OFFSET bpRollText
|
||||
dd OFFSET bpResultText,OFFSET bpBot,OFFSET bpScoreText
|
||||
dd OFFSET bpResultText,OFFSET bpBot,OFFSET bpScoreText,OFFSET bpResetText,OFFSET bpReturnText,OFFSET bpSelectBallText
|
||||
.data?
|
||||
bpBallSurface3D dd 64*64 dup(?)
|
||||
bpBallSurface3D dd 4*64*64 dup(?)
|
||||
bpTintedHandPixels3D dd 256*256 dup(?)
|
||||
bpSetterSurface3D dd 64*64 dup(?)
|
||||
.data
|
||||
bpPlayPrompt db 200,195,208,192,210,220,32,194,32,193,206,211,203,200,205,195,0
|
||||
bpTitle db 193,206,211,203,200,205,195,0
|
||||
|
|
@ -77,4 +182,15 @@ bpScoreText db 209,215,168,210,0
|
|||
bpGutterText db 198,197,203,206,193,0
|
||||
bpStrikeText db 209,210,208,192,201,202,0
|
||||
bpSpareText db 209,207,221,208,0
|
||||
bpResetText db 211,209,210,192,205,206,194,202,192,0
|
||||
bpReturnText db 194,206,199,194,208,192,210,32,216,192,208,192,0
|
||||
bpKilogramsText db ' ',202,195,0
|
||||
bpKg4Text db '4 ',202,195,0
|
||||
bpKg5Text db '5 ',202,195,0
|
||||
bpKg6Text db '6 ',202,195,0
|
||||
bpKg7Text db '7 ',202,195,0
|
||||
bpWeightLabels3D dd OFFSET bpKg4Text,OFFSET bpKg5Text,OFFSET bpKg6Text,OFFSET bpKg7Text
|
||||
bpSelectBallText db 194,219,193,206,208,32,216,192,208,192,0
|
||||
bpTakeBallText db 194,199,223,210,220,0
|
||||
bpChangeBallText db 216,192,208,0
|
||||
.code
|
||||
|
|
|
|||
|
|
@ -34,44 +34,97 @@ bp_ball_tex_pixel:
|
|||
inc esi
|
||||
cmp esi,64
|
||||
jb bp_ball_tex_row
|
||||
xor esi,esi
|
||||
bp_ball_tex_variants:
|
||||
mov eax,bpBallSurface3D[esi*4]
|
||||
invoke BowlingTintBallPixel3D,eax,4
|
||||
mov bpBallSurface3D[esi*4+64*64*4],eax
|
||||
mov eax,bpBallSurface3D[esi*4]
|
||||
invoke BowlingTintBallPixel3D,eax,5
|
||||
mov bpBallSurface3D[esi*4+2*64*64*4],eax
|
||||
mov eax,bpBallSurface3D[esi*4]
|
||||
invoke BowlingTintBallPixel3D,eax,7
|
||||
mov bpBallSurface3D[esi*4+3*64*64*4],eax
|
||||
inc esi
|
||||
cmp esi,64*64
|
||||
jb bp_ball_tex_variants
|
||||
ret
|
||||
InitBowlingBallSurface3D ENDP
|
||||
|
||||
include src_graphics\bowling_pin_shape.inc
|
||||
include src_graphics\bowling_pinsetter.inc
|
||||
|
||||
DrawBowlingPlayPin3D PROC uses ebx esi edi pin:DWORD,centre:DWORD
|
||||
local x:DWORD,y:DWORD,z:DWORD,headY:DWORD,ry:DWORD,rz:DWORD
|
||||
local baseX:DWORD,baseY:DWORD,axisX:DWORD,axisY:DWORD,axisZ:DWORD
|
||||
local x:DWORD,y:DWORD,z:DWORD,radius:DWORD
|
||||
mov esi,pin
|
||||
mov ecx,esi
|
||||
mov ebx,1
|
||||
shl ebx,cl
|
||||
mov edi,bpLane3D
|
||||
test bwRack3D[edi*4],ebx
|
||||
invoke BowlingPinsetterPose3D,esi
|
||||
test eax,eax
|
||||
jz bp_pin_done
|
||||
mov eax,bpPinX3D[esi*4]
|
||||
mov eax,bpVisualPinX3D
|
||||
add eax,centre
|
||||
mov x,eax
|
||||
mov eax,bpPinY3D[esi*4]
|
||||
mov y,eax
|
||||
mov headY,eax
|
||||
mov z,FP_1*15/100
|
||||
mov ry,FP_1/10
|
||||
mov rz,FP_1*13/100
|
||||
test bpHitMask3D,ebx
|
||||
jz bp_pin_draw
|
||||
mov z,FP_1*7/100
|
||||
mov ry,FP_1*23/100
|
||||
mov rz,FP_1*6/100
|
||||
sub headY,FP_1/4
|
||||
bp_pin_draw:
|
||||
invoke DrawRoofEllipsoid3D,x,y,z,FP_1/10,ry,rz,239
|
||||
mov eax,FP_1*34/100
|
||||
test bpHitMask3D,ebx
|
||||
jz @F
|
||||
mov eax,FP_1*7/100
|
||||
mov baseX,eax
|
||||
mov eax,bpVisualPinY3D
|
||||
mov baseY,eax
|
||||
mov eax,bpVisualPinTilt3D
|
||||
shr eax,8
|
||||
cmp eax,128
|
||||
jbe @F
|
||||
mov eax,128
|
||||
@@:
|
||||
invoke DrawRoofEllipsoid3D,x,headY,eax,FP_1*65/1000,FP_1*65/1000,FP_1*6/100,239
|
||||
mov eax,z
|
||||
add eax,rz
|
||||
invoke DrawRoofEllipsoid3D,x,headY,eax,FP_1*45/1000,FP_1*45/1000,FP_1*25/1000,240
|
||||
mov edi,tableSin[eax*4]
|
||||
mov ecx,edi
|
||||
neg ecx
|
||||
mov bpRenderVZ3D,ecx
|
||||
mov eax,tableCos[eax*4]
|
||||
mov axisZ,eax
|
||||
mov bpRenderNZ3D,eax
|
||||
imul bpPinAxisX3D[esi*4]
|
||||
shrd eax,edx,16
|
||||
mov bpRenderVX3D,eax
|
||||
mov eax,axisZ
|
||||
imul bpPinAxisY3D[esi*4]
|
||||
shrd eax,edx,16
|
||||
mov bpRenderVY3D,eax
|
||||
mov eax,bpPinAxisY3D[esi*4]
|
||||
mov bpRenderUX3D,eax
|
||||
mov eax,bpPinAxisX3D[esi*4]
|
||||
neg eax
|
||||
mov bpRenderUY3D,eax
|
||||
mov eax,bpPinAxisX3D[esi*4]
|
||||
imul edi
|
||||
shrd eax,edx,16
|
||||
mov axisX,eax
|
||||
mov bpRenderNX3D,eax
|
||||
mov eax,bpPinAxisY3D[esi*4]
|
||||
imul edi
|
||||
shrd eax,edx,16
|
||||
mov axisY,eax
|
||||
mov bpRenderNY3D,eax
|
||||
xor ebx,ebx
|
||||
bp_pin_section:
|
||||
mov eax,bpPinSectionHeight3D[ebx*4]
|
||||
imul axisX
|
||||
shrd eax,edx,16
|
||||
add eax,baseX
|
||||
mov x,eax
|
||||
mov eax,bpPinSectionHeight3D[ebx*4]
|
||||
imul axisY
|
||||
shrd eax,edx,16
|
||||
add eax,baseY
|
||||
mov y,eax
|
||||
mov eax,bpPinSectionHeight3D[ebx*4]
|
||||
imul axisZ
|
||||
shrd eax,edx,16
|
||||
add eax,FP_1*8/100
|
||||
add eax,bpVisualPinLift3D
|
||||
mov z,eax
|
||||
mov eax,bpPinSectionRadius3D[ebx*4]
|
||||
mov radius,eax
|
||||
invoke DrawBowlingEllipsoid3D,x,y,z,radius,radius,bpPinSectionLength3D[ebx*4],bpPinSectionMaterial3D[ebx*4]
|
||||
inc ebx
|
||||
cmp ebx,4
|
||||
jb bp_pin_section
|
||||
bp_pin_done:
|
||||
ret
|
||||
DrawBowlingPlayPin3D ENDP
|
||||
|
|
@ -126,59 +179,7 @@ bp_frame_pending:
|
|||
ret
|
||||
BowlingFrameTotal3D ENDP
|
||||
|
||||
DrawBowlingPlayScores3D PROC uses ebx esi edi
|
||||
local x:DWORD,y:DWORD,owner:DWORD
|
||||
invoke DrawBoxBorder,4,47,312,139,00151F26h,005BC9BEh,1
|
||||
invoke DrawString8x8,12,55,OFFSET bpScoreText,00E8D7ADh
|
||||
xor esi,esi
|
||||
bp_score_heading:
|
||||
imul eax,esi,26
|
||||
add eax,44
|
||||
mov x,eax
|
||||
lea eax,[esi+1]
|
||||
invoke FormatNumber,eax,OFFSET bpText3D
|
||||
invoke DrawString8x8,x,73,OFFSET bpText3D,00AABDB6h
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_score_heading
|
||||
xor edi,edi
|
||||
bp_score_owner:
|
||||
lea eax,[edi*2]
|
||||
imul eax,18
|
||||
add eax,96
|
||||
mov y,eax
|
||||
mov eax,OFFSET bpYou
|
||||
test edi,edi
|
||||
jz @F
|
||||
mov eax,OFFSET bpBot
|
||||
@@:
|
||||
invoke DrawString8x8,9,y,eax,005BC9BEh
|
||||
mov eax,bpLane3D
|
||||
shl eax,1
|
||||
add eax,edi
|
||||
mov owner,eax
|
||||
xor esi,esi
|
||||
bp_score_cell:
|
||||
imul eax,esi,26
|
||||
add eax,44
|
||||
mov x,eax
|
||||
invoke BowlingFrameTotal3D,owner,esi
|
||||
cmp eax,-1
|
||||
je bp_score_empty
|
||||
invoke FormatNumber,eax,OFFSET bpText3D
|
||||
invoke DrawString8x8,x,y,OFFSET bpText3D,00FFFFFFh
|
||||
jmp bp_score_next
|
||||
bp_score_empty:
|
||||
invoke DrawBox,x,y,8,1,005C727Bh
|
||||
bp_score_next:
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_score_cell
|
||||
inc edi
|
||||
cmp edi,2
|
||||
jb bp_score_owner
|
||||
ret
|
||||
DrawBowlingPlayScores3D ENDP
|
||||
include src_graphics\bowling_scorecard.inc
|
||||
|
||||
DrawBowlingGaugeLine3D PROC uses ebx esi edi x0:DWORD,y0:DWORD,x1:DWORD,y1:DWORD
|
||||
local px:DWORD,py:DWORD,stepX:DWORD,stepY:DWORD
|
||||
|
|
@ -235,6 +236,8 @@ bp_gauge_line:
|
|||
ret
|
||||
DrawBowlingGaugeLine3D ENDP
|
||||
|
||||
include src_graphics\bowling_performance.inc
|
||||
|
||||
RenderBowlingPlay3D PROC uses ebx esi edi
|
||||
local x:DWORD,y:DWORD,color:DWORD,owner:DWORD,startY:DWORD
|
||||
mov eax,bpCentre3D
|
||||
|
|
@ -252,6 +255,8 @@ RenderBowlingPlay3D PROC uses ebx esi edi
|
|||
cmp bpState3D,BP_ROLL
|
||||
je bp_camera_follow
|
||||
cmp bpState3D,BP_SETTLE
|
||||
je bp_camera_follow
|
||||
cmp bpState3D,BP_RESET
|
||||
jne bp_camera_ready
|
||||
bp_camera_follow:
|
||||
mov eax,bpBallY3D
|
||||
|
|
@ -262,6 +267,40 @@ bp_camera_follow:
|
|||
@@:
|
||||
mov playerY,eax
|
||||
mov viewEye3D,FP_1*7/10
|
||||
cmp bpState3D,BP_RESET
|
||||
jne bp_camera_roll_blend
|
||||
mov ebx,bpTime3D
|
||||
cmp ebx,400
|
||||
jbe @F
|
||||
mov ebx,400
|
||||
@@:
|
||||
imul eax,ebx,2*FP_1
|
||||
cdq
|
||||
mov ecx,400
|
||||
idiv ecx
|
||||
add playerY,eax
|
||||
mov eax,playerY
|
||||
mov ebx,bpTime3D
|
||||
sub ebx,BP_RESET_MS-800
|
||||
jle bp_camera_ready
|
||||
cmp ebx,800
|
||||
jbe @F
|
||||
mov ebx,800
|
||||
@@:
|
||||
mov edx,startY
|
||||
sub edx,eax
|
||||
mov eax,edx
|
||||
imul eax,ebx
|
||||
cdq
|
||||
mov ecx,800
|
||||
idiv ecx
|
||||
add playerY,eax
|
||||
imul eax,ebx,HALL_STANDING_EYE-FP_1*7/10
|
||||
cdq
|
||||
idiv ecx
|
||||
add viewEye3D,eax
|
||||
jmp bp_camera_ready
|
||||
bp_camera_roll_blend:
|
||||
cmp bpState3D,BP_ROLL
|
||||
jne bp_camera_ready
|
||||
mov ebx,bpTime3D
|
||||
|
|
@ -274,15 +313,48 @@ bp_camera_follow:
|
|||
idiv ecx
|
||||
add eax,startY
|
||||
mov playerY,eax
|
||||
imul eax,ebx,FP_1*7/20
|
||||
mov edx,HALL_STANDING_EYE
|
||||
cmp bwTurn3D[esi*4],0
|
||||
jne @F
|
||||
mov edx,FP_1*55/100
|
||||
@@:
|
||||
mov x,edx
|
||||
mov eax,FP_1*7/10
|
||||
sub eax,edx
|
||||
imul eax,ebx
|
||||
cdq
|
||||
idiv ecx
|
||||
add eax,x
|
||||
mov viewEye3D,eax
|
||||
bp_camera_ready:
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
jne @F
|
||||
call BowlingRackCamera3D
|
||||
@@:
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne @F
|
||||
invoke BowlingReturnCamera3D,startY
|
||||
@@:
|
||||
cmp bpState3D,BP_RELEASE
|
||||
jne @F
|
||||
cmp bwTurn3D[esi*4],0
|
||||
jne @F
|
||||
mov eax,bpTime3D
|
||||
cmp eax,BP_RELEASE_MS
|
||||
jbe bp_camera_release_time
|
||||
mov eax,BP_RELEASE_MS
|
||||
bp_camera_release_time:
|
||||
imul eax,FP_1/2
|
||||
cdq
|
||||
mov ecx,BP_RELEASE_MS
|
||||
idiv ecx
|
||||
mov edx,HALL_STANDING_EYE
|
||||
sub edx,eax
|
||||
mov viewEye3D,edx
|
||||
bp_camera_ready:
|
||||
@@:
|
||||
call UpdateCamera3D
|
||||
call RenderBowling3D
|
||||
call RenderBowlingPinsetter3D
|
||||
mov esi,bpLane3D
|
||||
cmp bwTurn3D[esi*4],1
|
||||
jne bp_render_ball
|
||||
|
|
@ -306,12 +378,31 @@ bp_render_bot_draw:
|
|||
mov bwActor3D.posY,FP_1*235/10
|
||||
invoke DrawCityObject3D,OFFSET bwActor3D,0
|
||||
bp_render_ball:
|
||||
call RenderBowlingReactions3D
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
je bp_render_hud
|
||||
cmp bpState3D,BP_FINISHED
|
||||
je bp_render_hud
|
||||
cmp bpState3D,BP_ROLL
|
||||
je bp_render_real_ball
|
||||
cmp bpState3D,BP_SETTLE
|
||||
je bp_render_real_ball
|
||||
cmp bpState3D,BP_RESET
|
||||
je bp_render_hud
|
||||
cmp bpState3D,BP_RETURN
|
||||
je bp_render_hud
|
||||
cmp bpHandArt3D.pixels,0
|
||||
jne bp_render_hud
|
||||
bp_render_real_ball:
|
||||
cmp bpEndTicks3D,25
|
||||
jae bp_render_hud
|
||||
mov eax,bpBallX3D
|
||||
add eax,bpCentre3D
|
||||
invoke DrawBowlingBall3D,eax,bpBallY3D,253
|
||||
mov x,eax
|
||||
invoke BowlingBallMaterial3D,bpShotWeightKg3D
|
||||
invoke DrawBowlingBall3D,x,bpBallY3D,eax
|
||||
bp_render_hud:
|
||||
call DrawBowlingPlayerHand3D
|
||||
invoke DrawBox,0,0,320,17,00121B20h
|
||||
invoke DrawString8x8,8,4,OFFSET bpTitle,00E8D7ADh
|
||||
mov eax,bpLane3D
|
||||
|
|
@ -338,7 +429,10 @@ bp_render_hud:
|
|||
mov ebx,owner
|
||||
mov eax,bwFrames3D[ebx*4]
|
||||
cmp bpState3D,BP_SETTLE
|
||||
je bp_frame_result
|
||||
cmp bpState3D,BP_RESET
|
||||
jne @F
|
||||
bp_frame_result:
|
||||
cmp bwFrameDone3D[esi*4],0
|
||||
je @F
|
||||
dec eax
|
||||
|
|
@ -353,12 +447,24 @@ bp_render_hud:
|
|||
invoke DrawString8x8,116,227,OFFSET bpText3D,00FFFFFFh
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
je bp_render_direction
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
je bp_render_done
|
||||
cmp bpState3D,BP_POWER
|
||||
je bp_render_power
|
||||
cmp bpState3D,BP_SETTLE
|
||||
je bp_render_result
|
||||
cmp bpState3D,BP_FINISHED
|
||||
je bp_render_finished
|
||||
cmp bpState3D,BP_RESET
|
||||
jne @F
|
||||
invoke DrawString8x8,104,197,OFFSET bpResetText,00E8D7ADh
|
||||
jmp bp_render_done
|
||||
@@:
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne @F
|
||||
invoke DrawString8x8,104,197,OFFSET bpReturnText,00E8D7ADh
|
||||
jmp bp_render_done
|
||||
@@:
|
||||
invoke DrawString8x8,8,204,OFFSET bpRollText,00E8D7ADh
|
||||
jmp bp_render_done
|
||||
bp_render_direction:
|
||||
|
|
@ -403,11 +509,11 @@ bp_render_arc:
|
|||
invoke DrawBowlingGaugeLine3D,eax,162,ebx,168
|
||||
jmp bp_render_done
|
||||
bp_render_power:
|
||||
invoke DrawString8x8,246,62,OFFSET bpPowerText,00E8D7ADh
|
||||
invoke DrawBoxBorder,276,79,13,124,00121B20h,00AABDB6h,1
|
||||
invoke DrawBox,278,82,9,118,00D67057h
|
||||
invoke DrawBox,278,128,9,38,00E7C455h
|
||||
invoke DrawBox,278,82,9,46,005BC98Ch
|
||||
invoke DrawString8x8,16,62,OFFSET bpPowerText,00E8D7ADh
|
||||
invoke DrawBoxBorder,30,79,13,124,00121B20h,00AABDB6h,1
|
||||
invoke DrawBox,32,82,9,118,00D67057h
|
||||
invoke DrawBox,32,128,9,38,00E7C455h
|
||||
invoke DrawBox,32,82,9,46,005BC98Ch
|
||||
mov eax,bpPower3D
|
||||
imul eax,116
|
||||
xor edx,edx
|
||||
|
|
@ -416,9 +522,9 @@ bp_render_power:
|
|||
mov edx,198
|
||||
sub edx,eax
|
||||
mov y,edx
|
||||
invoke DrawBox,270,y,25,2,00FFFFFFh
|
||||
invoke DrawBox,24,y,25,2,00FFFFFFh
|
||||
invoke FormatNumber,bpPower3D,OFFSET bpText3D
|
||||
invoke DrawString8x8,246,180,OFFSET bpText3D,00FFFFFFh
|
||||
invoke DrawString8x8,50,180,OFFSET bpText3D,00FFFFFFh
|
||||
jmp bp_render_done
|
||||
bp_render_result:
|
||||
mov eax,OFFSET bpResultText
|
||||
|
|
@ -451,6 +557,7 @@ bp_render_finished:
|
|||
invoke DrawString8x8,88,161,ebx,00E8D7ADh
|
||||
invoke DrawString8x8,136,187,OFFSET bpAgainText,00FFFFFFh
|
||||
bp_render_done:
|
||||
call DrawBowlingWeight3D
|
||||
cmp bpScoreOpen3D,0
|
||||
je @F
|
||||
call DrawBowlingPlayScores3D
|
||||
|
|
|
|||
|
|
@ -158,14 +158,25 @@ bw_planes_done:
|
|||
RenderBowlingPlanes3D ENDP
|
||||
|
||||
DrawBowlingBall3D PROC uses ebx esi x:DWORD,y:DWORD,mat:DWORD
|
||||
local holeY:DWORD,holeZ:DWORD,phase:DWORD
|
||||
invoke DrawRoofEllipsoid3D,x,y,FP_1*135/1000,FP_1*12/100,FP_1*12/100,FP_1*12/100,mat
|
||||
cmp mat,253
|
||||
jne bw_ball_done
|
||||
mov eax,y
|
||||
sar eax,8
|
||||
and eax,511
|
||||
mov phase,eax
|
||||
invoke DrawBowlingBallAt3D,x,y,FP_1*135/1000,mat,eax
|
||||
ret
|
||||
DrawBowlingBall3D ENDP
|
||||
|
||||
DrawBowlingBallAt3D PROC uses ebx esi x:DWORD,y:DWORD,z:DWORD,mat:DWORD,phase:DWORD
|
||||
local holeY:DWORD,holeZ:DWORD
|
||||
invoke DrawRoofEllipsoid3D,x,y,z,FP_1*12/100,FP_1*12/100,FP_1*12/100,mat
|
||||
cmp mat,253
|
||||
je bw_ball_holes
|
||||
cmp mat,255
|
||||
jb bw_ball_done
|
||||
cmp mat,257
|
||||
ja bw_ball_done
|
||||
bw_ball_holes:
|
||||
mov eax,phase
|
||||
and eax,511
|
||||
mov eax,tableCos[eax*4]
|
||||
test eax,eax
|
||||
jle bw_ball_done
|
||||
|
|
@ -180,7 +191,7 @@ DrawBowlingBall3D PROC uses ebx esi x:DWORD,y:DWORD,mat:DWORD
|
|||
imul eax,11
|
||||
cdq
|
||||
idiv ecx
|
||||
add eax,FP_1*135/1000
|
||||
add eax,z
|
||||
mov holeZ,eax
|
||||
mov eax,x
|
||||
sub eax,FP_1*35/1000
|
||||
|
|
@ -193,7 +204,7 @@ DrawBowlingBall3D PROC uses ebx esi x:DWORD,y:DWORD,mat:DWORD
|
|||
invoke DrawRoofEllipsoid3D,x,holeY,eax,FP_1*18/1000,FP_1*18/1000,FP_1*18/1000,233
|
||||
bw_ball_done:
|
||||
ret
|
||||
DrawBowlingBall3D ENDP
|
||||
DrawBowlingBallAt3D ENDP
|
||||
|
||||
DrawBowlingPin3D PROC uses ebx esi edi lane:DWORD,pin:DWORD,centre:DWORD
|
||||
local x:DWORD,y:DWORD,t:DWORD,z:DWORD,ry:DWORD,rz:DWORD,headY:DWORD,headZ:DWORD
|
||||
|
|
@ -528,8 +539,8 @@ bw_cast_dining:
|
|||
; The match opponent leaves this restaurant seat instead of appearing twice.
|
||||
cmp bpActive3D,0
|
||||
je @F
|
||||
test esi,esi
|
||||
jz bw_cast_dining_next
|
||||
cmp esi,3
|
||||
jb bw_cast_dining_next
|
||||
@@:
|
||||
mov eax,bwVisitorX3D[esi*4]
|
||||
mov bwSmallActor3D.posX,eax
|
||||
|
|
@ -602,32 +613,8 @@ bw_detail_return:
|
|||
add eax,FP_1*64/100
|
||||
mov x1,eax
|
||||
invoke DrawCityVertical3D,1,26*FP_1+512,x0,x1,FP_1/20,FP_1*62/100,241
|
||||
xor edi,edi
|
||||
bw_detail_rack_ball:
|
||||
mov eax,centerX
|
||||
imul edx,edi,FP_1*23/100
|
||||
add eax,edx
|
||||
sub eax,FP_1*23/100
|
||||
mov ebx,242
|
||||
test edi,1
|
||||
jz @F
|
||||
mov ebx,243
|
||||
@@:
|
||||
invoke DrawRoofEllipsoid3D,eax,FP_1*254/10,FP_1*84/100,FP_1*11/100,FP_1*11/100,FP_1*11/100,ebx
|
||||
mov eax,centerX
|
||||
imul edx,edi,FP_1*23/100
|
||||
add eax,edx
|
||||
sub eax,FP_1*23/100
|
||||
sub eax,FP_1*35/1000
|
||||
invoke DrawRoofEllipsoid3D,eax,FP_1*25494/1000,FP_1*905/1000,FP_1*14/1000,FP_1*14/1000,FP_1*14/1000,233
|
||||
mov eax,centerX
|
||||
imul edx,edi,FP_1*23/100
|
||||
add eax,edx
|
||||
sub eax,FP_1*195/1000
|
||||
invoke DrawRoofEllipsoid3D,eax,FP_1*25494/1000,FP_1*905/1000,FP_1*14/1000,FP_1*14/1000,FP_1*14/1000,233
|
||||
inc edi
|
||||
cmp edi,3
|
||||
jb bw_detail_rack_ball
|
||||
invoke RenderBowlingReturnMachine3D,centerX
|
||||
invoke RenderBowlingBallRack3D,centerX,esi
|
||||
mov eax,centerX
|
||||
sub eax,FP_1*27/100
|
||||
invoke DrawRoofEllipsoid3D,eax,27*FP_1,FP_1*49/100,FP_1*16/100,FP_1*16/100,FP_1*2/100,239
|
||||
|
|
@ -637,6 +624,7 @@ bw_detail_rack_ball:
|
|||
inc esi
|
||||
cmp esi,4
|
||||
jb bw_detail_return
|
||||
call RenderBowlingReturnedBall3D
|
||||
xor esi,esi
|
||||
bw_detail_dining:
|
||||
mov eax,esi
|
||||
|
|
|
|||
145
src_graphics/bowling_return.inc
Normal file
145
src_graphics/bowling_return.inc
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
; Score/turn advancement stays independent of the visible ball-return cycle.
|
||||
CompleteBowlingRoll3D PROC
|
||||
call BowlingPlayNext3D
|
||||
mov eax,bpState3D
|
||||
mov bpAfterReturn3D,eax
|
||||
mov bpState3D,BP_RETURN
|
||||
mov bpTime3D,0
|
||||
ret
|
||||
CompleteBowlingRoll3D ENDP
|
||||
|
||||
BowlingReturnCamera3D PROC uses ebx esi startY:DWORD
|
||||
local progress:DWORD
|
||||
mov eax,bpTime3D
|
||||
cmp eax,2000
|
||||
jb bp_return_camera_turn
|
||||
mov eax,BP_RETURN_MS
|
||||
sub eax,bpTime3D
|
||||
invoke BowlingPinsetterEase3D,eax,800
|
||||
jmp bp_return_camera_pose
|
||||
bp_return_camera_turn:
|
||||
invoke BowlingPinsetterEase3D,eax,400
|
||||
bp_return_camera_pose:
|
||||
mov progress,eax
|
||||
mov ebx,FP_1*268/10
|
||||
sub ebx,startY
|
||||
imul ebx
|
||||
shrd eax,edx,16
|
||||
add eax,startY
|
||||
mov playerY,eax
|
||||
mov eax,progress
|
||||
imul eax,64
|
||||
sar eax,16
|
||||
mov esi,bpLane3D
|
||||
test esi,1
|
||||
jz @F
|
||||
neg eax
|
||||
@@:
|
||||
add eax,384
|
||||
mov playerAngle,eax
|
||||
mov viewEye3D,HALL_STANDING_EYE
|
||||
ret
|
||||
BowlingReturnCamera3D ENDP
|
||||
|
||||
; Position belongs to the return tray, not to the pin collision solver.
|
||||
BowlingReturnBallPose3D PROC uses esi
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne bp_return_ball_hidden
|
||||
mov eax,bpTime3D
|
||||
cmp eax,400
|
||||
jb bp_return_ball_hidden
|
||||
cmp eax,2000
|
||||
jae bp_return_ball_hidden
|
||||
mov esi,bpLane3D
|
||||
shr esi,1
|
||||
imul eax,esi,FP_1*38/10
|
||||
add eax,FP_1*395/100
|
||||
mov bpReturnedX3D,eax
|
||||
mov eax,bpTime3D
|
||||
sub eax,400
|
||||
cmp eax,900
|
||||
jae bp_return_ball_coast
|
||||
invoke BowlingPinsetterEase3D,eax,900
|
||||
mov esi,eax
|
||||
mov ecx,FP_1/2
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
add eax,FP_1*251/10
|
||||
mov bpReturnedY3D,eax
|
||||
mov eax,esi
|
||||
mov ecx,FP_1*22/100
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
add eax,FP_1*62/100
|
||||
mov bpReturnedZ3D,eax
|
||||
jmp bp_return_ball_phase
|
||||
bp_return_ball_coast:
|
||||
sub eax,900
|
||||
invoke BowlingPinsetterEase3D,eax,400
|
||||
mov ecx,FP_1*55/100
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
add eax,FP_1*256/10
|
||||
mov bpReturnedY3D,eax
|
||||
mov bpReturnedZ3D,FP_1*84/100
|
||||
bp_return_ball_phase:
|
||||
mov eax,bpReturnedY3D
|
||||
sub eax,FP_1*251/10
|
||||
imul eax,680
|
||||
sar eax,16
|
||||
and eax,511
|
||||
mov bpReturnedPhase3D,eax
|
||||
mov eax,1
|
||||
ret
|
||||
bp_return_ball_hidden:
|
||||
xor eax,eax
|
||||
ret
|
||||
BowlingReturnBallPose3D ENDP
|
||||
|
||||
RenderBowlingReturnMachine3D PROC uses ebx esi centre:DWORD
|
||||
local lo:DWORD,hi:DWORD
|
||||
mov eax,centre
|
||||
sub eax,FP_1*33/100
|
||||
mov lo,eax
|
||||
add eax,FP_1*66/100
|
||||
mov hi,eax
|
||||
invoke DrawRoofSolid3D,lo,hi,FP_1*248/10,FP_1*253/10,FP_1*68/100,FP_1,254
|
||||
invoke DrawRoofEllipsoid3D,centre,FP_1*2495/100,FP_1*94/100,FP_1*33/100,FP_1*32/100,FP_1*18/100,254
|
||||
mov eax,centre
|
||||
sub eax,FP_1*14/100
|
||||
mov ebx,centre
|
||||
add ebx,FP_1*14/100
|
||||
invoke DrawCityVertical3D,1,FP_1*2531/100,eax,ebx,FP_1*70/100,FP_1*95/100,233
|
||||
mov esi,-1
|
||||
bp_return_rail:
|
||||
imul eax,esi,FP_1/10
|
||||
add eax,centre
|
||||
mov ebx,eax
|
||||
sub eax,FP_1*2/100
|
||||
add ebx,FP_1*2/100
|
||||
invoke DrawRoofSolid3D,eax,ebx,FP_1*253/10,FP_1*2635/100,FP_1*70/100,FP_1*75/100,238
|
||||
add esi,2
|
||||
cmp esi,1
|
||||
jle bp_return_rail
|
||||
mov eax,centre
|
||||
sub eax,FP_1*21/100
|
||||
mov ebx,centre
|
||||
add ebx,FP_1*21/100
|
||||
mov lo,eax
|
||||
mov hi,ebx
|
||||
invoke DrawRoofSolid3D,lo,hi,FP_1*2635/100,FP_1*264/10,FP_1*70/100,FP_1*79/100,254
|
||||
invoke DrawRoofSolid3D,lo,hi,FP_1*262/10,FP_1*2628/100,FP_1*6/100,FP_1*70/100,254
|
||||
ret
|
||||
RenderBowlingReturnMachine3D ENDP
|
||||
|
||||
RenderBowlingReturnedBall3D PROC
|
||||
cmp bpActive3D,0
|
||||
je bp_return_draw_done
|
||||
call BowlingReturnBallPose3D
|
||||
test eax,eax
|
||||
jz bp_return_draw_done
|
||||
invoke BowlingBallMaterial3D,bpShotWeightKg3D
|
||||
invoke DrawBowlingBallAt3D,bpReturnedX3D,bpReturnedY3D,bpReturnedZ3D,eax,bpReturnedPhase3D
|
||||
bp_return_draw_done:
|
||||
ret
|
||||
RenderBowlingReturnedBall3D ENDP
|
||||
164
src_graphics/bowling_scorecard.inc
Normal file
164
src_graphics/bowling_scorecard.inc
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
; Return the actual roll offset of a frame, including incomplete frames.
|
||||
BowlingFrameIndex3D PROC uses ebx esi edi owner:DWORD,wanted:DWORD
|
||||
mov ebx,owner
|
||||
imul eax,ebx,96
|
||||
lea esi,bwRolls3D[eax]
|
||||
xor edi,edi
|
||||
xor ecx,ecx
|
||||
bp_index_frame:
|
||||
cmp ecx,wanted
|
||||
je bp_index_ready
|
||||
cmp edi,bwRollCount3D[ebx*4]
|
||||
jae bp_index_missing
|
||||
cmp DWORD PTR [esi+edi*4],10
|
||||
je @F
|
||||
inc edi
|
||||
@@:
|
||||
inc edi
|
||||
inc ecx
|
||||
jmp bp_index_frame
|
||||
bp_index_ready:
|
||||
mov eax,edi
|
||||
ret
|
||||
bp_index_missing:
|
||||
mov eax,-1
|
||||
ret
|
||||
BowlingFrameIndex3D ENDP
|
||||
|
||||
BowlingRollGlyph3D PROC uses ebx esi edi owner:DWORD,frame:DWORD,slot:DWORD
|
||||
invoke BowlingFrameIndex3D,owner,frame
|
||||
cmp eax,-1
|
||||
je bp_glyph_blank
|
||||
mov edi,eax
|
||||
mov ebx,owner
|
||||
imul eax,ebx,96
|
||||
lea esi,bwRolls3D[eax]
|
||||
mov ecx,slot
|
||||
cmp frame,9
|
||||
je bp_glyph_tenth
|
||||
cmp ecx,2
|
||||
jae bp_glyph_blank
|
||||
cmp DWORD PTR [esi+edi*4],10
|
||||
jne bp_glyph_available
|
||||
test ecx,ecx
|
||||
jnz bp_glyph_blank
|
||||
jmp bp_glyph_available
|
||||
bp_glyph_tenth:
|
||||
cmp ecx,3
|
||||
jae bp_glyph_blank
|
||||
cmp ecx,2
|
||||
jne bp_glyph_available
|
||||
mov eax,[esi+edi*4]
|
||||
cmp eax,10
|
||||
je bp_glyph_available
|
||||
add eax,[esi+edi*4+4]
|
||||
cmp eax,10
|
||||
jne bp_glyph_blank
|
||||
bp_glyph_available:
|
||||
add edi,ecx
|
||||
cmp edi,bwRollCount3D[ebx*4]
|
||||
jae bp_glyph_blank
|
||||
mov eax,[esi+edi*4]
|
||||
test ecx,ecx
|
||||
jz bp_glyph_digit
|
||||
cmp ecx,1
|
||||
jne bp_glyph_bonus_spare
|
||||
cmp DWORD PTR [esi+edi*4-4],10
|
||||
je bp_glyph_digit
|
||||
jmp bp_glyph_spare
|
||||
bp_glyph_bonus_spare:
|
||||
cmp DWORD PTR [esi+edi*4-8],10
|
||||
jne bp_glyph_digit
|
||||
cmp DWORD PTR [esi+edi*4-4],10
|
||||
je bp_glyph_digit
|
||||
bp_glyph_spare:
|
||||
mov edx,eax
|
||||
add edx,[esi+edi*4-4]
|
||||
cmp edx,10
|
||||
jne bp_glyph_digit
|
||||
mov eax,'/'
|
||||
ret
|
||||
bp_glyph_digit:
|
||||
cmp eax,10
|
||||
je bp_glyph_strike
|
||||
test eax,eax
|
||||
jz bp_glyph_miss
|
||||
add eax,'0'
|
||||
ret
|
||||
bp_glyph_miss:
|
||||
mov eax,'-'
|
||||
ret
|
||||
bp_glyph_strike:
|
||||
mov eax,'X'
|
||||
ret
|
||||
bp_glyph_blank:
|
||||
mov eax,' '
|
||||
ret
|
||||
BowlingRollGlyph3D ENDP
|
||||
|
||||
DrawBowlingPlayScores3D PROC uses ebx esi edi
|
||||
local x:DWORD,y:DWORD,owner:DWORD,slot:DWORD
|
||||
invoke DrawBoxBorder,4,47,312,160,00151F26h,005BC9BEh,1
|
||||
invoke DrawString8x8,12,55,OFFSET bpScoreText,00E8D7ADh
|
||||
xor esi,esi
|
||||
bp_card_header:
|
||||
imul eax,esi,26
|
||||
add eax,44
|
||||
mov x,eax
|
||||
invoke DrawBox,x,88,1,108,00425D64h
|
||||
lea eax,[esi+1]
|
||||
invoke FormatNumber,eax,OFFSET bpText3D
|
||||
invoke DrawString8x8,x,73,OFFSET bpText3D,00AABDB6h
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_card_header
|
||||
invoke DrawBox,6,137,308,1,005BC9BEh
|
||||
xor edi,edi
|
||||
bp_card_player:
|
||||
imul eax,edi,54
|
||||
add eax,95
|
||||
mov y,eax
|
||||
mov eax,OFFSET bpYou
|
||||
test edi,edi
|
||||
jz @F
|
||||
mov eax,OFFSET bpBot
|
||||
@@:
|
||||
invoke DrawString8x8,8,y,eax,005BC9BEh
|
||||
mov eax,bpLane3D
|
||||
shl eax,1
|
||||
add eax,edi
|
||||
mov owner,eax
|
||||
xor esi,esi
|
||||
bp_card_frame:
|
||||
mov slot,0
|
||||
bp_card_roll:
|
||||
invoke BowlingRollGlyph3D,owner,esi,slot
|
||||
mov bpGlyph3D,al
|
||||
imul eax,esi,26
|
||||
add eax,45
|
||||
mov ecx,slot
|
||||
lea eax,[eax+ecx*8]
|
||||
mov x,eax
|
||||
invoke DrawString8x8,x,y,OFFSET bpGlyph3D,00E8D7ADh
|
||||
inc slot
|
||||
cmp slot,3
|
||||
jb bp_card_roll
|
||||
imul eax,esi,26
|
||||
add eax,45
|
||||
mov x,eax
|
||||
invoke BowlingFrameTotal3D,owner,esi
|
||||
cmp eax,-1
|
||||
je bp_card_next
|
||||
invoke FormatNumber,eax,OFFSET bpText3D
|
||||
mov eax,y
|
||||
add eax,22
|
||||
invoke DrawString8x8,x,eax,OFFSET bpText3D,00FFFFFFh
|
||||
bp_card_next:
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb bp_card_frame
|
||||
inc edi
|
||||
cmp edi,2
|
||||
jb bp_card_player
|
||||
ret
|
||||
DrawBowlingPlayScores3D ENDP
|
||||
388
src_graphics/bowling_weight.inc
Normal file
388
src_graphics/bowling_weight.inc
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
BowlingApplyBallMass3D PROC uses esi
|
||||
mov esi,bpLane3D
|
||||
mov eax,bpWeightKg3D
|
||||
cmp bwTurn3D[esi*4],0
|
||||
je @F
|
||||
mov eax,bpBotWeightKg3D
|
||||
@@:
|
||||
cmp eax,4
|
||||
jae @F
|
||||
mov eax,4
|
||||
@@:
|
||||
cmp eax,7
|
||||
jbe @F
|
||||
mov eax,7
|
||||
@@:
|
||||
mov bpShotWeightKg3D,eax
|
||||
imul eax,1000
|
||||
mov bpBallGrams3D,eax
|
||||
mov ecx,eax
|
||||
mov eax,BP_PIN_GRAMS*FP_1
|
||||
xor edx,edx
|
||||
div ecx
|
||||
mov bpInvMass3D[BP_BALL_BODY*4],eax
|
||||
ret
|
||||
BowlingApplyBallMass3D ENDP
|
||||
|
||||
; Selection consumes its own event, never the direction-lock/throw event.
|
||||
HandleBowlingWeight3D PROC uses ebx esi mousePress:DWORD
|
||||
xor esi,esi
|
||||
bp_weight_key:
|
||||
lea eax,[esi+31h]
|
||||
invoke Pressed3D,eax
|
||||
test eax,eax
|
||||
jnz bp_weight_choose
|
||||
inc esi
|
||||
cmp esi,4
|
||||
jb bp_weight_key
|
||||
cmp mousePress,0
|
||||
je bp_weight_no
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
je bp_weight_rack_hit
|
||||
cmp mouseY3D,26
|
||||
jb bp_weight_no
|
||||
cmp mouseY3D,44
|
||||
jae bp_weight_no
|
||||
cmp mouseX3D,8
|
||||
jb bp_weight_no
|
||||
cmp mouseX3D,96
|
||||
jae bp_weight_no
|
||||
mov bpState3D,BP_SELECT_BALL
|
||||
mov eax,1
|
||||
ret
|
||||
bp_weight_rack_hit:
|
||||
call BowlingRackCamera3D
|
||||
call UpdateCamera3D
|
||||
xor esi,esi
|
||||
bp_weight_hit:
|
||||
invoke BowlingRackScreen3D,esi
|
||||
mov eax,mouseX3D
|
||||
sub eax,bpRackHitX3D[esi*4]
|
||||
imul eax,eax
|
||||
mov ebx,eax
|
||||
mov eax,mouseY3D
|
||||
sub eax,bpRackHitY3D[esi*4]
|
||||
imul eax,eax
|
||||
add ebx,eax
|
||||
mov eax,bpRackHitRadius3D[esi*4]
|
||||
add eax,2
|
||||
imul eax,eax
|
||||
cmp ebx,eax
|
||||
jbe bp_weight_choose
|
||||
mov eax,bpRackHitX3D[esi*4]
|
||||
sub eax,18
|
||||
cmp mouseX3D,eax
|
||||
jb bp_weight_hit_next
|
||||
add eax,36
|
||||
cmp mouseX3D,eax
|
||||
jae bp_weight_hit_next
|
||||
mov eax,bpRackHitY3D[esi*4]
|
||||
add eax,bpRackHitRadius3D[esi*4]
|
||||
add eax,2
|
||||
cmp mouseY3D,eax
|
||||
jb bp_weight_hit_next
|
||||
add eax,14
|
||||
cmp mouseY3D,eax
|
||||
jb bp_weight_choose
|
||||
bp_weight_hit_next:
|
||||
inc esi
|
||||
cmp esi,4
|
||||
jb bp_weight_hit
|
||||
; Ignore clicks on the floor instead of accidentally locking the direction.
|
||||
cmp mouseY3D,193
|
||||
jb bp_weight_rack_consumed
|
||||
cmp mouseY3D,213
|
||||
jae bp_weight_rack_consumed
|
||||
cmp mouseX3D,128
|
||||
jb bp_weight_rack_consumed
|
||||
cmp mouseX3D,192
|
||||
jae bp_weight_rack_consumed
|
||||
mov bpState3D,BP_DIRECTION
|
||||
bp_weight_rack_consumed:
|
||||
mov eax,1
|
||||
ret
|
||||
bp_weight_no:
|
||||
xor eax,eax
|
||||
ret
|
||||
bp_weight_choose:
|
||||
lea eax,[esi+4]
|
||||
mov bpWeightKg3D,eax
|
||||
mov bpState3D,BP_DIRECTION
|
||||
mov eax,1
|
||||
ret
|
||||
HandleBowlingWeight3D ENDP
|
||||
|
||||
DrawBowlingWeight3D PROC uses ebx esi edi
|
||||
local x:DWORD,y:DWORD,edge:DWORD
|
||||
cmp bpScoreOpen3D,0
|
||||
jne bp_weight_draw_done
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
jne bp_weight_locked_label
|
||||
invoke DrawString8x8,120,32,OFFSET bpSelectBallText,00E8D7ADh
|
||||
xor esi,esi
|
||||
bp_weight_rack_label:
|
||||
invoke BowlingRackScreen3D,esi
|
||||
mov eax,bpRackHitX3D[esi*4]
|
||||
sub eax,18
|
||||
mov x,eax
|
||||
mov eax,bpRackHitY3D[esi*4]
|
||||
add eax,bpRackHitRadius3D[esi*4]
|
||||
add eax,2
|
||||
mov y,eax
|
||||
mov edge,003C4D53h
|
||||
lea eax,[esi+4]
|
||||
cmp eax,bpWeightKg3D
|
||||
jne @F
|
||||
mov eax,bpBallColors3D[esi*4]
|
||||
mov edge,eax
|
||||
@@:
|
||||
invoke DrawBoxBorder,x,y,36,14,00121B20h,edge,1
|
||||
mov eax,x
|
||||
add eax,2
|
||||
mov ebx,y
|
||||
add ebx,3
|
||||
invoke DrawString8x8,eax,ebx,bpWeightLabels3D[esi*4],00FFFFFFh
|
||||
inc esi
|
||||
cmp esi,4
|
||||
jb bp_weight_rack_label
|
||||
invoke DrawBoxBorder,128,193,64,20,00121B20h,005BC9BEh,1
|
||||
invoke DrawString8x8,136,199,OFFSET bpTakeBallText,00FFFFFFh
|
||||
ret
|
||||
bp_weight_locked_label:
|
||||
mov eax,bpShotWeightKg3D
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
je bp_weight_selected_label
|
||||
cmp bpState3D,BP_POWER
|
||||
jne @F
|
||||
bp_weight_selected_label:
|
||||
mov eax,bpWeightKg3D
|
||||
@@:
|
||||
cmp bpState3D,BP_BOT
|
||||
jne @F
|
||||
mov eax,bpBotWeightKg3D
|
||||
@@:
|
||||
mov esi,eax
|
||||
invoke FormatNumber,eax,OFFSET bpText3D
|
||||
invoke AppendCString,OFFSET bpText3D,OFFSET bpKilogramsText
|
||||
sub esi,4
|
||||
cmp esi,3
|
||||
ja bp_weight_draw_done
|
||||
mov eax,bpBallColors3D[esi*4]
|
||||
mov edge,eax
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_weight_static_label
|
||||
invoke DrawBoxBorder,8,26,88,18,00121B20h,edge,1
|
||||
invoke DrawString8x8,14,31,OFFSET bpChangeBallText,00E8D7ADh
|
||||
invoke DrawString8x8,50,31,OFFSET bpText3D,00FFFFFFh
|
||||
ret
|
||||
bp_weight_static_label:
|
||||
invoke DrawBox,8,27,5,7,edge
|
||||
invoke DrawString8x8,18,26,OFFSET bpText3D,00E8D7ADh
|
||||
bp_weight_draw_done:
|
||||
ret
|
||||
DrawBowlingWeight3D ENDP
|
||||
|
||||
BowlingBallMaterial3D PROC kg:DWORD
|
||||
mov eax,kg
|
||||
sub eax,4
|
||||
cmp eax,3
|
||||
jbe @F
|
||||
mov eax,2
|
||||
@@:
|
||||
mov eax,bpBallMaterials3D[eax*4]
|
||||
ret
|
||||
BowlingBallMaterial3D ENDP
|
||||
|
||||
BowlingRackCamera3D PROC
|
||||
mov eax,bpLane3D
|
||||
shr eax,1
|
||||
imul eax,FP_1*38/10
|
||||
add eax,FP_1*585/100
|
||||
mov playerX,eax
|
||||
mov playerY,FP_1*2583/100
|
||||
mov playerAngle,256
|
||||
mov viewEye3D,FP_1*102/100
|
||||
ret
|
||||
BowlingRackCamera3D ENDP
|
||||
|
||||
; Labels and picking share the actual world projection, not guessed UI slots.
|
||||
BowlingRackScreen3D PROC uses ebx esi index:DWORD
|
||||
mov esi,index
|
||||
imul ebx,esi,-FP_1*245/1000
|
||||
add ebx,FP_1*262/10
|
||||
mov eax,playerX
|
||||
sub eax,FP_1*135/100
|
||||
invoke ProjectCityPoint3D,eax,ebx
|
||||
sar eax,1
|
||||
mov bpRackHitX3D[esi*4],eax
|
||||
mov ebx,edx
|
||||
mov eax,viewEye3D
|
||||
sub eax,FP_1*84/100
|
||||
imul eax,SCREEN_H
|
||||
cdq
|
||||
idiv ebx
|
||||
add eax,viewHorizon3D
|
||||
sar eax,1
|
||||
mov bpRackHitY3D[esi*4],eax
|
||||
mov eax,FP_1*12/100*SCREEN_H
|
||||
cdq
|
||||
idiv ebx
|
||||
shr eax,1
|
||||
mov bpRackHitRadius3D[esi*4],eax
|
||||
ret
|
||||
BowlingRackScreen3D ENDP
|
||||
|
||||
RenderBowlingBallRack3D PROC uses ebx esi edi centre:DWORD,pairIndex:DWORD
|
||||
local lo:DWORD,hi:DWORD,x:DWORD,y:DWORD
|
||||
; Storage runs lengthwise, alongside (not across) the clear return track.
|
||||
mov eax,centre
|
||||
add eax,FP_1*43/100
|
||||
mov lo,eax
|
||||
add eax,FP_1*4/100
|
||||
mov hi,eax
|
||||
invoke DrawRoofSolid3D,lo,hi,FP_1*253/10,FP_1*264/10,FP_1*70/100,FP_1*75/100,238
|
||||
add lo,FP_1*20/100
|
||||
add hi,FP_1*20/100
|
||||
invoke DrawRoofSolid3D,lo,hi,FP_1*253/10,FP_1*264/10,FP_1*70/100,FP_1*75/100,238
|
||||
mov eax,centre
|
||||
add eax,FP_1*35/100
|
||||
mov lo,eax
|
||||
add eax,FP_1*40/100
|
||||
mov hi,eax
|
||||
invoke DrawRoofSolid3D,lo,hi,FP_1*253/10,FP_1*2538/100,FP_1*6/100,FP_1*73/100,254
|
||||
invoke DrawRoofSolid3D,lo,hi,FP_1*2632/100,FP_1*264/10,FP_1*6/100,FP_1*73/100,254
|
||||
xor esi,esi
|
||||
bp_rack_stock:
|
||||
cmp bpActive3D,0
|
||||
je bp_rack_stock_draw
|
||||
mov eax,bpLane3D
|
||||
shr eax,1
|
||||
cmp eax,pairIndex
|
||||
jne bp_rack_stock_draw
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
je bp_rack_stock_draw
|
||||
mov eax,bpWeightKg3D
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
je @F
|
||||
cmp bpState3D,BP_POWER
|
||||
je @F
|
||||
mov eax,bpShotWeightKg3D
|
||||
@@:
|
||||
sub eax,4
|
||||
cmp eax,esi
|
||||
je bp_rack_stock_next
|
||||
bp_rack_stock_draw:
|
||||
mov eax,centre
|
||||
add eax,FP_1*55/100
|
||||
mov x,eax
|
||||
imul eax,esi,-FP_1*245/1000
|
||||
add eax,FP_1*262/10
|
||||
mov y,eax
|
||||
invoke DrawBowlingBallAt3D,x,y,FP_1*84/100,bpBallMaterials3D[esi*4],45
|
||||
bp_rack_stock_next:
|
||||
inc esi
|
||||
cmp esi,4
|
||||
jb bp_rack_stock
|
||||
ret
|
||||
RenderBowlingBallRack3D ENDP
|
||||
|
||||
; Reuse the blue marble's luminance; only its hue changes. Preserve alpha.
|
||||
BowlingTintBallPixel3D PROC uses ebx ecx pixel:DWORD,kg:DWORD
|
||||
mov eax,pixel
|
||||
cmp kg,6
|
||||
je bp_tint_done
|
||||
mov ebx,eax
|
||||
and ebx,255
|
||||
mov ecx,eax
|
||||
shr ecx,16
|
||||
and ecx,255
|
||||
and eax,0FF00FF00h
|
||||
cmp kg,4
|
||||
jne @F
|
||||
mov edx,pixel
|
||||
shr edx,8
|
||||
and edx,255
|
||||
shl ebx,8
|
||||
and eax,0FFFF00FFh
|
||||
or eax,ebx
|
||||
or eax,edx
|
||||
shl ecx,16
|
||||
or eax,ecx
|
||||
ret
|
||||
@@:
|
||||
or eax,ecx
|
||||
cmp kg,5
|
||||
jne bp_tint_gold
|
||||
mov edx,eax
|
||||
and edx,0000FF00h
|
||||
shr edx,1
|
||||
and edx,0000FF00h
|
||||
and eax,0FFFF00FFh
|
||||
or eax,edx
|
||||
bp_tint_gold:
|
||||
cmp kg,7
|
||||
jne @F
|
||||
mov edx,pixel
|
||||
shr edx,8
|
||||
and edx,255
|
||||
add edx,ebx
|
||||
shr edx,1
|
||||
shl edx,8
|
||||
and eax,0FFFF00FFh
|
||||
or eax,edx
|
||||
@@:
|
||||
shl ebx,16
|
||||
or eax,ebx
|
||||
bp_tint_done:
|
||||
ret
|
||||
BowlingTintBallPixel3D ENDP
|
||||
|
||||
; A cached single-frame scratch pack keeps skin, sleeve and source assets intact.
|
||||
BowlingTintHand3D PROC uses ebx esi edi frame:DWORD,kg:DWORD
|
||||
mov eax,frame
|
||||
cmp eax,bpRackHandFrame3D
|
||||
jne bp_tint_hand_build
|
||||
mov eax,kg
|
||||
cmp eax,bpRackHandKg3D
|
||||
je bp_tint_hand_done
|
||||
bp_tint_hand_build:
|
||||
mov eax,frame
|
||||
mov bpRackHandFrame3D,eax
|
||||
shl eax,18
|
||||
add eax,bpHandArt3D.pixels
|
||||
mov esi,eax
|
||||
mov eax,kg
|
||||
mov bpRackHandKg3D,eax
|
||||
lea edi,bpTintedHandPixels3D
|
||||
mov ebx,256*256
|
||||
bp_tint_hand_pixel:
|
||||
lodsd
|
||||
cmp kg,6
|
||||
je bp_tint_hand_store
|
||||
mov edx,eax
|
||||
and edx,255
|
||||
mov ecx,eax
|
||||
shr ecx,8
|
||||
and ecx,255
|
||||
add ecx,24
|
||||
cmp edx,ecx
|
||||
jbe bp_tint_hand_store
|
||||
mov ecx,eax
|
||||
shr ecx,16
|
||||
and ecx,255
|
||||
add ecx,24
|
||||
cmp edx,ecx
|
||||
jbe bp_tint_hand_store
|
||||
invoke BowlingTintBallPixel3D,eax,kg
|
||||
bp_tint_hand_store:
|
||||
stosd
|
||||
dec ebx
|
||||
jnz bp_tint_hand_pixel
|
||||
mov bpTintedHand3D.imageWidth,256
|
||||
mov bpTintedHand3D.height,256
|
||||
mov bpTintedHand3D.frames,1
|
||||
mov bpTintedHand3D.bytes,256*256*4
|
||||
mov bpTintedHand3D.pixels,OFFSET bpTintedHandPixels3D
|
||||
bp_tint_hand_done:
|
||||
ret
|
||||
BowlingTintHand3D ENDP
|
||||
|
|
@ -5,13 +5,14 @@ InitNpcLife3D PROC uses ebx esi edi
|
|||
mov npcSelected3D,-1
|
||||
npc_life_init:
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov npcLife3D[ebx].identity,esi
|
||||
mov eax,npcInitialIdentity3D[esi*4]
|
||||
mov npcLife3D[ebx].identity,eax
|
||||
mov npcLife3D[ebx].state,NPC_STAND
|
||||
mov eax,esi
|
||||
imul eax,900
|
||||
add eax,1800
|
||||
mov npcLife3D[ebx].remaining,eax
|
||||
mov npcLife3D[ebx].routeStep,esi
|
||||
mov npcLife3D[ebx].routeStep,0
|
||||
mov npcLife3D[ebx].pathCount,0
|
||||
mov npcLife3D[ebx].remainder,0
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
|
|
@ -19,30 +20,29 @@ npc_life_init:
|
|||
mov npcWalkVelocityX3D[esi*4],0
|
||||
mov npcWalkVelocityY3D[esi*4],0
|
||||
mov npcRise3D[esi*4],0
|
||||
mov npcSitTime3D[esi*4],0
|
||||
mov eax,npcStartDest3D[esi*4]
|
||||
mov npcLife3D[ebx].destination,eax
|
||||
imul edi,esi,SIZEOF NpcMindEntity
|
||||
push eax
|
||||
invoke NpcEntity3D,esi
|
||||
mov edi,eax
|
||||
pop eax
|
||||
mov ecx,npcDestX3D[eax*4]
|
||||
mov casinoNpcs3D[edi].posX,ecx
|
||||
mov [edi].NpcMindEntity.posX,ecx
|
||||
mov ecx,npcDestY3D[eax*4]
|
||||
mov casinoNpcs3D[edi].posY,ecx
|
||||
cmp eax,7
|
||||
je @F
|
||||
cmp eax,8
|
||||
jne npc_life_init_next
|
||||
@@:
|
||||
mov npcLife3D[ebx].state,NPC_SIT
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
mov [edi].NpcMindEntity.posY,ecx
|
||||
npc_life_init_next:
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
jb npc_life_init
|
||||
call InitNpcVisits3D
|
||||
mov npcLifeReady3D,1
|
||||
ret
|
||||
InitNpcLife3D ENDP
|
||||
|
||||
; BFS visits each tile at most once. Body clearance includes furniture and the stage.
|
||||
NpcTryCell3D PROC uses ebx esi cell:DWORD,parent:DWORD
|
||||
NpcTryCell3D PROC uses ebx esi edi cell:DWORD,parent:DWORD
|
||||
local startX:DWORD,startY:DWORD,endX:DWORD,endY:DWORD,probeX:DWORD
|
||||
mov esi,cell
|
||||
cmp esi,NPC_PATH_CAP
|
||||
jae npc_cell_done
|
||||
|
|
@ -56,9 +56,41 @@ NpcTryCell3D PROC uses ebx esi cell:DWORD,parent:DWORD
|
|||
shr edx,5
|
||||
shl edx,16
|
||||
add edx,FP_HALF
|
||||
mov endX,eax
|
||||
mov endY,edx
|
||||
invoke CanWalk3D,eax,edx
|
||||
test eax,eax
|
||||
jz npc_cell_done
|
||||
; Free tile centres do not imply a free edge beside a chair or thin divider.
|
||||
mov eax,parent
|
||||
mov edx,eax
|
||||
and eax,31
|
||||
shl eax,16
|
||||
add eax,FP_HALF
|
||||
mov startX,eax
|
||||
shr edx,5
|
||||
shl edx,16
|
||||
add edx,FP_HALF
|
||||
mov startY,edx
|
||||
mov edi,1
|
||||
npc_cell_edge:
|
||||
mov eax,endX
|
||||
sub eax,startX
|
||||
imul eax,edi
|
||||
sar eax,2
|
||||
add eax,startX
|
||||
mov probeX,eax
|
||||
mov eax,endY
|
||||
sub eax,startY
|
||||
imul eax,edi
|
||||
sar eax,2
|
||||
add eax,startY
|
||||
invoke CanWalk3D,probeX,eax
|
||||
test eax,eax
|
||||
jz npc_cell_done
|
||||
inc edi
|
||||
cmp edi,4
|
||||
jb npc_cell_edge
|
||||
mov eax,parent
|
||||
mov npcParents3D[esi*4],eax
|
||||
mov ebx,npcSearchTail3D
|
||||
|
|
@ -78,11 +110,12 @@ NpcPlanPath3D PROC uses ebx esi edi slot:DWORD,destination:DWORD
|
|||
jae npc_plan_fail
|
||||
imul ebx,slot,SIZEOF NpcLife3D
|
||||
mov npcLife3D[ebx].pathCount,0
|
||||
imul esi,slot,SIZEOF NpcMindEntity
|
||||
mov eax,casinoNpcs3D[esi].posY
|
||||
invoke NpcEntity3D,slot
|
||||
mov esi,eax
|
||||
mov eax,[esi].NpcMindEntity.posY
|
||||
sar eax,16
|
||||
shl eax,5
|
||||
mov ecx,casinoNpcs3D[esi].posX
|
||||
mov ecx,[esi].NpcMindEntity.posX
|
||||
sar ecx,16
|
||||
add eax,ecx
|
||||
cmp eax,NPC_PATH_CAP
|
||||
|
|
@ -190,16 +223,17 @@ npc_space_person:
|
|||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
cmp npcLife3D[ebx].state,NPC_AWAY
|
||||
je npc_space_next
|
||||
imul ebx,esi,SIZEOF NpcMindEntity
|
||||
invoke NpcEntity3D,esi
|
||||
mov ebx,eax
|
||||
mov eax,px
|
||||
sub eax,casinoNpcs3D[ebx].posX
|
||||
sub eax,[ebx].NpcMindEntity.posX
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
cmp eax,FP_1*2/5
|
||||
jae npc_space_next
|
||||
mov eax,py
|
||||
sub eax,casinoNpcs3D[ebx].posY
|
||||
sub eax,[ebx].NpcMindEntity.posY
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
|
|
@ -222,8 +256,8 @@ NpcMove3D PROC uses ebx esi edi slot:DWORD,milliseconds:DWORD
|
|||
local budget:DWORD,wx:DWORD,wy:DWORD,mind:DWORD,pathBase:DWORD
|
||||
local oldX:DWORD,oldY:DWORD
|
||||
imul ebx,slot,SIZEOF NpcLife3D
|
||||
imul eax,slot,SIZEOF NpcMindEntity
|
||||
lea esi,casinoNpcs3D[eax]
|
||||
invoke NpcEntity3D,slot
|
||||
mov esi,eax
|
||||
mov mind,esi
|
||||
mov eax,[esi].NpcMindEntity.posX
|
||||
mov oldX,eax
|
||||
|
|
@ -234,7 +268,8 @@ NpcMove3D PROC uses ebx esi edi slot:DWORD,milliseconds:DWORD
|
|||
add eax,OFFSET npcPaths3D
|
||||
mov pathBase,eax
|
||||
mov eax,milliseconds
|
||||
mov ecx,55000
|
||||
mov ecx,slot
|
||||
mov ecx,npcVisitSpeed3D[ecx*4]
|
||||
mul ecx
|
||||
add eax,npcLife3D[ebx].remainder
|
||||
adc edx,0
|
||||
|
|
@ -338,28 +373,26 @@ npc_move_y:
|
|||
cmp npcLife3D[ebx].pathCount,0
|
||||
jne npc_move_done
|
||||
npc_move_arrived:
|
||||
mov eax,npcLife3D[ebx].destination
|
||||
mov npcLife3D[ebx].state,NPC_STAND
|
||||
mov npcLife3D[ebx].remaining,3500
|
||||
cmp eax,0
|
||||
jne @F
|
||||
mov npcLife3D[ebx].state,NPC_AWAY
|
||||
mov npcLife3D[ebx].remaining,4500
|
||||
jmp npc_move_done
|
||||
@@:
|
||||
cmp eax,7
|
||||
je @F
|
||||
cmp eax,8
|
||||
jne npc_move_done
|
||||
@@:
|
||||
mov npcLife3D[ebx].state,NPC_SIT
|
||||
mov npcLife3D[ebx].remaining,12000
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
invoke NpcArrive3D,slot
|
||||
jmp npc_move_done
|
||||
npc_move_blocked:
|
||||
mov eax,slot
|
||||
add npcVisitBlocked3D[eax*4],250
|
||||
cmp npcVisitBlocked3D[eax*4],2000
|
||||
jae npc_move_abandon
|
||||
mov npcLife3D[ebx].state,NPC_STAND
|
||||
mov npcVisitActivity3D[eax*4],NV_YIELD
|
||||
imul eax,23
|
||||
add eax,200
|
||||
mov npcLife3D[ebx].remaining,eax
|
||||
jmp npc_move_done
|
||||
npc_move_abandon:
|
||||
invoke NpcReleaseStation3D,slot
|
||||
mov npcLife3D[ebx].state,NPC_STAND
|
||||
mov npcLife3D[ebx].remaining,1000
|
||||
mov npcLife3D[ebx].pathCount,0
|
||||
mov eax,slot
|
||||
mov npcVisitActivity3D[eax*4],NV_IDLE
|
||||
npc_move_done:
|
||||
; Advance gait by successful displacement only, including partial blocked steps.
|
||||
mov esi,mind
|
||||
|
|
@ -372,6 +405,7 @@ npc_move_done:
|
|||
mov edi,eax
|
||||
or eax,ecx
|
||||
jz npc_move_no_stride
|
||||
mov npcVisitBlocked3D[ebx*4],0
|
||||
mov npcWalkVelocityX3D[ebx*4],ecx
|
||||
mov npcWalkVelocityY3D[ebx*4],edi
|
||||
mov eax,ecx
|
||||
|
|
@ -389,16 +423,25 @@ npc_move_done:
|
|||
mov ecx,FP_1*3/4
|
||||
div ecx
|
||||
mov npcWalkDistance3D[ebx*4],edx
|
||||
imul eax,ebx,SIZEOF NpcLife3D
|
||||
cmp npcLife3D[eax].state,NPC_WALK
|
||||
jne npc_move_no_stride
|
||||
ret
|
||||
npc_move_no_stride:
|
||||
mov eax,slot
|
||||
mov npcWalkVelocityX3D[eax*4],0
|
||||
mov npcWalkVelocityY3D[eax*4],0
|
||||
ret
|
||||
NpcMove3D ENDP
|
||||
|
||||
UpdateNpcLife3D PROC uses ebx esi edi
|
||||
local milliseconds:DWORD,destination:DWORD
|
||||
local milliseconds:DWORD
|
||||
cmp npcLifeReady3D,1
|
||||
jne npc_update_done
|
||||
cmp hallLevel3D,0
|
||||
jne npc_update_done
|
||||
cmp engineMode,MODE_WALK
|
||||
jne npc_update_done
|
||||
mov eax,deltaTime3D
|
||||
cmp eax,250
|
||||
jbe @F
|
||||
|
|
@ -411,6 +454,20 @@ npc_update_person:
|
|||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov eax,milliseconds
|
||||
add npcLife3D[ebx].poseClock,eax
|
||||
sub npcRemarkTime3D[esi*4],eax
|
||||
jns @F
|
||||
mov npcRemarkTime3D[esi*4],0
|
||||
@@:
|
||||
cmp npcLife3D[ebx].state,NPC_SIT
|
||||
jne npc_update_seat_ready
|
||||
mov ecx,npcSitTime3D[esi*4]
|
||||
add ecx,eax
|
||||
cmp ecx,800
|
||||
jbe @F
|
||||
mov ecx,800
|
||||
@@:
|
||||
mov npcSitTime3D[esi*4],ecx
|
||||
npc_update_seat_ready:
|
||||
cmp npcLife3D[ebx].state,NPC_WALK
|
||||
jne npc_update_wait
|
||||
cmp npcRise3D[esi*4],0
|
||||
|
|
@ -425,51 +482,23 @@ npc_update_move:
|
|||
npc_update_wait:
|
||||
sub npcLife3D[ebx].remaining,eax
|
||||
ja npc_update_sync
|
||||
cmp npcLife3D[ebx].state,NPC_AWAY
|
||||
jne npc_update_choose
|
||||
mov eax,npcLife3D[ebx].identity
|
||||
add eax,6
|
||||
cmp eax,NPC_IDENTITY_COUNT
|
||||
jb @F
|
||||
sub eax,NPC_IDENTITY_COUNT
|
||||
@@:
|
||||
mov npcLife3D[ebx].identity,eax
|
||||
mov npcLife3D[ebx].state,NPC_STAND
|
||||
npc_update_choose:
|
||||
mov eax,npcLife3D[ebx].routeStep
|
||||
xor edx,edx
|
||||
mov ecx,NPC_DEST_COUNT
|
||||
div ecx
|
||||
mov eax,npcVisitRoute3D[edx*4]
|
||||
mov destination,eax
|
||||
inc npcLife3D[ebx].routeStep
|
||||
mov npcRise3D[esi*4],0
|
||||
cmp npcLife3D[ebx].state,NPC_SIT
|
||||
jne @F
|
||||
mov npcRise3D[esi*4],800
|
||||
@@:
|
||||
invoke NpcPlanPath3D,esi,destination
|
||||
test eax,eax
|
||||
jz npc_update_retry
|
||||
mov npcLife3D[ebx].state,NPC_WALK
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
jmp npc_update_sync
|
||||
npc_update_retry:
|
||||
mov npcRise3D[esi*4],0
|
||||
mov npcLife3D[ebx].state,NPC_STAND
|
||||
mov npcLife3D[ebx].remaining,1000
|
||||
invoke NpcAdvanceVisit3D,esi
|
||||
npc_update_sync:
|
||||
imul edi,esi,SIZEOF NpcMindEntity
|
||||
invoke NpcEntity3D,esi
|
||||
mov edi,eax
|
||||
mov eax,npcLife3D[ebx].state
|
||||
mov casinoNpcs3D[edi].state,eax
|
||||
mov [edi].NpcMindEntity.state,eax
|
||||
mov eax,npcLife3D[ebx].remaining
|
||||
mov casinoNpcs3D[edi].stateTimer,eax
|
||||
mov [edi].NpcMindEntity.stateTimer,eax
|
||||
; Keep the old public position array coherent for existing world checks.
|
||||
cmp esi,6
|
||||
jae npc_update_sync_next
|
||||
imul ecx,esi,SIZEOF CityProp3D
|
||||
mov eax,casinoNpcs3D[edi].posX
|
||||
mov eax,[edi].NpcMindEntity.posX
|
||||
mov hallGuests3D[ecx].posX,eax
|
||||
mov eax,casinoNpcs3D[edi].posY
|
||||
mov eax,[edi].NpcMindEntity.posY
|
||||
mov hallGuests3D[ecx].posY,eax
|
||||
npc_update_sync_next:
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
jb npc_update_person
|
||||
|
|
@ -483,8 +512,9 @@ RenderNpcLife3D PROC uses ebx esi edi
|
|||
jne npc_draw_done
|
||||
xor esi,esi
|
||||
npc_draw_depth:
|
||||
imul ebx,esi,SIZEOF NpcMindEntity
|
||||
invoke ProjectCityPoint3D,casinoNpcs3D[ebx].posX,casinoNpcs3D[ebx].posY
|
||||
invoke NpcEntity3D,esi
|
||||
mov ebx,eax
|
||||
invoke ProjectCityPoint3D,[ebx].NpcMindEntity.posX,[ebx].NpcMindEntity.posY
|
||||
mov npcDrawDepth3D[esi*4],edx
|
||||
mov npcDrawOrder3D[esi*4],esi
|
||||
inc esi
|
||||
|
|
@ -514,24 +544,29 @@ npc_draw_person:
|
|||
imul ebx,eax,SIZEOF NpcLife3D
|
||||
cmp npcLife3D[ebx].state,NPC_AWAY
|
||||
je npc_draw_next
|
||||
imul edi,eax,SIZEOF NpcMindEntity
|
||||
mov eax,casinoNpcs3D[edi].posX
|
||||
invoke NpcEntity3D,eax
|
||||
mov edi,eax
|
||||
mov eax,[edi].NpcMindEntity.posX
|
||||
mov npcSprite3D.posX,eax
|
||||
mov eax,casinoNpcs3D[edi].posY
|
||||
mov eax,[edi].NpcMindEntity.posY
|
||||
mov npcSprite3D.posY,eax
|
||||
mov eax,npcLife3D[ebx].identity
|
||||
mov eax,npcGuestAppearance3D[eax*4]
|
||||
mov castId,eax
|
||||
mov castAction,CAST_TALK
|
||||
mov castAction,CAST_IDLE
|
||||
mov eax,npcLife3D[ebx].poseClock
|
||||
mov castClock,eax
|
||||
mov eax,npcDrawOrder3D[esi*4]
|
||||
mov slot,eax
|
||||
invoke NpcResolveVisitPose3D,eax
|
||||
mov castAction,eax
|
||||
cmp npcLife3D[ebx].state,NPC_SIT
|
||||
jne npc_draw_walk
|
||||
mov castAction,CAST_SEAT_TALK
|
||||
cmp castClock,800
|
||||
mov eax,slot
|
||||
mov eax,npcSitTime3D[eax*4]
|
||||
cmp eax,800
|
||||
jae npc_draw_sprite
|
||||
mov castClock,eax
|
||||
mov castAction,CAST_SIT_DOWN
|
||||
jmp npc_draw_sprite
|
||||
npc_draw_walk:
|
||||
|
|
@ -546,6 +581,9 @@ npc_draw_walk:
|
|||
mov castClock,eax
|
||||
jmp npc_draw_sprite
|
||||
npc_draw_moving:
|
||||
mov eax,npcWalkVelocityX3D[ebx*4]
|
||||
or eax,npcWalkVelocityY3D[ebx*4]
|
||||
jz npc_draw_sprite
|
||||
mov castAction,CAST_WALK
|
||||
mov eax,npcWalkDistance3D[ebx*4]
|
||||
mov castClock,eax
|
||||
|
|
@ -553,6 +591,7 @@ npc_draw_sprite:
|
|||
mov ebx,slot
|
||||
invoke ConfigureCharacter3D,OFFSET npcSprite3D,castId,castAction,castClock,npcWalkVelocityX3D[ebx*4],npcWalkVelocityY3D[ebx*4]
|
||||
invoke DrawCityObject3D,OFFSET npcSprite3D,0
|
||||
invoke NpcDrawRemark3D,slot
|
||||
npc_draw_next:
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
|
|
@ -576,14 +615,15 @@ npc_interact_person:
|
|||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
cmp npcLife3D[ebx].state,NPC_AWAY
|
||||
je npc_interact_next
|
||||
imul edi,esi,SIZEOF NpcMindEntity
|
||||
mov eax,casinoNpcs3D[edi].posX
|
||||
invoke NpcEntity3D,esi
|
||||
mov edi,eax
|
||||
mov eax,[edi].NpcMindEntity.posX
|
||||
sub eax,playerX
|
||||
sar eax,8
|
||||
mov deltaX,eax
|
||||
imul eax,eax
|
||||
mov distance,eax
|
||||
mov eax,casinoNpcs3D[edi].posY
|
||||
mov eax,[edi].NpcMindEntity.posY
|
||||
sub eax,playerY
|
||||
sar eax,8
|
||||
mov deltaY,eax
|
||||
|
|
@ -640,3 +680,5 @@ npc_interact_next:
|
|||
npc_interact_done:
|
||||
ret
|
||||
CheckNpcInteractions3D ENDP
|
||||
|
||||
include src_graphics\npc_visits.inc
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ IFDEF CASINO_ACTION_TEST
|
|||
DeleteFileA PROTO :DWORD
|
||||
ENDIF
|
||||
INTERACT_NPC equ 40
|
||||
NPC_LIFE_COUNT equ 6
|
||||
NPC_LIFE_COUNT equ 10
|
||||
NPC_IDENTITY_COUNT equ 12
|
||||
NPC_DEST_COUNT equ 10
|
||||
NPC_DEST_COUNT equ 12
|
||||
NPC_STAND equ 0
|
||||
NPC_WALK equ 1
|
||||
NPC_SIT equ 2
|
||||
|
|
@ -23,6 +23,16 @@ NpcPlanPath3D PROTO :DWORD,:DWORD
|
|||
NpcTryCell3D PROTO :DWORD,:DWORD
|
||||
NpcMove3D PROTO :DWORD,:DWORD
|
||||
NpcCanStep3D PROTO :DWORD,:DWORD,:DWORD
|
||||
NpcEntity3D PROTO :DWORD
|
||||
InitNpcVisits3D PROTO
|
||||
NpcArrive3D PROTO :DWORD
|
||||
NpcChooseVisit3D PROTO :DWORD
|
||||
NpcAdvanceVisit3D PROTO :DWORD
|
||||
NpcResolveVisitPose3D PROTO :DWORD
|
||||
NpcSeatOffset3D PROTO :DWORD
|
||||
NpcVisitRandom3D PROTO :DWORD,:DWORD
|
||||
NpcReleaseStation3D PROTO :DWORD
|
||||
NpcDrawRemark3D PROTO :DWORD
|
||||
NpcRecordRound3D PROTO :DWORD,:DWORD
|
||||
NpcEnsureJournal3D PROTO
|
||||
NpcSaveJournal3D PROTO
|
||||
|
|
@ -43,6 +53,9 @@ NpcLife3D STRUCT
|
|||
NpcLife3D ENDS
|
||||
.data
|
||||
npcLife3D NpcLife3D NPC_LIFE_COUNT dup(<>)
|
||||
; The original six poker-mind records retain their layout and profile range.
|
||||
npcExtraActors3D NpcMindEntity 4 dup(<>)
|
||||
npcInitialIdentity3D dd 0,1,2,3,4,5,6,7,9,10
|
||||
npcLifeReady3D dd 0
|
||||
npcGuestArt3D AnimPack3D <>
|
||||
npcGuestPath3D db "assets\animations\hall\guest-cast-v1.bin",0
|
||||
|
|
@ -55,6 +68,7 @@ npcWalkVelocityX3D dd NPC_LIFE_COUNT dup(0)
|
|||
npcWalkVelocityY3D dd NPC_LIFE_COUNT dup(0)
|
||||
; Keep the twelve-slot historical journal, but resolve every appearance to the shared ten.
|
||||
npcRise3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcSitTime3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcGuestAppearance3D dd 0,2,4,1,3,5,6,8,0,7,9,2
|
||||
npcGuestNames3D dd OFFSET npcName0,OFFSET npcName1,OFFSET npcName2,OFFSET npcGuestAnna3D
|
||||
dd OFFSET npcGuestMarina3D,OFFSET npcGuestVera3D,OFFSET npcName6,OFFSET npcName7
|
||||
|
|
@ -71,11 +85,12 @@ npcDialogError3D dd 0
|
|||
npcNameBuffer3D db 64 dup(0)
|
||||
npcJournalIoError3D dd 0
|
||||
npcDestX3D dd 16*FP_1+FP_HALF,16*FP_1+FP_HALF,10*FP_1+FP_HALF,6*FP_1+FP_HALF,13*FP_1+FP_HALF
|
||||
dd 21*FP_1+FP_HALF,7*FP_1+FP_HALF,6*FP_1+FP_HALF,16*FP_1+FP_HALF,16*FP_1+FP_HALF
|
||||
dd 21*FP_1+FP_HALF,7*FP_1+FP_HALF,13*FP_1+FP_HALF,16*FP_1+FP_HALF,19*FP_1+FP_HALF
|
||||
dd 6*FP_1+FP_HALF,15*FP_1+FP_HALF
|
||||
npcDestY3D dd 28*FP_1+FP_HALF,17*FP_1+FP_HALF,13*FP_1+FP_HALF,14*FP_1+FP_HALF,9*FP_1+FP_HALF
|
||||
dd 10*FP_1+FP_HALF,25*FP_1+FP_HALF,27*FP_1+FP_HALF,10*FP_1+FP_HALF,7*FP_1+FP_HALF
|
||||
npcVisitRoute3D dd 1,5,8,2,3,6,7,9,1,0
|
||||
npcStartDest3D dd 1,2,3,6,8,7
|
||||
dd 10*FP_1+FP_HALF,25*FP_1+FP_HALF,19*FP_1+FP_HALF,10*FP_1+FP_HALF,10*FP_1+FP_HALF
|
||||
dd 25*FP_1+FP_HALF,19*FP_1+FP_HALF
|
||||
npcStartDest3D dd 1,2,3,6,8,7,4,5,9,11
|
||||
npcSprite3D CityProp3D <0,0,FP_1*3/5,FP_1*6/5,0,OFFSET hallPatrons3D>
|
||||
npcDrawOrder3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcDrawDepth3D dd NPC_LIFE_COUNT dup(0)
|
||||
|
|
@ -91,7 +106,7 @@ npcJournalBasePtr3D dd 0
|
|||
ENDIF
|
||||
npcDateOverride3D dd 0
|
||||
npcSystemTime3D dw 8 dup(0)
|
||||
; One bounded journal per profile; visitors 0..5 and 6..11 alternate at the entrance.
|
||||
; Retain the twelve historical journal entries for existing saves and contracts.
|
||||
npcJournal3D LABEL DWORD
|
||||
npcJournalMagic3D dd 3151504Eh
|
||||
npcJournalDay3D dd 0
|
||||
|
|
@ -157,4 +172,5 @@ npcQueue3D dd NPC_PATH_CAP dup(?)
|
|||
npcSearchHead3D dd 0
|
||||
npcSearchTail3D dd 0
|
||||
npcSearchGoal3D dd 0
|
||||
include src_graphics\npc_visits_data.inc
|
||||
.code
|
||||
|
|
|
|||
511
src_graphics/npc_visits.inc
Normal file
511
src_graphics/npc_visits.inc
Normal file
|
|
@ -0,0 +1,511 @@
|
|||
; Four additional visitors do not expand the six legacy poker personality records.
|
||||
NpcEntity3D PROC slot:DWORD
|
||||
mov eax,slot
|
||||
cmp eax,6
|
||||
jae nv_entity_extra
|
||||
imul eax,SIZEOF NpcMindEntity
|
||||
add eax,OFFSET casinoNpcs3D
|
||||
ret
|
||||
nv_entity_extra:
|
||||
sub eax,6
|
||||
imul eax,SIZEOF NpcMindEntity
|
||||
add eax,OFFSET npcExtraActors3D
|
||||
ret
|
||||
NpcEntity3D ENDP
|
||||
|
||||
NpcVisitRandom3D PROC slot:DWORD,limit:DWORD
|
||||
mov ecx,slot
|
||||
mov eax,npcVisitRng3D[ecx*4]
|
||||
imul eax,1664525
|
||||
add eax,1013904223
|
||||
mov npcVisitRng3D[ecx*4],eax
|
||||
shr eax,8
|
||||
xor edx,edx
|
||||
div limit
|
||||
mov eax,edx
|
||||
ret
|
||||
NpcVisitRandom3D ENDP
|
||||
|
||||
InitNpcVisits3D PROC uses ebx esi edi
|
||||
lea edi,npcStationOwner3D
|
||||
mov ecx,NPC_DEST_COUNT
|
||||
mov eax,-1
|
||||
rep stosd
|
||||
xor esi,esi
|
||||
nv_init_person:
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
imul eax,esi,7919
|
||||
add eax,071C4A931h
|
||||
mov npcVisitRng3D[esi*4],eax
|
||||
mov eax,npcVisitInitialChips3D[esi*4]
|
||||
mov npcVisitChips3D[esi*4],eax
|
||||
mov npcVisitRounds3D[esi*4],0
|
||||
mov npcVisitThirst3D[esi*4],0
|
||||
mov npcVisitMood3D[esi*4],0
|
||||
mov npcVisitBlocked3D[esi*4],0
|
||||
mov npcRemark3D[esi*4],0
|
||||
mov npcRemarkTime3D[esi*4],0
|
||||
mov eax,npcLife3D[ebx].destination
|
||||
mov npcStationOwner3D[eax*4],esi
|
||||
invoke NpcArrive3D,esi
|
||||
; Different initial waits prevent a synchronized crowd surge.
|
||||
imul eax,esi,1100
|
||||
add npcLife3D[ebx].remaining,eax
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
jb nv_init_person
|
||||
ret
|
||||
InitNpcVisits3D ENDP
|
||||
|
||||
NpcReleaseStation3D PROC uses esi slot:DWORD
|
||||
xor esi,esi
|
||||
nv_release_station:
|
||||
mov eax,slot
|
||||
cmp npcStationOwner3D[esi*4],eax
|
||||
jne @F
|
||||
mov npcStationOwner3D[esi*4],-1
|
||||
@@:
|
||||
inc esi
|
||||
cmp esi,NPC_DEST_COUNT
|
||||
jb nv_release_station
|
||||
ret
|
||||
NpcReleaseStation3D ENDP
|
||||
|
||||
NpcArrive3D PROC uses ebx esi slot:DWORD
|
||||
mov esi,slot
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov npcLife3D[ebx].state,NPC_STAND
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
mov npcSitTime3D[esi*4],0
|
||||
mov npcRemark3D[esi*4],0
|
||||
mov npcRemarkTime3D[esi*4],0
|
||||
mov npcVisitBlocked3D[esi*4],0
|
||||
mov npcVisitRounds3D[esi*4],0
|
||||
mov eax,npcLife3D[ebx].destination
|
||||
mov ecx,npcStationKind3D[eax*4]
|
||||
mov npcVisitActivity3D[esi*4],ecx
|
||||
cmp ecx,NV_LEAVE
|
||||
jne @F
|
||||
invoke NpcReleaseStation3D,esi
|
||||
mov npcLife3D[ebx].state,NPC_AWAY
|
||||
mov npcLife3D[ebx].remaining,8000
|
||||
ret
|
||||
@@:
|
||||
cmp ecx,NV_ORDER
|
||||
jne @F
|
||||
mov npcLife3D[ebx].remaining,2400
|
||||
mov npcRemark3D[esi*4],OFFSET npcRemarkOrder3D
|
||||
mov npcRemarkTime3D[esi*4],2200
|
||||
ret
|
||||
@@:
|
||||
cmp ecx,NV_REST
|
||||
jne @F
|
||||
mov npcLife3D[ebx].state,NPC_SIT
|
||||
invoke NpcVisitRandom3D,esi,9000
|
||||
add eax,14000
|
||||
mov npcLife3D[ebx].remaining,eax
|
||||
ret
|
||||
@@:
|
||||
cmp ecx,NV_WATCH
|
||||
jne @F
|
||||
invoke NpcVisitRandom3D,esi,10000
|
||||
add eax,12000
|
||||
mov npcLife3D[ebx].remaining,eax
|
||||
ret
|
||||
@@:
|
||||
invoke NpcVisitRandom3D,esi,1800
|
||||
add eax,2200
|
||||
mov npcLife3D[ebx].remaining,eax
|
||||
ret
|
||||
NpcArrive3D ENDP
|
||||
|
||||
; Reserve a free destination before walking; neither a failed path nor a blocked
|
||||
; walker keeps a permanent claim on furniture. Casino RNG and bankroll are unused.
|
||||
NpcChooseVisit3D PROC uses ebx esi edi slot:DWORD
|
||||
local candidate:DWORD,wasSeated:DWORD,attempt:DWORD
|
||||
mov esi,slot
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov eax,npcLife3D[ebx].state
|
||||
mov wasSeated,eax
|
||||
mov attempt,0
|
||||
nv_choose_candidate:
|
||||
cmp npcVisitChips3D[esi*4],20
|
||||
jae nv_choose_thirst
|
||||
mov candidate,0
|
||||
jmp nv_choose_free
|
||||
nv_choose_thirst:
|
||||
cmp npcVisitMood3D[esi*4],-2
|
||||
jle nv_choose_break
|
||||
cmp npcVisitThirst3D[esi*4],3
|
||||
jb nv_choose_random
|
||||
nv_choose_break:
|
||||
mov eax,6
|
||||
test attempt,1
|
||||
jz @F
|
||||
mov eax,10
|
||||
@@:
|
||||
mov candidate,eax
|
||||
cmp attempt,2
|
||||
jb nv_choose_free
|
||||
nv_choose_random:
|
||||
invoke NpcVisitRandom3D,esi,100
|
||||
cmp eax,45
|
||||
jae nv_choose_bar
|
||||
mov eax,npcVisitFavourite3D[esi*4]
|
||||
mov candidate,eax
|
||||
cmp attempt,0
|
||||
je nv_choose_free
|
||||
invoke NpcVisitRandom3D,esi,5
|
||||
inc eax
|
||||
mov candidate,eax
|
||||
jmp nv_choose_free
|
||||
nv_choose_bar:
|
||||
cmp eax,65
|
||||
jae nv_choose_rest
|
||||
invoke NpcVisitRandom3D,esi,2
|
||||
imul eax,4
|
||||
add eax,6
|
||||
mov candidate,eax
|
||||
jmp nv_choose_free
|
||||
nv_choose_rest:
|
||||
cmp eax,83
|
||||
jae nv_choose_watch
|
||||
invoke NpcVisitRandom3D,esi,2
|
||||
imul eax,4
|
||||
add eax,7
|
||||
mov candidate,eax
|
||||
jmp nv_choose_free
|
||||
nv_choose_watch:
|
||||
invoke NpcVisitRandom3D,esi,2
|
||||
add eax,8
|
||||
mov candidate,eax
|
||||
nv_choose_free:
|
||||
mov edi,candidate
|
||||
cmp edi,npcLife3D[ebx].destination
|
||||
je nv_choose_next
|
||||
cmp npcStationOwner3D[edi*4],-1
|
||||
jne nv_choose_next
|
||||
invoke NpcPlanPath3D,esi,edi
|
||||
test eax,eax
|
||||
jz nv_choose_next
|
||||
invoke NpcReleaseStation3D,esi
|
||||
mov npcStationOwner3D[edi*4],esi
|
||||
mov npcLife3D[ebx].state,NPC_WALK
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
mov npcVisitActivity3D[esi*4],NV_IDLE
|
||||
mov npcRise3D[esi*4],0
|
||||
cmp wasSeated,NPC_SIT
|
||||
jne @F
|
||||
mov npcRise3D[esi*4],800
|
||||
@@:
|
||||
inc npcLife3D[ebx].routeStep
|
||||
mov eax,1
|
||||
ret
|
||||
nv_choose_next:
|
||||
inc attempt
|
||||
cmp attempt,16
|
||||
jb nv_choose_candidate
|
||||
; Keep a seated visitor seated when all useful destinations are busy.
|
||||
mov eax,wasSeated
|
||||
cmp eax,NPC_AWAY
|
||||
jne @F
|
||||
mov eax,NPC_STAND
|
||||
@@:
|
||||
mov npcLife3D[ebx].state,eax
|
||||
mov npcLife3D[ebx].remaining,1800
|
||||
xor eax,eax
|
||||
ret
|
||||
NpcChooseVisit3D ENDP
|
||||
|
||||
NpcAdvanceVisit3D PROC uses ebx esi edi slot:DWORD
|
||||
mov esi,slot
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov eax,npcVisitActivity3D[esi*4]
|
||||
cmp eax,NV_YIELD
|
||||
jne @F
|
||||
mov npcLife3D[ebx].state,NPC_WALK
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
ret
|
||||
@@:
|
||||
cmp eax,NV_GAME
|
||||
je nv_play_result
|
||||
cmp eax,NV_WIN
|
||||
je nv_after_result
|
||||
cmp eax,NV_LOSS
|
||||
je nv_after_result
|
||||
cmp eax,NV_ORDER
|
||||
je nv_order_ready
|
||||
cmp eax,NV_DRINK
|
||||
je nv_social
|
||||
cmp eax,NV_REST
|
||||
je nv_social
|
||||
cmp eax,NV_LEAVE
|
||||
jne @F
|
||||
mov eax,npcVisitInitialChips3D[esi*4]
|
||||
mov npcVisitChips3D[esi*4],eax
|
||||
mov npcVisitMood3D[esi*4],0
|
||||
mov npcVisitThirst3D[esi*4],0
|
||||
@@:
|
||||
invoke NpcChooseVisit3D,esi
|
||||
ret
|
||||
nv_play_result:
|
||||
mov edi,npcVisitStake3D[esi*4]
|
||||
invoke NpcVisitRandom3D,esi,100
|
||||
cmp eax,42
|
||||
jae nv_play_loss
|
||||
add npcVisitChips3D[esi*4],edi
|
||||
cmp npcVisitMood3D[esi*4],3
|
||||
jge @F
|
||||
inc npcVisitMood3D[esi*4]
|
||||
@@:
|
||||
mov npcVisitActivity3D[esi*4],NV_WIN
|
||||
mov npcRemark3D[esi*4],OFFSET npcRemarkWin3D
|
||||
jmp nv_result_done
|
||||
nv_play_loss:
|
||||
sub npcVisitChips3D[esi*4],edi
|
||||
jns @F
|
||||
mov npcVisitChips3D[esi*4],0
|
||||
@@:
|
||||
cmp npcVisitMood3D[esi*4],-3
|
||||
jle @F
|
||||
dec npcVisitMood3D[esi*4]
|
||||
@@:
|
||||
mov npcVisitActivity3D[esi*4],NV_LOSS
|
||||
mov npcRemark3D[esi*4],OFFSET npcRemarkLoss3D
|
||||
nv_result_done:
|
||||
inc npcVisitRounds3D[esi*4]
|
||||
inc npcVisitThirst3D[esi*4]
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
mov npcLife3D[ebx].remaining,1800
|
||||
mov npcRemarkTime3D[esi*4],1800
|
||||
ret
|
||||
nv_after_result:
|
||||
cmp npcVisitMood3D[esi*4],-2
|
||||
jle nv_take_break
|
||||
mov eax,npcVisitRounds3D[esi*4]
|
||||
cmp eax,npcVisitSession3D[esi*4]
|
||||
jae nv_take_break
|
||||
mov eax,npcVisitStake3D[esi*4]
|
||||
cmp eax,npcVisitChips3D[esi*4]
|
||||
ja nv_take_break
|
||||
mov npcVisitActivity3D[esi*4],NV_GAME
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
invoke NpcVisitRandom3D,esi,1800
|
||||
add eax,2200
|
||||
mov npcLife3D[ebx].remaining,eax
|
||||
ret
|
||||
nv_take_break:
|
||||
mov npcRemark3D[esi*4],OFFSET npcRemarkBreak3D
|
||||
mov npcRemarkTime3D[esi*4],1600
|
||||
invoke NpcChooseVisit3D,esi
|
||||
ret
|
||||
nv_order_ready:
|
||||
sub npcVisitChips3D[esi*4],20
|
||||
jns @F
|
||||
mov npcVisitChips3D[esi*4],0
|
||||
@@:
|
||||
mov npcVisitThirst3D[esi*4],0
|
||||
mov npcVisitMood3D[esi*4],0
|
||||
mov npcVisitActivity3D[esi*4],NV_DRINK
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
mov npcLife3D[ebx].remaining,6500
|
||||
ret
|
||||
nv_social:
|
||||
cmp npcVisitMood3D[esi*4],0
|
||||
jge @F
|
||||
inc npcVisitMood3D[esi*4]
|
||||
@@:
|
||||
; Only chat when another stationary visitor is actually nearby.
|
||||
invoke NpcEntity3D,esi
|
||||
mov edi,eax
|
||||
xor ecx,ecx
|
||||
nv_social_find:
|
||||
cmp ecx,esi
|
||||
je nv_social_next
|
||||
push ecx
|
||||
invoke NpcEntity3D,ecx
|
||||
mov edx,[edi].NpcMindEntity.posX
|
||||
sub edx,[eax].NpcMindEntity.posX
|
||||
jns @F
|
||||
neg edx
|
||||
@@:
|
||||
cmp edx,FP_1*5/2
|
||||
ja nv_social_far
|
||||
mov edx,[edi].NpcMindEntity.posY
|
||||
sub edx,[eax].NpcMindEntity.posY
|
||||
jns @F
|
||||
neg edx
|
||||
@@:
|
||||
cmp edx,FP_1*5/2
|
||||
ja nv_social_far
|
||||
pop ecx
|
||||
imul eax,ecx,SIZEOF NpcLife3D
|
||||
cmp npcLife3D[eax].state,NPC_WALK
|
||||
je nv_social_next
|
||||
cmp npcLife3D[eax].state,NPC_AWAY
|
||||
je nv_social_next
|
||||
mov npcVisitActivity3D[esi*4],NV_CHAT
|
||||
mov npcLife3D[ebx].poseClock,0
|
||||
mov npcLife3D[ebx].remaining,6000
|
||||
mov npcRemark3D[esi*4],OFFSET npcRemarkChat3D
|
||||
mov npcRemarkTime3D[esi*4],1800
|
||||
ret
|
||||
nv_social_far:
|
||||
pop ecx
|
||||
nv_social_next:
|
||||
inc ecx
|
||||
cmp ecx,NPC_LIFE_COUNT
|
||||
jb nv_social_find
|
||||
invoke NpcChooseVisit3D,esi
|
||||
ret
|
||||
NpcAdvanceVisit3D ENDP
|
||||
|
||||
NpcResolveVisitPose3D PROC uses ebx esi slot:DWORD
|
||||
mov esi,slot
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov eax,npcLife3D[ebx].state
|
||||
cmp eax,NPC_SIT
|
||||
je nv_pose_seat
|
||||
cmp npcRise3D[esi*4],0
|
||||
jne nv_pose_rising
|
||||
mov eax,npcVisitActivity3D[esi*4]
|
||||
cmp eax,NV_WIN
|
||||
je nv_pose_cheer
|
||||
cmp eax,NV_DRINK
|
||||
je nv_pose_drink
|
||||
cmp eax,NV_CHAT
|
||||
je nv_pose_talk
|
||||
cmp eax,NV_ORDER
|
||||
je nv_pose_talk
|
||||
mov eax,CAST_IDLE
|
||||
ret
|
||||
nv_pose_cheer:
|
||||
mov eax,CAST_CHEER
|
||||
ret
|
||||
nv_pose_drink:
|
||||
mov eax,CAST_DRINK
|
||||
ret
|
||||
nv_pose_talk:
|
||||
mov eax,CAST_TALK
|
||||
ret
|
||||
nv_pose_seat:
|
||||
invoke NpcSeatOffset3D,npcSitTime3D[esi*4]
|
||||
mov eax,CAST_SEAT
|
||||
cmp npcVisitActivity3D[esi*4],NV_CHAT
|
||||
jne @F
|
||||
mov eax,CAST_SEAT_TALK
|
||||
@@:
|
||||
ret
|
||||
nv_pose_rising:
|
||||
invoke NpcSeatOffset3D,npcRise3D[esi*4]
|
||||
mov eax,CAST_IDLE
|
||||
ret
|
||||
NpcResolveVisitPose3D ENDP
|
||||
|
||||
; Smoothstep into/out of the existing seat anchor. Activity clocks cannot replay it.
|
||||
NpcSeatOffset3D PROC uses ebx milliseconds:DWORD
|
||||
mov eax,milliseconds
|
||||
cmp eax,800
|
||||
jb nv_seat_fraction
|
||||
mov eax,FP_1
|
||||
jmp nv_seat_offset
|
||||
nv_seat_fraction:
|
||||
shl eax,16
|
||||
xor edx,edx
|
||||
mov ecx,800
|
||||
div ecx
|
||||
mov ebx,eax
|
||||
imul eax
|
||||
shrd eax,edx,16
|
||||
mov ecx,3*FP_1
|
||||
sub ecx,ebx
|
||||
sub ecx,ebx
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
nv_seat_offset:
|
||||
mov ebx,eax
|
||||
mov ecx,FP_HALF
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
sub npcSprite3D.posX,eax
|
||||
mov eax,ebx
|
||||
mov ecx,FP_1*35/100
|
||||
imul ecx
|
||||
shrd eax,edx,16
|
||||
sub npcSprite3D.posY,eax
|
||||
ret
|
||||
NpcSeatOffset3D ENDP
|
||||
|
||||
NpcDrawRemark3D PROC uses ebx esi edi slot:DWORD
|
||||
local px:DWORD,py:DWORD,depth:DWORD,boxW:DWORD,textPtr:DWORD
|
||||
mov esi,slot
|
||||
cmp npcRemarkTime3D[esi*4],0
|
||||
je nv_remark_done
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
cmp npcLife3D[ebx].state,NPC_WALK
|
||||
je nv_remark_done
|
||||
invoke ProjectCityPoint3D,npcSprite3D.posX,npcSprite3D.posY
|
||||
cmp edx,FP_1/2
|
||||
jle nv_remark_done
|
||||
cmp edx,5*FP_1
|
||||
jg nv_remark_done
|
||||
cmp eax,24
|
||||
jl nv_remark_done
|
||||
cmp eax,SCREEN_W-24
|
||||
jg nv_remark_done
|
||||
cmp edx,zBuffer[eax*4]
|
||||
jg nv_remark_done
|
||||
mov depth,edx
|
||||
mov px,eax
|
||||
mov eax,viewEye3D
|
||||
sub eax,CAST_HEIGHT
|
||||
imul eax,SCREEN_H
|
||||
cdq
|
||||
idiv depth
|
||||
add eax,viewHorizon3D
|
||||
sar eax,1
|
||||
sub eax,20
|
||||
cmp eax,22
|
||||
jl nv_remark_done
|
||||
cmp eax,194
|
||||
jg nv_remark_done
|
||||
mov py,eax
|
||||
mov edi,npcRemark3D[esi*4]
|
||||
test edi,edi
|
||||
jz nv_remark_done
|
||||
mov textPtr,edi
|
||||
xor ecx,ecx
|
||||
nv_remark_length:
|
||||
cmp BYTE PTR [edi+ecx],0
|
||||
je nv_remark_place
|
||||
inc ecx
|
||||
cmp ecx,24
|
||||
jb nv_remark_length
|
||||
ret
|
||||
nv_remark_place:
|
||||
lea ebx,[ecx*8+12]
|
||||
mov boxW,ebx
|
||||
shr ebx,1
|
||||
mov eax,px
|
||||
sar eax,1
|
||||
sub eax,ebx
|
||||
cmp eax,4
|
||||
jge @F
|
||||
mov eax,4
|
||||
@@:
|
||||
mov ecx,316
|
||||
sub ecx,boxW
|
||||
cmp eax,ecx
|
||||
jle @F
|
||||
mov eax,ecx
|
||||
@@:
|
||||
mov px,eax
|
||||
invoke DrawBoxBorder,px,py,boxW,18,00151D22h,00899599h,1
|
||||
mov eax,px
|
||||
add eax,6
|
||||
mov ecx,py
|
||||
add ecx,5
|
||||
invoke DrawString8x8,eax,ecx,textPtr,00E8D7ADh
|
||||
nv_remark_done:
|
||||
ret
|
||||
NpcDrawRemark3D ENDP
|
||||
35
src_graphics/npc_visits_data.inc
Normal file
35
src_graphics/npc_visits_data.inc
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
NV_IDLE equ 0
|
||||
NV_GAME equ 1
|
||||
NV_WIN equ 2
|
||||
NV_LOSS equ 3
|
||||
NV_ORDER equ 4
|
||||
NV_DRINK equ 5
|
||||
NV_REST equ 6
|
||||
NV_WATCH equ 7
|
||||
NV_CHAT equ 8
|
||||
NV_LEAVE equ 9
|
||||
NV_YIELD equ 10
|
||||
.data
|
||||
npcVisitActivity3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcVisitRng3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcVisitChips3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcVisitRounds3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcVisitThirst3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcVisitMood3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcVisitBlocked3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcStationOwner3D dd NPC_DEST_COUNT dup(-1)
|
||||
npcRemark3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcRemarkTime3D dd NPC_LIFE_COUNT dup(0)
|
||||
npcVisitSpeed3D dd 55000,61000,47000,52000,58000,44000,59000,50000,46000,54000
|
||||
npcVisitFavourite3D dd 5,3,2,1,4,2,5,1,3,4
|
||||
npcVisitSession3D dd 3,4,2,2,4,1,3,2,1,3
|
||||
npcVisitStake3D dd 40,60,20,30,80,20,50,30,20,60
|
||||
npcVisitInitialChips3D dd 1200,900,800,1000,1800,500,1300,1000,650,1400
|
||||
npcStationKind3D dd NV_LEAVE,NV_GAME,NV_GAME,NV_GAME,NV_GAME,NV_GAME
|
||||
dd NV_ORDER,NV_REST,NV_WATCH,NV_WATCH,NV_ORDER,NV_REST
|
||||
npcRemarkWin3D db 197,209,210,220,33,0
|
||||
npcRemarkLoss3D db 206,207,223,210,220,32,204,200,204,206,46,46,46,0
|
||||
npcRemarkOrder3D db 194,206,196,219,44,32,207,206,198,192,203,211,201,209,210,192,46,0
|
||||
npcRemarkChat3D db 202,192,202,32,194,197,215,197,208,63,0
|
||||
npcRemarkBreak3D db 207,206,208,192,32,207,197,208,197,196,206,213,205,211,210,220,46,0
|
||||
|
||||
88
tools/generators/pack_bowling_feel.py
Normal file
88
tools/generators/pack_bowling_feel.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
"""Offline first-person atlas packing and original deterministic bowling Foley."""
|
||||
from pathlib import Path
|
||||
import json
|
||||
import math
|
||||
import random
|
||||
import struct
|
||||
import wave
|
||||
from PIL import Image
|
||||
from pack_bowling import tween, pack
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
ART = ROOT/'assets/sprites/bowling'
|
||||
SOUND = ROOT/'assets/audio/bowling'
|
||||
|
||||
|
||||
def wav(name, seconds, pulses, rolling=False):
|
||||
rate = 22050
|
||||
rng = random.Random(41309)
|
||||
samples = []
|
||||
low = 0.0
|
||||
for i in range(round(rate*seconds)):
|
||||
t = i/rate
|
||||
noise = rng.uniform(-1,1)
|
||||
low += .12*(noise-low)
|
||||
value = 0.0
|
||||
if rolling:
|
||||
envelope = min(1,t/.03,(seconds-t)/.03)
|
||||
value = .22*low*envelope*(.7+.3*math.sin(t*43))
|
||||
for start, gain, frequency in pulses:
|
||||
age = t-start
|
||||
if 0 <= age < .45:
|
||||
value += gain*(.42*math.sin(age*frequency*math.tau)*math.exp(-age*27)
|
||||
+ .58*noise*math.exp(-age*45))
|
||||
samples.append(max(-32767,min(32767,round(value*24000))))
|
||||
with wave.open(str(SOUND/name),'wb') as output:
|
||||
output.setparams((1,2,rate,0,'NONE','not compressed'))
|
||||
output.writeframes(struct.pack(f'<{len(samples)}h',*samples))
|
||||
|
||||
|
||||
def pinsetter_audio():
|
||||
wav('pinsetter.wav',5.2,[(0,.24,120),(.4,.22,160),(1.7,.3,105),
|
||||
(2.2,.24,130),(3.7,.2,105),(4,.22,160),(4.4,.25,140)],True)
|
||||
|
||||
|
||||
def return_audio():
|
||||
wav('return.wav',2.0,[(.35,.18,95),(.75,.12,130),(1.3,.16,160),
|
||||
(1.65,.32,110),(1.78,.18,85)],True)
|
||||
|
||||
|
||||
def main():
|
||||
SOUND.mkdir(parents=True,exist_ok=True)
|
||||
source = Image.open(ART/'player-underarm-v2.png').convert('RGBA')
|
||||
keys = []
|
||||
# Cell 7 contains a detached ball: release uses the actual simulated sphere.
|
||||
for cell in (*range(7),8,9,10,11):
|
||||
x,y = cell%4,cell//4
|
||||
keys.append(source.crop((round(x*source.width/4),round(y*source.height/3),
|
||||
round((x+1)*source.width/4),round((y+1)*source.height/3)))
|
||||
.resize((256,256),Image.Resampling.LANCZOS))
|
||||
frames=[]
|
||||
for i,a in enumerate(keys):
|
||||
b=keys[min(i+1,len(keys)-1)]
|
||||
# Never morph the held ball into an empty hand across the release event.
|
||||
frames += [a,a,a] if i==6 else [a,tween(a,b,1/3),tween(a,b,2/3)]
|
||||
pack('player-underarm-v2.bin',frames)
|
||||
frames[0].save(ART/'player-underarm-v2.gif',save_all=True,
|
||||
append_images=frames[1:],duration=33,loop=0,disposal=2)
|
||||
wav('release.wav',.35,[(0,.8,94),(.025,.3,130)])
|
||||
wav('rolling.wav',14.5,[],True)
|
||||
wav('pins-light.wav',.7,[(0,.65,430),(.08,.38,670),(.19,.24,510)])
|
||||
wav('pins-heavy.wav',1.3,[(0,.9,390),(.025,.75,710),(.08,.65,510),
|
||||
(.14,.6,830),(.24,.4,620),(.39,.32,440),(.57,.2,740)])
|
||||
wav('applause.wav',1.4,[(i*.09,.25+(i%3)*.04,1700+i*23) for i in range(13)])
|
||||
pinsetter_audio()
|
||||
return_audio()
|
||||
(ART/'player-underarm-v2.json').write_text(json.dumps({
|
||||
'generator':'built-in image_gen','source':'player-underarm-v2.png',
|
||||
'brief':'First-person right-handed underarm bowling: low pendulum swing beside thigh, '
|
||||
'backswing leaves view, hand behind/below blue ball, ankle-height release, palm-up follow-through; '
|
||||
'dark rolled sleeve; transparent 4 by 3 atlas. Replaces rejected forward-pushing draft.',
|
||||
'selected_cells':[0,1,2,3,4,5,6,8,9,10,11],
|
||||
'frames':len(frames),'frame_size':[256,256],'release_frame':21,
|
||||
'audio':'Original seeded PCM synthesis, no sampled third-party recordings.'},indent=2)+'\n')
|
||||
print('Packed',len(frames),'underarm frames and seven original PCM effects')
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
||||
455
tools/tests/bowling_feel_test.inc
Normal file
455
tools/tests/bowling_feel_test.inc
Normal file
|
|
@ -0,0 +1,455 @@
|
|||
.data
|
||||
bpFeelScoreRolls dd 10,7,3,0,8,5,4,9,0,6,2,8,1,7,2,9,0,10,7,3
|
||||
bpFeelScorePath db 'build\hall-expansion\bowling-scorecard-full.bmp',0
|
||||
bpFeelPinPath0 db 'build\hall-expansion\bowling-impact-0.bmp',0
|
||||
bpFeelPinPath1 db 'build\hall-expansion\bowling-impact-1.bmp',0
|
||||
bpFeelPinPath2 db 'build\hall-expansion\bowling-impact-2.bmp',0
|
||||
bpFeelPinPath3 db 'build\hall-expansion\bowling-impact-3.bmp',0
|
||||
bpFeelPinPaths dd OFFSET bpFeelPinPath0,OFFSET bpFeelPinPath1,OFFSET bpFeelPinPath2,OFFSET bpFeelPinPath3
|
||||
bpFeelStatus db 'status bowlroll mode',0
|
||||
bpFeelStatusLight db 'status bowllight mode',0
|
||||
bpFeelStatusReset db 'status bowlreset mode',0
|
||||
bpFeelStatusReturn db 'status bowlreturn mode',0
|
||||
bpFeelReply db 64 dup(0)
|
||||
bpFeelSampleAim dd -FP_1/2,-FP_1*45/100,-FP_1*4/10,-FP_1*35/100,-FP_1*3/10,-FP_1/4,-FP_1/5,-FP_1*15/100,-FP_1/10,-FP_1/20
|
||||
dd 0,FP_1/20,FP_1/10,FP_1*15/100,FP_1/5,FP_1/4,FP_1*3/10,FP_1*35/100,FP_1*4/10,FP_1*45/100,FP_1/2
|
||||
bpFeelSamplePower dd 0,50,100
|
||||
bpFeelSamples dd 63*4 dup(0)
|
||||
bpFeelSamplesPath db 'build\hall-expansion\bowling-physics-samples.bin',0
|
||||
bpFeelSetterTimes dd 0,150,300,900,2000,3750,4150,4400
|
||||
bpFeelEmptyPinPath db 'build\hall-expansion\bowling-shape-empty.bmp',0
|
||||
bpFeelTinyPinPath db 'build\hall-expansion\bowling-shape-tiny.bmp',0
|
||||
include tools/tests/bowling_hand_paths.inc
|
||||
.code
|
||||
BowlingFeelNativeTests PROC uses ebx esi edi
|
||||
local window:DWORD,volume:DWORD,tilt:DWORD,aim:DWORD,power:DWORD,handle:DWORD,count:DWORD
|
||||
mov expansionStage,170
|
||||
call InitBowling3D
|
||||
mov hallLevel3D,HALL_BOWLING
|
||||
invoke BeginBowlingPlay3D,1
|
||||
mov expansionStage,179
|
||||
call ResetBowlingPlay3D
|
||||
; Subpixel negative impulses must not collapse the pin's local basis.
|
||||
invoke BowlingPlayKick3D,0,1,-1
|
||||
cmp bpPinAxisX3D,0
|
||||
jne bp_feel_fail
|
||||
cmp bpPinAxisY3D,-FP_1
|
||||
jne bp_feel_fail
|
||||
invoke BowlingPlayKick3D,0,257,257
|
||||
mov eax,bpPinAxisX3D
|
||||
imul eax
|
||||
shrd eax,edx,16
|
||||
mov ebx,eax
|
||||
mov eax,bpPinAxisY3D
|
||||
imul eax
|
||||
shrd eax,edx,16
|
||||
add eax,ebx
|
||||
cmp eax,FP_1*99/100
|
||||
jb bp_feel_fail
|
||||
cmp eax,FP_1*101/100
|
||||
ja bp_feel_fail
|
||||
mov bpState3D,BP_SETTLE
|
||||
mov bpBallY3D,FP_1*28/10
|
||||
mov bpPinTilt3D,128*256
|
||||
mov bwRack3D[4],0
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,OFFSET bpFeelEmptyPinPath
|
||||
mov bwRack3D[4],1
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,OFFSET bpFeelTinyPinPath
|
||||
mov expansionStage,170
|
||||
call ResetBowlingPlay3D
|
||||
mov bwRack3D[4],1
|
||||
mov bpGutter3D,1
|
||||
mov bpPinVX3D,512
|
||||
invoke BowlingPlayKick3D,0,512,0
|
||||
cmp bpHitMask3D,0
|
||||
jne bp_feel_fail
|
||||
mov esi,200
|
||||
bp_feel_weak:
|
||||
call BowlingPlayStep3D
|
||||
dec esi
|
||||
jnz bp_feel_weak
|
||||
cmp bpHitMask3D,0
|
||||
jne bp_feel_fail
|
||||
cmp bpPinTilt3D,24*256
|
||||
jae bp_feel_fail
|
||||
mov expansionStage,171
|
||||
call ResetBowlingPlay3D
|
||||
mov bwRack3D[4],1
|
||||
mov bpGutter3D,1
|
||||
mov bpPinVX3D,10000
|
||||
invoke BowlingPlayKick3D,0,10000,0
|
||||
cmp bpHitMask3D,0
|
||||
jne bp_feel_fail
|
||||
mov esi,120
|
||||
bp_feel_topple:
|
||||
call BowlingPlayStep3D
|
||||
dec esi
|
||||
jnz bp_feel_topple
|
||||
test bpHitMask3D,1
|
||||
jz bp_feel_fail
|
||||
cmp bpPinTilt3D,100*256
|
||||
jb bp_feel_fail
|
||||
cmp bpPinX3D,FP_1*93/100
|
||||
jg bp_feel_fail
|
||||
mov expansionStage,172
|
||||
; Opening contacts are separated but must not gain another impulse.
|
||||
call ResetBowlingPlay3D
|
||||
mov bpPinX3D,0
|
||||
mov bpPinX3D[4],FP_1*15/100
|
||||
mov bpPinY3D,4*FP_1
|
||||
mov bpPinY3D[4],4*FP_1
|
||||
mov bpPinVX3D,-2000
|
||||
mov bpPinVX3D[4],2000
|
||||
invoke BowlingPlayContact3D,0,1
|
||||
cmp bpPinVX3D,-2000
|
||||
jne bp_feel_fail
|
||||
cmp bpPinVX3D[4],2000
|
||||
jne bp_feel_fail
|
||||
; A fallen pin can receive a second impact and transfer momentum again.
|
||||
mov bpPinX3D,0
|
||||
mov bpPinX3D[4],FP_1*15/100
|
||||
mov bpPinVX3D,2000
|
||||
mov bpPinVX3D[4],0
|
||||
mov bpPinTilt3D,128*256
|
||||
mov bpHitMask3D,1
|
||||
invoke BowlingPlayContact3D,0,1
|
||||
cmp bpPinVX3D[4],500
|
||||
jb bp_feel_fail
|
||||
cmp bpPinVX3D,2000
|
||||
jae bp_feel_fail
|
||||
mov expansionStage,173
|
||||
call ResetBowlingPlay3D
|
||||
mov bpEndTicks3D,100
|
||||
mov bpPinTilt3D,40*256
|
||||
call BowlingPlayReady3D
|
||||
test eax,eax
|
||||
jnz bp_feel_fail
|
||||
mov bpPinTilt3D,128*256
|
||||
call BowlingPlayReady3D
|
||||
cmp eax,1
|
||||
jne bp_feel_fail
|
||||
mov expansionStage,174
|
||||
call ResetBowlingPlay3D
|
||||
lea esi,bpFeelScoreRolls
|
||||
lea edi,bwRolls3D[192]
|
||||
mov ecx,20
|
||||
rep movsd
|
||||
mov bwRollCount3D[8],20
|
||||
invoke BowlingScore3D,2
|
||||
invoke BowlingRollGlyph3D,2,0,0
|
||||
cmp eax,'X'
|
||||
jne bp_feel_fail
|
||||
invoke BowlingRollGlyph3D,2,1,1
|
||||
cmp eax,'/'
|
||||
jne bp_feel_fail
|
||||
invoke BowlingRollGlyph3D,2,2,0
|
||||
cmp eax,'-'
|
||||
jne bp_feel_fail
|
||||
invoke BowlingRollGlyph3D,2,9,0
|
||||
cmp eax,'X'
|
||||
jne bp_feel_fail
|
||||
invoke BowlingRollGlyph3D,2,9,1
|
||||
cmp eax,'7'
|
||||
jne bp_feel_fail
|
||||
invoke BowlingRollGlyph3D,2,9,2
|
||||
cmp eax,'/'
|
||||
jne bp_feel_fail
|
||||
mov bpScoreOpen3D,1
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,OFFSET bpFeelScorePath
|
||||
mov bwRolls3D[192],0
|
||||
mov bwRolls3D[196],10
|
||||
mov bwRollCount3D[8],2
|
||||
invoke BowlingRollGlyph3D,2,0,1
|
||||
cmp eax,'/'
|
||||
jne bp_feel_fail
|
||||
lea esi,bpFeelScoreRolls
|
||||
lea edi,bwRolls3D[192]
|
||||
mov ecx,20
|
||||
rep movsd
|
||||
mov bwRollCount3D[8],20
|
||||
mov bwRolls3D[192+18*4],0
|
||||
mov bwRolls3D[192+19*4],10
|
||||
invoke BowlingRollGlyph3D,2,9,2
|
||||
cmp eax,'/'
|
||||
jne bp_feel_fail
|
||||
mov expansionStage,175
|
||||
call ResetBowlingPlay3D
|
||||
mov bpLockedAim3D,0
|
||||
mov bpLockedPower3D,85
|
||||
call BowlingPlayLaunch3D
|
||||
mov bpState3D,BP_ROLL
|
||||
mov esi,0
|
||||
mov edi,0
|
||||
bp_feel_impact:
|
||||
call BowlingPlayStep3D
|
||||
inc esi
|
||||
cmp esi,160
|
||||
jb bp_feel_impact
|
||||
mov eax,esi
|
||||
and eax,15
|
||||
jnz bp_feel_impact
|
||||
imul eax,esi,16
|
||||
mov bpTime3D,eax
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,bpFeelPinPaths[edi*4]
|
||||
inc edi
|
||||
cmp edi,4
|
||||
jb bp_feel_impact
|
||||
mov power,0
|
||||
mov aim,0
|
||||
mov edi,0
|
||||
bp_feel_sample:
|
||||
call ResetBowlingPlay3D
|
||||
mov eax,aim
|
||||
mov eax,bpFeelSampleAim[eax*4]
|
||||
mov bpLockedAim3D,eax
|
||||
mov bpFeelSamples[edi],eax
|
||||
mov eax,power
|
||||
mov eax,bpFeelSamplePower[eax*4]
|
||||
mov bpLockedPower3D,eax
|
||||
mov bpFeelSamples[edi+4],eax
|
||||
call BowlingPlayLaunch3D
|
||||
mov esi,900
|
||||
bp_feel_sample_steps:
|
||||
call BowlingPlayStep3D
|
||||
; Check the constraints throughout the roll, not just at settlement.
|
||||
mov ebx,0
|
||||
bp_feel_sample_bounds:
|
||||
mov eax,bpPinX3D[ebx*4]
|
||||
sub eax,bwPinX3D[ebx*4]
|
||||
sar eax,8
|
||||
imul eax,eax
|
||||
mov ecx,eax
|
||||
mov eax,bpPinY3D[ebx*4]
|
||||
sub eax,bwPinY3D[ebx*4]
|
||||
sar eax,8
|
||||
imul eax,eax
|
||||
add eax,ecx
|
||||
cmp eax,132*132
|
||||
ja bp_feel_fail
|
||||
mov eax,bpPinAxisX3D[ebx*4]
|
||||
imul eax
|
||||
shrd eax,edx,16
|
||||
mov ecx,eax
|
||||
mov eax,bpPinAxisY3D[ebx*4]
|
||||
imul eax
|
||||
shrd eax,edx,16
|
||||
add eax,ecx
|
||||
cmp eax,FP_1*99/100
|
||||
jb bp_feel_fail
|
||||
cmp eax,FP_1*101/100
|
||||
ja bp_feel_fail
|
||||
inc ebx
|
||||
cmp ebx,10
|
||||
jb bp_feel_sample_bounds
|
||||
dec esi
|
||||
jnz bp_feel_sample_steps
|
||||
mov eax,bpHitMask3D
|
||||
mov bpFeelSamples[edi+8],eax
|
||||
mov eax,bpPinTilt3D
|
||||
mov bpFeelSamples[edi+12],eax
|
||||
add edi,16
|
||||
inc aim
|
||||
cmp aim,21
|
||||
jb bp_feel_sample
|
||||
mov aim,0
|
||||
inc power
|
||||
cmp power,3
|
||||
jb bp_feel_sample
|
||||
invoke CreateFileA,OFFSET bpFeelSamplesPath,40000000h,0,0,2,80h,0
|
||||
mov handle,eax
|
||||
invoke WriteFile,handle,OFFSET bpFeelSamples,SIZEOF bpFeelSamples,ADDR count,0
|
||||
invoke CloseHandle,handle
|
||||
mov expansionStage,176
|
||||
call ResetBowlingPlay3D
|
||||
xor esi,esi
|
||||
bp_feel_hand:
|
||||
mov bpState3D,BP_RELEASE
|
||||
imul eax,esi,33
|
||||
mov bpTime3D,eax
|
||||
cmp esi,21
|
||||
jb @F
|
||||
mov bpState3D,BP_ROLL
|
||||
sub eax,21*33
|
||||
mov bpTime3D,eax
|
||||
@@:
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,bpFeelHandPaths[esi*4]
|
||||
inc esi
|
||||
cmp esi,33
|
||||
jb bp_feel_hand
|
||||
mov expansionStage,178
|
||||
call ResetBowlingPlay3D
|
||||
mov bpPinX3D,2*FP_1
|
||||
mov bpPinVX3D,10000
|
||||
invoke BowlingPlayTether3D,0
|
||||
cmp bpPinX3D,FP_1*67/100
|
||||
ja bp_feel_fail
|
||||
cmp bpPinVX3D,2500
|
||||
ja bp_feel_fail
|
||||
mov bpPinTilt3D,128*256
|
||||
mov bpPinAxisX3D,FP_1
|
||||
mov bpPinAxisY3D,0
|
||||
invoke BowlingPlayDeckBounds3D,0
|
||||
cmp bpPinX3D,FP_1*48/100
|
||||
ja bp_feel_fail
|
||||
call ResetBowlingPlay3D
|
||||
mov bpHitMask3D,1
|
||||
mov bpPinTilt3D,128*256
|
||||
call BowlingPlayFinishRoll3D
|
||||
mov deltaTime3D,250
|
||||
mov esi,7
|
||||
bp_feel_start_setter:
|
||||
call HandleBowlingPlay3D
|
||||
dec esi
|
||||
jnz bp_feel_start_setter
|
||||
cmp bpState3D,BP_RESET
|
||||
jne bp_feel_fail
|
||||
cmp bwRollCount3D[8],1
|
||||
jne bp_feel_fail
|
||||
mov bpTime3D,1100
|
||||
invoke BowlingPinsetterPose3D,0
|
||||
test eax,eax
|
||||
jz bp_feel_fail
|
||||
cmp bpVisualPinLift3D,FP_1/2
|
||||
jb bp_feel_fail
|
||||
cmp bpPinTilt3D,128*256
|
||||
jne bp_feel_fail
|
||||
mov bpTime3D,1800
|
||||
invoke BowlingPinsetterPose3D,0
|
||||
cmp eax,1
|
||||
jne bp_feel_fail
|
||||
cmp bpVisualPinLift3D,FP_1
|
||||
jb bp_feel_fail
|
||||
mov bpTime3D,2450
|
||||
invoke BowlingPinsetterPose3D,0
|
||||
cmp eax,1
|
||||
jne bp_feel_fail
|
||||
cmp bpVisualPinLift3D,FP_1
|
||||
jb bp_feel_fail
|
||||
invoke BowlingPinsetterPose3D,1
|
||||
cmp eax,1
|
||||
jne bp_feel_fail
|
||||
mov bwNewRack3D[4],1
|
||||
invoke BowlingPinsetterPose3D,0
|
||||
cmp eax,1
|
||||
jne bp_feel_fail
|
||||
mov bwNewRack3D[4],0
|
||||
mov bpTime3D,3750
|
||||
invoke BowlingPinsetterPose3D,1
|
||||
cmp bpVisualPinLift3D,0
|
||||
jne bp_feel_fail
|
||||
mov esi,0
|
||||
bp_feel_setter_capture:
|
||||
mov eax,bpFeelSetterTimes[esi*4]
|
||||
mov bpTime3D,eax
|
||||
mov bpBallY3D,FP_1*28/10
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,bpFeelSetterPaths[esi*4]
|
||||
inc esi
|
||||
cmp esi,8
|
||||
jb bp_feel_setter_capture
|
||||
mov bpTime3D,BP_RESET_MS
|
||||
mov deltaTime3D,0
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne bp_feel_fail
|
||||
mov bpTime3D,BP_RETURN_MS
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_feel_fail
|
||||
cmp bwRack3D[4],1022
|
||||
jne bp_feel_fail
|
||||
cmp bwRollCount3D[8],1
|
||||
jne bp_feel_fail
|
||||
; First-ball miss leaves the standing rack alone and never runs the hoist.
|
||||
call ResetBowlingPlay3D
|
||||
call BowlingPlayFinishRoll3D
|
||||
mov bpTime3D,1600
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne bp_feel_fail
|
||||
mov bpTime3D,BP_RETURN_MS
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_feel_fail
|
||||
cmp bwRack3D[4],1023
|
||||
jne bp_feel_fail
|
||||
mov bpState3D,BP_RESET
|
||||
mov bpTime3D,0
|
||||
call BowlingPinsetterGate3D
|
||||
cmp eax,FP_1
|
||||
jne bp_feel_fail
|
||||
mov bpTime3D,400
|
||||
call BowlingPinsetterGate3D
|
||||
cmp eax,FP_1*14/100
|
||||
ja bp_feel_fail
|
||||
mov bpTime3D,4400
|
||||
call BowlingPinsetterGate3D
|
||||
cmp eax,FP_1
|
||||
jne bp_feel_fail
|
||||
mov expansionStage,177
|
||||
; Real MCI devices, muted: opens, volume, release/roll/impact and close.
|
||||
mov eax,h3DWnd
|
||||
mov window,eax
|
||||
mov eax,settingsVolume
|
||||
mov volume,eax
|
||||
mov h3DWnd,1
|
||||
mov settingsVolume,0
|
||||
call BowlingAudioOpen3D
|
||||
mov bpScoreOpen3D,0
|
||||
mov bpState3D,BP_ROLL
|
||||
mov bpEndTicks3D,0
|
||||
mov bpImpactEnergy3D,6000
|
||||
mov bpImpactCooldown3D,0
|
||||
call BowlingAudioUpdate3D
|
||||
invoke mciSendStringA,OFFSET bpFeelStatus,OFFSET bpFeelReply,64,0
|
||||
test eax,eax
|
||||
jnz bp_feel_audio_fail
|
||||
cmp BYTE PTR bpFeelReply,'p'
|
||||
jne bp_feel_audio_fail
|
||||
invoke mciSendStringA,OFFSET bpFeelStatusLight,OFFSET bpFeelReply,64,0
|
||||
test eax,eax
|
||||
jnz bp_feel_audio_fail
|
||||
invoke mciSendStringA,OFFSET bpFeelStatusReset,OFFSET bpFeelReply,64,0
|
||||
test eax,eax
|
||||
jnz bp_feel_audio_fail
|
||||
mov bpScoreOpen3D,1
|
||||
call BowlingAudioUpdate3D
|
||||
cmp bpAudioRolling3D,0
|
||||
jne bp_feel_audio_fail
|
||||
mov bpScoreOpen3D,0
|
||||
mov bpState3D,BP_RETURN
|
||||
mov bpTime3D,500
|
||||
call BowlingAudioUpdate3D
|
||||
invoke mciSendStringA,OFFSET bpFeelStatusReturn,OFFSET bpFeelReply,64,0
|
||||
test eax,eax
|
||||
jnz bp_feel_audio_fail
|
||||
cmp BYTE PTR bpFeelReply,'p'
|
||||
jne bp_feel_audio_fail
|
||||
mov bpScoreOpen3D,1
|
||||
call BowlingAudioUpdate3D
|
||||
cmp bpAudioReturning3D,0
|
||||
jne bp_feel_audio_fail
|
||||
call BowlingAudioClose3D
|
||||
invoke mciSendStringA,OFFSET bpFeelStatus,OFFSET bpFeelReply,64,0
|
||||
test eax,eax
|
||||
jz bp_feel_audio_fail
|
||||
invoke mciSendStringA,OFFSET bpFeelStatusReturn,OFFSET bpFeelReply,64,0
|
||||
test eax,eax
|
||||
jz bp_feel_audio_fail
|
||||
mov eax,window
|
||||
mov h3DWnd,eax
|
||||
mov eax,volume
|
||||
mov settingsVolume,eax
|
||||
call LeaveBowlingPlay3D
|
||||
ret
|
||||
bp_feel_audio_fail:
|
||||
call BowlingAudioClose3D
|
||||
bp_feel_fail:
|
||||
invoke ExitProcess,expansionStage
|
||||
ret
|
||||
BowlingFeelNativeTests ENDP
|
||||
52
tools/tests/bowling_hand_paths.inc
Normal file
52
tools/tests/bowling_hand_paths.inc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
.data
|
||||
bpFeelHand0 db 'build\hall-expansion\bowling-hand-00.bmp',0
|
||||
bpFeelHand1 db 'build\hall-expansion\bowling-hand-01.bmp',0
|
||||
bpFeelHand2 db 'build\hall-expansion\bowling-hand-02.bmp',0
|
||||
bpFeelHand3 db 'build\hall-expansion\bowling-hand-03.bmp',0
|
||||
bpFeelHand4 db 'build\hall-expansion\bowling-hand-04.bmp',0
|
||||
bpFeelHand5 db 'build\hall-expansion\bowling-hand-05.bmp',0
|
||||
bpFeelHand6 db 'build\hall-expansion\bowling-hand-06.bmp',0
|
||||
bpFeelHand7 db 'build\hall-expansion\bowling-hand-07.bmp',0
|
||||
bpFeelHand8 db 'build\hall-expansion\bowling-hand-08.bmp',0
|
||||
bpFeelHand9 db 'build\hall-expansion\bowling-hand-09.bmp',0
|
||||
bpFeelHand10 db 'build\hall-expansion\bowling-hand-10.bmp',0
|
||||
bpFeelHand11 db 'build\hall-expansion\bowling-hand-11.bmp',0
|
||||
bpFeelHand12 db 'build\hall-expansion\bowling-hand-12.bmp',0
|
||||
bpFeelHand13 db 'build\hall-expansion\bowling-hand-13.bmp',0
|
||||
bpFeelHand14 db 'build\hall-expansion\bowling-hand-14.bmp',0
|
||||
bpFeelHand15 db 'build\hall-expansion\bowling-hand-15.bmp',0
|
||||
bpFeelHand16 db 'build\hall-expansion\bowling-hand-16.bmp',0
|
||||
bpFeelHand17 db 'build\hall-expansion\bowling-hand-17.bmp',0
|
||||
bpFeelHand18 db 'build\hall-expansion\bowling-hand-18.bmp',0
|
||||
bpFeelHand19 db 'build\hall-expansion\bowling-hand-19.bmp',0
|
||||
bpFeelHand20 db 'build\hall-expansion\bowling-hand-20.bmp',0
|
||||
bpFeelHand21 db 'build\hall-expansion\bowling-hand-21.bmp',0
|
||||
bpFeelHand22 db 'build\hall-expansion\bowling-hand-22.bmp',0
|
||||
bpFeelHand23 db 'build\hall-expansion\bowling-hand-23.bmp',0
|
||||
bpFeelHand24 db 'build\hall-expansion\bowling-hand-24.bmp',0
|
||||
bpFeelHand25 db 'build\hall-expansion\bowling-hand-25.bmp',0
|
||||
bpFeelHand26 db 'build\hall-expansion\bowling-hand-26.bmp',0
|
||||
bpFeelHand27 db 'build\hall-expansion\bowling-hand-27.bmp',0
|
||||
bpFeelHand28 db 'build\hall-expansion\bowling-hand-28.bmp',0
|
||||
bpFeelHand29 db 'build\hall-expansion\bowling-hand-29.bmp',0
|
||||
bpFeelHand30 db 'build\hall-expansion\bowling-hand-30.bmp',0
|
||||
bpFeelHand31 db 'build\hall-expansion\bowling-hand-31.bmp',0
|
||||
bpFeelHand32 db 'build\hall-expansion\bowling-hand-32.bmp',0
|
||||
bpFeelHandPaths LABEL DWORD
|
||||
dd OFFSET bpFeelHand0,OFFSET bpFeelHand1,OFFSET bpFeelHand2,OFFSET bpFeelHand3,OFFSET bpFeelHand4
|
||||
dd OFFSET bpFeelHand5,OFFSET bpFeelHand6,OFFSET bpFeelHand7,OFFSET bpFeelHand8,OFFSET bpFeelHand9
|
||||
dd OFFSET bpFeelHand10,OFFSET bpFeelHand11,OFFSET bpFeelHand12,OFFSET bpFeelHand13,OFFSET bpFeelHand14
|
||||
dd OFFSET bpFeelHand15,OFFSET bpFeelHand16,OFFSET bpFeelHand17,OFFSET bpFeelHand18,OFFSET bpFeelHand19
|
||||
dd OFFSET bpFeelHand20,OFFSET bpFeelHand21,OFFSET bpFeelHand22,OFFSET bpFeelHand23,OFFSET bpFeelHand24
|
||||
dd OFFSET bpFeelHand25,OFFSET bpFeelHand26,OFFSET bpFeelHand27,OFFSET bpFeelHand28,OFFSET bpFeelHand29
|
||||
dd OFFSET bpFeelHand30,OFFSET bpFeelHand31,OFFSET bpFeelHand32
|
||||
bpFeelSetter0 db 'build\hall-expansion\bowling-pinsetter-0.bmp',0
|
||||
bpFeelSetter1 db 'build\hall-expansion\bowling-pinsetter-1.bmp',0
|
||||
bpFeelSetter2 db 'build\hall-expansion\bowling-pinsetter-2.bmp',0
|
||||
bpFeelSetter3 db 'build\hall-expansion\bowling-pinsetter-3.bmp',0
|
||||
bpFeelSetter4 db 'build\hall-expansion\bowling-pinsetter-4.bmp',0
|
||||
bpFeelSetter5 db 'build\hall-expansion\bowling-pinsetter-5.bmp',0
|
||||
bpFeelSetter6 db 'build\hall-expansion\bowling-pinsetter-6.bmp',0
|
||||
bpFeelSetter7 db 'build\hall-expansion\bowling-pinsetter-7.bmp',0
|
||||
bpFeelSetterPaths dd OFFSET bpFeelSetter0,OFFSET bpFeelSetter1,OFFSET bpFeelSetter2,OFFSET bpFeelSetter3,OFFSET bpFeelSetter4,OFFSET bpFeelSetter5,OFFSET bpFeelSetter6,OFFSET bpFeelSetter7
|
||||
.code
|
||||
|
|
@ -28,6 +28,13 @@ BowlingPlayNativeTests PROC uses ebx esi edi
|
|||
jne bp_test_fail
|
||||
cmp bwBusy3D[4],2
|
||||
jne bp_test_fail
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
jne bp_test_fail
|
||||
mov deltaTime3D,0
|
||||
mov pressedKeys3D[20h],1
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_test_fail
|
||||
mov expansionStage,151
|
||||
mov deltaTime3D,0
|
||||
mov bpClock3D,0
|
||||
|
|
@ -259,8 +266,15 @@ bp_test_flight:
|
|||
mov eax,bankroll
|
||||
cmp eax,bank
|
||||
jne bp_test_fail
|
||||
call BowlingFeelNativeTests
|
||||
call BowlingReturnNativeTests
|
||||
call BowlingWeightNativeTests
|
||||
ret
|
||||
bp_test_fail:
|
||||
invoke ExitProcess,expansionStage
|
||||
ret
|
||||
BowlingPlayNativeTests ENDP
|
||||
|
||||
include tools/tests/bowling_feel_test.inc
|
||||
include tools/tests/bowling_return_test.inc
|
||||
include tools/tests/bowling_weight_test.inc
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ BowlingUiStart PROC
|
|||
call Create3DWindow
|
||||
test eax,eax
|
||||
jz bp_ui_fail
|
||||
call ToggleFullscreen3D
|
||||
invoke SetWindowLongA,h3DWnd,-4,OFFSET WindowEvents3D
|
||||
call InitBowling3D
|
||||
call LoadBowling3D
|
||||
|
|
|
|||
167
tools/tests/bowling_return_test.inc
Normal file
167
tools/tests/bowling_return_test.inc
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
.data
|
||||
bpReturnTest0 db 'build\hall-expansion\bowling-return-0.bmp',0
|
||||
bpReturnTest1 db 'build\hall-expansion\bowling-return-1.bmp',0
|
||||
bpReturnTest2 db 'build\hall-expansion\bowling-return-2.bmp',0
|
||||
bpReturnTest3 db 'build\hall-expansion\bowling-return-3.bmp',0
|
||||
bpReturnTest4 db 'build\hall-expansion\bowling-return-4.bmp',0
|
||||
bpReturnTest5 db 'build\hall-expansion\bowling-return-5.bmp',0
|
||||
bpReturnTest6 db 'build\hall-expansion\bowling-return-6.bmp',0
|
||||
bpReturnTest7 db 'build\hall-expansion\bowling-return-7.bmp',0
|
||||
bpReturnTestPaths dd OFFSET bpReturnTest0,OFFSET bpReturnTest1,OFFSET bpReturnTest2,OFFSET bpReturnTest3
|
||||
dd OFFSET bpReturnTest4,OFFSET bpReturnTest5,OFFSET bpReturnTest6,OFFSET bpReturnTest7
|
||||
; Capture after the emerging ball clears the solid hood, not while inside it.
|
||||
bpReturnTestTimes dd 0,400,900,1000,1300,1700,2200,2800
|
||||
.code
|
||||
BowlingReturnNativeTests PROC uses ebx esi edi
|
||||
local position:DWORD
|
||||
mov expansionStage,180
|
||||
call InitBowling3D
|
||||
mov hallLevel3D,HALL_BOWLING
|
||||
mov engineMode,MODE_WALK
|
||||
mov playerX,5*FP_1
|
||||
mov playerY,25*FP_1
|
||||
mov playerAngle,384
|
||||
invoke BeginBowlingPlay3D,1
|
||||
mov bpHitMask3D,1
|
||||
call BowlingPlayFinishRoll3D
|
||||
mov bpState3D,BP_RESET
|
||||
mov bpTime3D,BP_RESET_MS
|
||||
mov deltaTime3D,0
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne bp_return_test_fail
|
||||
cmp bpAfterReturn3D,BP_DIRECTION
|
||||
jne bp_return_test_fail
|
||||
cmp bwRollCount3D[8],1
|
||||
jne bp_return_test_fail
|
||||
cmp bwRack3D[4],1022
|
||||
jne bp_return_test_fail
|
||||
call BowlingReturnBallPose3D
|
||||
test eax,eax
|
||||
jnz bp_return_test_fail
|
||||
; A queued throw cannot skip the return or choose the next direction.
|
||||
mov mouseX3D,160
|
||||
mov mouseY3D,120
|
||||
mov mouseClick3D,1
|
||||
mov pressedKeys3D[20h],1
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne bp_return_test_fail
|
||||
mov bpTime3D,1000
|
||||
call BowlingReturnBallPose3D
|
||||
cmp eax,1
|
||||
jne bp_return_test_fail
|
||||
cmp bpReturnedX3D,FP_1*395/100
|
||||
jne bp_return_test_fail
|
||||
mov eax,bpReturnedY3D
|
||||
mov position,eax
|
||||
mov bpTime3D,1700
|
||||
call BowlingReturnBallPose3D
|
||||
cmp eax,1
|
||||
jne bp_return_test_fail
|
||||
mov eax,bpReturnedY3D
|
||||
cmp eax,position
|
||||
jle bp_return_test_fail
|
||||
cmp eax,FP_1*2616/100
|
||||
ja bp_return_test_fail
|
||||
cmp bpReturnedZ3D,FP_1*84/100
|
||||
jne bp_return_test_fail
|
||||
mov bpTime3D,400
|
||||
invoke BowlingReturnCamera3D,FP_1*252/10
|
||||
cmp playerAngle,320
|
||||
jne bp_return_test_fail
|
||||
cmp playerY,FP_1*268/10
|
||||
jne bp_return_test_fail
|
||||
mov bpTime3D,1000
|
||||
mov bpScoreOpen3D,1
|
||||
mov deltaTime3D,250
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpTime3D,1000
|
||||
jne bp_return_test_fail
|
||||
mov bpScoreOpen3D,0
|
||||
mov deltaTime3D,0
|
||||
xor esi,esi
|
||||
bp_return_test_capture:
|
||||
mov eax,bpReturnTestTimes[esi*4]
|
||||
mov bpTime3D,eax
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,bpReturnTestPaths[esi*4]
|
||||
inc esi
|
||||
cmp esi,8
|
||||
jb bp_return_test_capture
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_return_test_fail
|
||||
cmp bpTime3D,0
|
||||
jne bp_return_test_fail
|
||||
cmp bwRollCount3D[8],1
|
||||
jne bp_return_test_fail
|
||||
mov expansionStage,181
|
||||
mov bpHitMask3D,1022
|
||||
call BowlingPlayFinishRoll3D
|
||||
call CompleteBowlingRoll3D
|
||||
cmp bpAfterReturn3D,BP_BOT
|
||||
jne bp_return_test_fail
|
||||
cmp bwTurn3D[4],1
|
||||
jne bp_return_test_fail
|
||||
mov bpTime3D,BP_RETURN_MS
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_BOT
|
||||
jne bp_return_test_fail
|
||||
cmp bwRollCount3D[8],2
|
||||
jne bp_return_test_fail
|
||||
; Even the final ball returns before the result overlay appears.
|
||||
call ResetBowlingPlay3D
|
||||
mov esi,23
|
||||
bp_return_test_perfect:
|
||||
mov bpHitMask3D,1023
|
||||
call BowlingPlayFinishRoll3D
|
||||
call BowlingPlayNext3D
|
||||
dec esi
|
||||
jnz bp_return_test_perfect
|
||||
mov bpHitMask3D,1023
|
||||
call BowlingPlayFinishRoll3D
|
||||
call CompleteBowlingRoll3D
|
||||
cmp bpAfterReturn3D,BP_FINISHED
|
||||
jne bp_return_test_fail
|
||||
cmp bpState3D,BP_RETURN
|
||||
jne bp_return_test_fail
|
||||
mov bpTime3D,BP_RETURN_MS
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_FINISHED
|
||||
jne bp_return_test_fail
|
||||
cmp bwScores3D[8],300
|
||||
jne bp_return_test_fail
|
||||
cmp bwScores3D[12],300
|
||||
jne bp_return_test_fail
|
||||
call LeaveBowlingPlay3D
|
||||
mov expansionStage,182
|
||||
invoke BeginBowlingPlay3D,2
|
||||
mov bpState3D,BP_RETURN
|
||||
mov bpTime3D,1700
|
||||
call BowlingReturnBallPose3D
|
||||
cmp bpReturnedX3D,FP_1*38/10+FP_1*395/100
|
||||
jne bp_return_test_fail
|
||||
invoke BowlingReturnCamera3D,FP_1*252/10
|
||||
cmp playerAngle,448
|
||||
jne bp_return_test_fail
|
||||
call LeaveBowlingPlay3D
|
||||
cmp playerX,5*FP_1
|
||||
jne bp_return_test_fail
|
||||
cmp playerY,25*FP_1
|
||||
jne bp_return_test_fail
|
||||
cmp playerAngle,384
|
||||
jne bp_return_test_fail
|
||||
cmp engineMode,MODE_WALK
|
||||
jne bp_return_test_fail
|
||||
invoke BowlingCanWalk3D,FP_1*395/100,FP_1*264/10
|
||||
test eax,eax
|
||||
jnz bp_return_test_fail
|
||||
invoke BowlingCanWalk3D,FP_1*49/10,FP_1*264/10
|
||||
cmp eax,1
|
||||
jne bp_return_test_fail
|
||||
ret
|
||||
bp_return_test_fail:
|
||||
invoke ExitProcess,expansionStage
|
||||
ret
|
||||
BowlingReturnNativeTests ENDP
|
||||
299
tools/tests/bowling_weight_test.inc
Normal file
299
tools/tests/bowling_weight_test.inc
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
.data
|
||||
bpMassTestPath db 'build\hall-expansion\bowling-mass-samples.bin',0
|
||||
bpMassTest4Path db 'build\hall-expansion\bowling-weight-4.bmp',0
|
||||
bpMassTest7Path db 'build\hall-expansion\bowling-weight-7.bmp',0
|
||||
bpMassTestLockedPath db 'build\hall-expansion\bowling-weight-locked.bmp',0
|
||||
bpMassTestRackPath db 'build\hall-expansion\bowling-weight-rack.bmp',0
|
||||
bpMassTestRedPath db 'build\hall-expansion\bowling-weight-5.bmp',0
|
||||
bpMassTestRackPairPath db 'build\hall-expansion\bowling-weight-rack-pair.bmp',0
|
||||
bpMassTestPowers dd 0,50,100
|
||||
bpMassShotsPath db 'build\hall-expansion\bowling-mass-shots.bin',0
|
||||
bpMassShots dd 84*3 dup(0)
|
||||
; kg, power, launch m/s Q16, inverse mass Q16, incoming vy, outgoing ball/pin vy, locked kg.
|
||||
bpMassTestSamples dd 12*8 dup(0)
|
||||
.code
|
||||
BowlingWeightNativeTests PROC uses ebx esi edi
|
||||
local bank:DWORD,rng:DWORD,kg:DWORD,power:DWORD,handle:DWORD,count:DWORD,inverse:DWORD
|
||||
local aim:DWORD
|
||||
mov expansionStage,183
|
||||
call InitBowling3D
|
||||
mov hallLevel3D,HALL_BOWLING
|
||||
invoke BeginBowlingPlay3D,1
|
||||
mov eax,bankroll
|
||||
mov bank,eax
|
||||
mov eax,bwRng3D
|
||||
mov rng,eax
|
||||
mov deltaTime3D,0
|
||||
mov viewWidth3D,640
|
||||
mov viewHeight3D,480
|
||||
mov viewLeft3D,0
|
||||
mov viewTop3D,0
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
jne bp_mass_test_fail
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,OFFSET bpMassTestRackPath
|
||||
invoke BowlingTintBallPixel3D,55203CC0h,4
|
||||
cmp eax,5520C03Ch
|
||||
jne bp_mass_test_fail
|
||||
invoke BowlingTintBallPixel3D,55203CC0h,5
|
||||
cmp eax,55C01E20h
|
||||
jne bp_mass_test_fail
|
||||
invoke BowlingTintBallPixel3D,55203CC0h,7
|
||||
cmp eax,55C07E20h
|
||||
jne bp_mass_test_fail
|
||||
xor esi,esi
|
||||
bp_mass_test_material:
|
||||
lea eax,[esi+4]
|
||||
invoke BowlingBallMaterial3D,eax
|
||||
invoke ResolveCitySurface3D,eax
|
||||
test eax,eax
|
||||
jz bp_mass_test_fail
|
||||
cmp ecx,64
|
||||
jne bp_mass_test_fail
|
||||
cmp edx,64
|
||||
jne bp_mass_test_fail
|
||||
cmp esi,3
|
||||
jae @F
|
||||
mov eax,bpRackHitX3D[esi*4+4]
|
||||
sub eax,bpRackHitX3D[esi*4]
|
||||
cmp eax,36
|
||||
jl bp_mass_test_fail
|
||||
@@:
|
||||
inc esi
|
||||
cmp esi,4
|
||||
jb bp_mass_test_material
|
||||
; A click away from the actual rack never selects a ball or starts a throw.
|
||||
invoke WindowEvents3D,0,201h,1,00780014h
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
jne bp_mass_test_fail
|
||||
mov eax,bpRackHitY3D
|
||||
shl eax,17
|
||||
mov edx,bpRackHitX3D
|
||||
shl edx,1
|
||||
or eax,edx
|
||||
invoke WindowEvents3D,0,201h,1,eax
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpWeightKg3D,4
|
||||
jne bp_mass_test_fail
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_mass_test_fail
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,OFFSET bpMassTest4Path
|
||||
invoke WindowEvents3D,0,100h,34h,0
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpWeightKg3D,7
|
||||
jne bp_mass_test_fail
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_mass_test_fail
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_mass_test_fail
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,OFFSET bpMassTest7Path
|
||||
; The weight label opens the in-world rack; labels and spheres share picking.
|
||||
invoke WindowEvents3D,0,201h,1,003C0018h
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpState3D,BP_SELECT_BALL
|
||||
jne bp_mass_test_fail
|
||||
call RenderBowlingPlay3D
|
||||
mov eax,bpRackHitY3D[4]
|
||||
add eax,bpRackHitRadius3D[4]
|
||||
add eax,9
|
||||
shl eax,17
|
||||
mov edx,bpRackHitX3D[4]
|
||||
shl edx,1
|
||||
or eax,edx
|
||||
invoke WindowEvents3D,0,201h,1,eax
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpWeightKg3D,5
|
||||
jne bp_mass_test_fail
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_mass_test_fail
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,OFFSET bpMassTestRedPath
|
||||
; Test the source/scratch pixels directly: transparent hand borders can reveal
|
||||
; different rack balls behind them and are not a valid skin screenshot mask.
|
||||
mov esi,bpHandArt3D.pixels
|
||||
lea edi,bpTintedHandPixels3D
|
||||
mov ebx,256*256
|
||||
xor ecx,ecx
|
||||
bp_mass_test_hand_pixel:
|
||||
mov eax,[esi]
|
||||
mov edx,[edi]
|
||||
xor edx,eax
|
||||
test edx,0FF000000h
|
||||
jnz bp_mass_test_fail
|
||||
test edx,edx
|
||||
jz bp_mass_test_hand_next
|
||||
inc ecx
|
||||
mov edx,eax
|
||||
shr edx,16
|
||||
and edx,255
|
||||
and eax,255
|
||||
cmp edx,eax
|
||||
jae bp_mass_test_fail
|
||||
bp_mass_test_hand_next:
|
||||
add esi,4
|
||||
add edi,4
|
||||
dec ebx
|
||||
jnz bp_mass_test_hand_pixel
|
||||
cmp ecx,500
|
||||
jb bp_mass_test_fail
|
||||
mov eax,bankroll
|
||||
cmp eax,bank
|
||||
jne bp_mass_test_fail
|
||||
mov eax,bwRng3D
|
||||
cmp eax,rng
|
||||
jne bp_mass_test_fail
|
||||
mov expansionStage,184
|
||||
mov kg,4
|
||||
mov power,0
|
||||
xor edi,edi
|
||||
bp_mass_sample:
|
||||
call ResetBowlingPlay3D
|
||||
mov eax,kg
|
||||
mov bpWeightKg3D,eax
|
||||
mov bpMassTestSamples[edi],eax
|
||||
mov eax,power
|
||||
mov eax,bpMassTestPowers[eax*4]
|
||||
mov bpLockedPower3D,eax
|
||||
mov bpMassTestSamples[edi+4],eax
|
||||
mov bpLockedAim3D,FP_1/2
|
||||
call BowlingPlayLaunch3D
|
||||
cmp bpBallVX3D,0
|
||||
jne bp_mass_test_fail
|
||||
mov eax,bpLaunchSpeed3D
|
||||
mov bpMassTestSamples[edi+8],eax
|
||||
mov eax,bpInvMass3D[40]
|
||||
mov bpMassTestSamples[edi+12],eax
|
||||
mov eax,bpBallVY3D
|
||||
mov bpMassTestSamples[edi+16],eax
|
||||
mov bpPinVY3D[40],eax
|
||||
mov bpPinVX3D[40],0
|
||||
mov bpPinX3D[40],0
|
||||
mov bpPinY3D[40],FP_1*42/10
|
||||
mov bpPinX3D,0
|
||||
mov bpPinY3D,4*FP_1
|
||||
invoke BowlingPlayContact3D,0,10
|
||||
mov eax,bpPinVY3D[40]
|
||||
mov bpMassTestSamples[edi+20],eax
|
||||
mov eax,bpPinVY3D
|
||||
mov bpMassTestSamples[edi+24],eax
|
||||
mov eax,bpShotWeightKg3D
|
||||
mov bpMassTestSamples[edi+28],eax
|
||||
add edi,32
|
||||
inc power
|
||||
cmp power,3
|
||||
jb bp_mass_sample
|
||||
mov power,0
|
||||
inc kg
|
||||
cmp kg,7
|
||||
jbe bp_mass_sample
|
||||
invoke CreateFileA,OFFSET bpMassTestPath,40000000h,0,0,2,80h,0
|
||||
mov handle,eax
|
||||
invoke WriteFile,handle,OFFSET bpMassTestSamples,SIZEOF bpMassTestSamples,ADDR count,0
|
||||
invoke CloseHandle,handle
|
||||
; Exercise complete high-power rolls across all selectable masses.
|
||||
mov kg,4
|
||||
mov aim,0
|
||||
xor edi,edi
|
||||
bp_mass_shot:
|
||||
call ResetBowlingPlay3D
|
||||
mov eax,kg
|
||||
mov bpWeightKg3D,eax
|
||||
mov bpMassShots[edi],eax
|
||||
mov eax,aim
|
||||
mov eax,bpFeelSampleAim[eax*4]
|
||||
mov bpLockedAim3D,eax
|
||||
mov bpMassShots[edi+4],eax
|
||||
mov bpLockedPower3D,100
|
||||
call BowlingPlayLaunch3D
|
||||
mov esi,900
|
||||
bp_mass_shot_tick:
|
||||
call BowlingPlayStep3D
|
||||
xor ebx,ebx
|
||||
bp_mass_shot_bounds:
|
||||
mov eax,bpPinX3D[ebx*4]
|
||||
cmp eax,-FP_1
|
||||
jl bp_mass_test_fail
|
||||
cmp eax,FP_1
|
||||
jg bp_mass_test_fail
|
||||
mov eax,bpPinY3D[ebx*4]
|
||||
cmp eax,3*FP_1
|
||||
jl bp_mass_test_fail
|
||||
cmp eax,FP_1*55/10
|
||||
jg bp_mass_test_fail
|
||||
inc ebx
|
||||
cmp ebx,10
|
||||
jb bp_mass_shot_bounds
|
||||
dec esi
|
||||
jnz bp_mass_shot_tick
|
||||
call BowlingPlayReady3D
|
||||
cmp eax,1
|
||||
jne bp_mass_test_fail
|
||||
mov eax,bpHitMask3D
|
||||
mov bpMassShots[edi+8],eax
|
||||
add edi,12
|
||||
inc aim
|
||||
cmp aim,21
|
||||
jb bp_mass_shot
|
||||
mov aim,0
|
||||
inc kg
|
||||
cmp kg,7
|
||||
jbe bp_mass_shot
|
||||
invoke CreateFileA,OFFSET bpMassShotsPath,40000000h,0,0,2,80h,0
|
||||
mov handle,eax
|
||||
invoke WriteFile,handle,OFFSET bpMassShots,SIZEOF bpMassShots,ADDR count,0
|
||||
invoke CloseHandle,handle
|
||||
mov expansionStage,185
|
||||
call ResetBowlingPlay3D
|
||||
mov bpWeightKg3D,7
|
||||
mov bpLockedAim3D,0
|
||||
mov bpLockedPower3D,70
|
||||
call BowlingPlayLaunch3D
|
||||
mov eax,bpInvMass3D[40]
|
||||
mov inverse,eax
|
||||
mov bpWeightKg3D,4
|
||||
mov pressedKeys3D[31h],1
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpShotWeightKg3D,7
|
||||
jne bp_mass_test_fail
|
||||
mov eax,bpInvMass3D[40]
|
||||
cmp eax,inverse
|
||||
jne bp_mass_test_fail
|
||||
cmp bpState3D,BP_RELEASE
|
||||
jne bp_mass_test_fail
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,OFFSET bpMassTestLockedPath
|
||||
mov bwTurn3D[4],1
|
||||
mov bpWeightKg3D,7
|
||||
call BowlingPlayLaunch3D
|
||||
cmp bpShotWeightKg3D,6
|
||||
jne bp_mass_test_fail
|
||||
cmp bpWeightKg3D,7
|
||||
jne bp_mass_test_fail
|
||||
call LeaveBowlingPlay3D
|
||||
invoke BeginBowlingPlay3D,2
|
||||
call RenderBowlingPlay3D
|
||||
invoke ExpansionSnapshot,OFFSET bpMassTestRackPairPath
|
||||
mov eax,bpRackHitY3D[12]
|
||||
shl eax,17
|
||||
mov edx,bpRackHitX3D[12]
|
||||
shl edx,1
|
||||
or eax,edx
|
||||
invoke WindowEvents3D,0,201h,1,eax
|
||||
call HandleBowlingPlay3D
|
||||
cmp bpWeightKg3D,7
|
||||
jne bp_mass_test_fail
|
||||
cmp bpState3D,BP_DIRECTION
|
||||
jne bp_mass_test_fail
|
||||
call LeaveBowlingPlay3D
|
||||
invoke BowlingCanWalk3D,FP_1*45/10,FP_1*257/10
|
||||
test eax,eax
|
||||
jnz bp_mass_test_fail
|
||||
ret
|
||||
bp_mass_test_fail:
|
||||
invoke ExitProcess,expansionStage
|
||||
ret
|
||||
BowlingWeightNativeTests ENDP
|
||||
|
|
@ -42,6 +42,7 @@ def prepare():
|
|||
code += "\n" + expand("src_graphics/rooftop.inc")
|
||||
code += "\n" + expand("src_graphics/bowling.inc")
|
||||
code += "\n" + read("src_graphics/character_cast.inc")
|
||||
code += "\n" + read("src_graphics/npc_visits.inc")
|
||||
code += "\n" + proc(read("src_graphics/scene_animation.inc"),"LoadAnimPack3D")
|
||||
code += "\n" + proc(read("src_graphics/unavailable.inc"),"BeginUnavailable3D")
|
||||
code += "\n" + read("src_graphics/observer.inc")
|
||||
|
|
@ -75,6 +76,7 @@ def prepare():
|
|||
darts = read("src_graphics/darts_data.inc").replace(
|
||||
"include src_graphics\\darts_art.inc", read("src_graphics/darts_art.inc"))
|
||||
data += "\n" + re.sub(r"^\w+ PROTO[^\n]*\n", "", darts, flags=re.M)
|
||||
data += "\n" + read("src_graphics/npc_visits_data.inc")
|
||||
own_data = set(re.findall(r"^(\w+) (?:dd|db|dw|REAL4|REAL8|AnimPack3D|CityProp3D)\b",data,re.M))
|
||||
own_data.update(re.findall(r"^(\w+) LABEL\b",data,re.M))
|
||||
coff = Coff(ROOT / "build/graphics/poker.obj")
|
||||
|
|
@ -90,7 +92,8 @@ def prepare():
|
|||
"casinoNpcs3D":"NpcMindEntity","hallSpriteTemp3D":"CityProp3D",
|
||||
"hallObjects3D":"CityProp3D","hallLights3D":"CityProp3D",
|
||||
"hallLoungeDecor3D":"CityProp3D","hallGuests3D":"CityProp3D",
|
||||
"npcSprite3D":"CityProp3D","scrStation3D":"CityProp3D"}
|
||||
"npcSprite3D":"CityProp3D","scrStation3D":"CityProp3D",
|
||||
"npcExtraActors3D":"NpcMindEntity"}
|
||||
all_source = "\n".join(read(str(path.relative_to(ROOT))) for path in
|
||||
[ROOT/"casino3d.inc",ROOT/"casino3d_data.inc",*sorted(path for path in
|
||||
(ROOT/"src_graphics").glob("*.inc") if path.name != "renderer.inc")])
|
||||
|
|
@ -137,13 +140,13 @@ def prepare():
|
|||
for dep in re.findall(r"\b[A-Za-z_]\w*",constants[name]):
|
||||
constant(dep)
|
||||
ordered.append(f"{name} equ {constants[name]}")
|
||||
for name in re.findall(r"\b[A-Za-z_]\w*",code+data+read("tools/tests/hall_expansion_test.inc")):
|
||||
for name in re.findall(r"\b[A-Za-z_]\w*",code+data+expand("tools/tests/hall_expansion_test.inc")):
|
||||
constant(name)
|
||||
# Win32 prototypes are not declarations in the helper object.
|
||||
for name,args in re.findall(r"^(\w+)\s+PROTO([^\n]*)",all_source,re.M):
|
||||
protos.setdefault(name,args.count(":DWORD"))
|
||||
protos.update({"ExitProcess":1,"WriteFile":5,"GetTickCount":0,"SetUnhandledExceptionFilter":1,
|
||||
"CreateDirectoryA":2})
|
||||
"CreateDirectoryA":2,"mciSendStringA":4})
|
||||
header = ".386\n.model flat\noption casemap:none\n" + "\n".join(structures+ordered+externs)
|
||||
header += "\noption language:stdcall\n" + "\n".join(
|
||||
name+" PROTO"+(" "+",".join([":DWORD"]*size) if size else "")
|
||||
|
|
@ -223,6 +226,10 @@ def check_bowling_room():
|
|||
return False
|
||||
if 2 <= x <= 17.3 and y < 22.3:
|
||||
return False
|
||||
if 26 <= y <= 26.6 and any(abs(x-(3.95+3.8*i)) <= .4 for i in range(4)):
|
||||
return False
|
||||
if 25.2 <= y <= 26.6 and any(.25 <= x-(3.95+3.8*i) <= .85 for i in range(4)):
|
||||
return False
|
||||
return not any(a <= x <= b and c <= y <= d for a,b,c,d in layout["collisions"])
|
||||
start = (68,120)
|
||||
reached,pending = {start},[start]
|
||||
|
|
@ -248,18 +255,118 @@ def check_bowling_room():
|
|||
assert len(captures) >= 10
|
||||
for a,b,region in (
|
||||
("direction","direction-left",(180,314,462,414)),
|
||||
("power","power-low",(536,154,596,408)),
|
||||
("power","power-low",(42,154,102,408)),
|
||||
):
|
||||
images = [Image.open(OUT/f"bowling-play-{name}.bmp").convert("RGB").crop(region) for name in (a,b)]
|
||||
assert ImageChops.difference(*images).getbbox(), (a,b,"timing indicator must move")
|
||||
print("PASS: playable bowling gates, collision solver, frame-rate invariance, remaining racks, bonus balls, opponent and score sheet")
|
||||
sample_data = (OUT/'bowling-physics-samples.bin').read_bytes()
|
||||
shots = list(struct.iter_unpack('<iiII', sample_data))
|
||||
assert len(shots) == 63
|
||||
assert all(mask < 1024 for _,_,mask,_ in shots)
|
||||
assert len({mask for _,_,mask,_ in shots}) >= 4, 'Aim/power have no physical effect'
|
||||
assert any(power==100 and mask==1023 for _,power,mask,_ in shots), 'No achievable physical strike'
|
||||
assert max(m.bit_count() for _,p,m,_ in shots if p==0) < max(m.bit_count() for _,p,m,_ in shots if p==100)
|
||||
for _,power,mask,_ in shots:
|
||||
assert 0 <= mask.bit_count() <= 10, (power,mask)
|
||||
print('Native pin-count ranges by power:', {p:(min(m.bit_count() for _,power,m,_ in shots if power==p),max(m.bit_count() for _,power,m,_ in shots if power==p)) for p in (0,50,100)})
|
||||
hand = [Image.open(OUT/f'bowling-hand-{i:02}.bmp').convert('RGB') for i in range(33)]
|
||||
assert len({im.crop((320,80,640,440)).tobytes() for im in hand}) >= 25
|
||||
hand[0].save(OUT/'bowling-native-release.gif',save_all=True,append_images=hand[1:],duration=33,loop=0)
|
||||
impacts = [Image.open(OUT/f'bowling-impact-{i}.bmp').convert('RGB') for i in range(4)]
|
||||
assert len({im.tobytes() for im in impacts}) == 4
|
||||
empty = Image.open(OUT/'bowling-shape-empty.bmp').convert('RGB')
|
||||
tiny = Image.open(OUT/'bowling-shape-tiny.bmp').convert('RGB')
|
||||
bounds = ImageChops.difference(empty,tiny).getbbox()
|
||||
assert bounds and 8 <= bounds[2]-bounds[0] <= 120 and 8 <= bounds[3]-bounds[1] <= 120, bounds
|
||||
setter = [Image.open(OUT/f'bowling-pinsetter-{i}.bmp').convert('RGB') for i in range(8)]
|
||||
# A closed guard correctly hides intermediate hoist motion.
|
||||
assert len({im.tobytes() for im in setter}) >= 6
|
||||
setter[0].save(OUT/'bowling-native-pinsetter.gif',save_all=True,append_images=setter[1:],duration=320,loop=0)
|
||||
print('PASS: weak rocking/strong toppling, separating contacts, fallen-pin impulses, late settlement, '
|
||||
'stable unit axes and compact silhouettes after tiny impacts, per-step travel limits, '
|
||||
'guard/hoist/respots, first-ball miss without cycling, no duplicate scoring, '
|
||||
'full X/spare/miss scorecard, 33 native release frames and seven muted MCI channels/cleanup')
|
||||
returned = [Image.open(OUT/f'bowling-return-{i}.bmp').convert('RGB') for i in range(8)]
|
||||
assert len({im.tobytes() for im in returned}) == 8
|
||||
returned[0].save(OUT/'bowling-native-return.gif',save_all=True,append_images=returned[1:],
|
||||
duration=[400,500,100,300,400,500,600,250],loop=0)
|
||||
print('PASS: visible return lift/rails, camera turn on either lane side, input/score invariants, '
|
||||
'pause/resume, final-ball return, return-tray collision and exit restoration')
|
||||
mass = list(struct.iter_unpack('<8i',(OUT/'bowling-mass-samples.bin').read_bytes()))
|
||||
assert len(mass) == 12
|
||||
for kg,power,speed,inv,incoming,ball,pin,locked in mass:
|
||||
assert kg == locked and 4 <= kg <= 7
|
||||
assert abs(inv/65536 - 1.6/kg) < .00002
|
||||
work = kg*(speed/65536)**2/2
|
||||
expected_work = 3*(3+6*power/100)**2
|
||||
assert abs(work/expected_work-1) < .0001,(kg,power,work)
|
||||
assert abs((-incoming*1000/16)/speed-1) < .0003
|
||||
before = kg*incoming
|
||||
after = kg*ball+1.6*pin
|
||||
assert abs((after-before)/before) < .001,(kg,before,after)
|
||||
assert abs((ball-pin)/-incoming-.5) < .002,(kg,ball,pin)
|
||||
assert kg*ball**2+1.6*pin**2 <= kg*incoming**2
|
||||
assert abs(pin/incoming - 1.5*kg/(kg+1.6)) < .002
|
||||
for power in (0,50,100):
|
||||
group = [s for s in mass if s[1] == power]
|
||||
assert all(a[2] > b[2] for a,b in zip(group,group[1:]))
|
||||
assert all(abs(a[5]/a[4]) < abs(b[5]/b[4]) for a,b in zip(group,group[1:]))
|
||||
print('PASS: 4/5/6/7 kg selection, equal-work launch energy, momentum/restitution checks, '
|
||||
'no impact energy gain, immutable shot mass and independent bot weight')
|
||||
held = {kg:Image.open(OUT/f'bowling-weight-{kg}.bmp').convert('RGB') for kg in (4,5,7)}
|
||||
assert len({im.crop((470,310,575,414)).tobytes() for im in held.values()}) == 3
|
||||
rack = Image.open(OUT/'bowling-weight-rack.bmp').convert('RGB')
|
||||
pair = Image.open(OUT/'bowling-weight-rack-pair.bmp').convert('RGB')
|
||||
assert rack.tobytes() != pair.tobytes(), 'Rack selection must use each pair in the actual room'
|
||||
print('PASS: in-world lengthwise ball rack, projected sphere/plate picking on both pairs, '
|
||||
'non-overlapping labels, native colour/alpha checks, unchanged skin/sleeve and storage-rail collision')
|
||||
mass_shots = list(struct.iter_unpack('<iiI',(OUT/'bowling-mass-shots.bin').read_bytes()))
|
||||
assert len(mass_shots) == 84 and all(mask < 1024 for _,_,mask in mass_shots)
|
||||
for kg in (4,5,6,7):
|
||||
masks = [mask for k,_,mask in mass_shots if k == kg]
|
||||
assert len(masks) == 21 and len(set(masks)) >= 4
|
||||
print('Native high-power pin-count ranges by kg:',
|
||||
{kg:(min(mask.bit_count() for k,_,mask in mass_shots if k==kg),
|
||||
max(mask.bit_count() for k,_,mask in mass_shots if k==kg)) for kg in (4,5,6,7)})
|
||||
print(f"PASS: eight bowling lanes, {len(reached)} connected walk points, reachable bar/dining/seats, native throw and room captures")
|
||||
|
||||
|
||||
def check_npc_visits():
|
||||
records = list(struct.iter_unpack('<8I', (OUT/'npc-visits.bin').read_bytes()))
|
||||
assert len(records) == 10 and len({r[2] for r in records}) == 10
|
||||
seen = 0
|
||||
for slot,identity,cast,activities,places,walking,journeys,chips in records:
|
||||
assert slot < 10 and identity < 12 and cast < 10
|
||||
assert walking >= 50 and journeys >= 3 and places.bit_count() >= 2, records
|
||||
assert chips < 100000
|
||||
seen |= activities
|
||||
assert seen & 0x1FE == 0x1FE, hex(seen)
|
||||
captures = []
|
||||
for kind in ('order','drink','seat','win','loss'):
|
||||
picture = Image.open(OUT/f'npc-visit-{kind}.bmp').convert('RGB')
|
||||
assert picture.size == (640,480) and max(ImageStat.Stat(picture).stddev) > 20
|
||||
picture.save(OUT/f'npc-visit-{kind}.png')
|
||||
captures.append(picture)
|
||||
assert captures[0].tobytes() != captures[1].tobytes()
|
||||
assert captures[3].tobytes() != captures[4].tobytes()
|
||||
for action,count in (('sit',10),('rise',9)):
|
||||
frames = [Image.open(OUT/f'npc-chair-{action}-{index}.bmp').convert('RGB')
|
||||
for index in range(count)]
|
||||
assert all(frame.size == (640,480) for frame in frames)
|
||||
assert len({frame.tobytes() for frame in frames}) >= 8, action
|
||||
frames[0].save(OUT/f'npc-chair-{action}.gif',save_all=True,
|
||||
append_images=frames[1:],duration=100,loop=0)
|
||||
print('PASS: ten stable visitor identities, 480 seconds of private schedules, exclusive '
|
||||
'stations, game/bar/rest/chat transitions, grounded chair poses, pause, '
|
||||
'unchanged player bankroll/RNG, real chair approach and sit/rise sequences')
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--parity",action="store_true")
|
||||
parser.add_argument("--bowling-only",action="store_true")
|
||||
parser.add_argument("--npc-only",action="store_true")
|
||||
parser.add_argument("--prove-alpha-regression",action="store_true")
|
||||
parser.add_argument("--prove-seam-regression",action="store_true")
|
||||
parser.add_argument("--prove-distance-regression",action="store_true")
|
||||
|
|
@ -291,6 +398,14 @@ def main():
|
|||
source = source.replace(" call LoadHallAssets3D\n cmp characterCast3D.pixels,0",
|
||||
" call LoadHallAssets3D\n call BowlingNativeTests\n invoke ExitProcess,0\n cmp characterCast3D.pixels,0")
|
||||
(OUT/(stem+".asm")).write_text(source,encoding="cp1251")
|
||||
if args.npc_only:
|
||||
stem = "module-npc"
|
||||
source = (OUT/"module.asm").read_text(encoding="cp1251")
|
||||
source = source.replace("include tools/tests/hall_expansion_test.inc",
|
||||
expand("tools/tests/hall_expansion_test.inc"))
|
||||
source = source.replace(" call LoadHallAssets3D\n cmp characterCast3D.pixels,0",
|
||||
" call LoadHallAssets3D\n call NpcVisitsNativeTests\n invoke ExitProcess,0\n cmp characterCast3D.pixels,0")
|
||||
(OUT/(stem+".asm")).write_text(source,encoding="cp1251")
|
||||
if args.prove_fate_anchor_regression:
|
||||
stem = "module-fate-anchor-regression"
|
||||
source = (OUT/"module.asm").read_text(encoding="cp1251")
|
||||
|
|
@ -347,6 +462,10 @@ def main():
|
|||
f"build/hall-expansion/{stem}.obj","build/hall-expansion/helpers.obj",
|
||||
"kernel32.lib","user32.lib","gdi32.lib","winmm.lib","ws2_32.lib"],cwd=ROOT,check=True)
|
||||
result = subprocess.run([str(OUT/(stem+".exe"))],cwd=ROOT,timeout=360)
|
||||
if args.npc_only:
|
||||
assert result.returncode == 0,result.returncode
|
||||
check_npc_visits()
|
||||
return
|
||||
if args.bowling_only:
|
||||
assert result.returncode == 0,result.returncode
|
||||
check_bowling_room()
|
||||
|
|
@ -373,6 +492,7 @@ def main():
|
|||
if not args.prove_seam_regression:
|
||||
check_rooftop_navigation()
|
||||
check_bowling_room()
|
||||
check_npc_visits()
|
||||
check_character_cast()
|
||||
closed = Image.open(OUT/"fortune-closed.bmp").tobytes()
|
||||
opened = Image.open(OUT/"fortune-open.bmp").tobytes()
|
||||
|
|
|
|||
|
|
@ -1000,8 +1000,9 @@ expansion_long_gait:
|
|||
expansion_gait_bounds:
|
||||
cmp npcWalkDistance3D[edi*4],FP_1*3/4
|
||||
jae expansion_fail
|
||||
imul ebx,edi,SIZEOF NpcMindEntity
|
||||
invoke CanWalk3D,casinoNpcs3D[ebx].posX,casinoNpcs3D[ebx].posY
|
||||
invoke NpcEntity3D,edi
|
||||
mov ebx,eax
|
||||
invoke CanWalk3D,[ebx].NpcMindEntity.posX,[ebx].NpcMindEntity.posY
|
||||
cmp eax,1
|
||||
jne expansion_fail
|
||||
inc edi
|
||||
|
|
@ -1175,6 +1176,7 @@ expansion_leaf_shut:
|
|||
call ExpansionDartsTests
|
||||
call RoofNativeTests
|
||||
call BowlingNativeTests
|
||||
call NpcVisitsNativeTests
|
||||
invoke ExitProcess,0
|
||||
expansion_fail:
|
||||
invoke ExitProcess,expansionStage
|
||||
|
|
@ -1187,3 +1189,4 @@ include tools/tests/darts_hall_test.inc
|
|||
include tools/tests/rooftop_test.inc
|
||||
include tools/tests/bowling_test.inc
|
||||
include tools/tests/character_cast_test.inc
|
||||
include tools/tests/npc_visits_test.inc
|
||||
|
|
|
|||
240
tools/tests/npc_chair_motion_test.inc
Normal file
240
tools/tests/npc_chair_motion_test.inc
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
.data
|
||||
ncTestSit0 db 'build\hall-expansion\npc-chair-sit-0.bmp',0
|
||||
ncTestSit1 db 'build\hall-expansion\npc-chair-sit-1.bmp',0
|
||||
ncTestSit2 db 'build\hall-expansion\npc-chair-sit-2.bmp',0
|
||||
ncTestSit3 db 'build\hall-expansion\npc-chair-sit-3.bmp',0
|
||||
ncTestSit4 db 'build\hall-expansion\npc-chair-sit-4.bmp',0
|
||||
ncTestSit5 db 'build\hall-expansion\npc-chair-sit-5.bmp',0
|
||||
ncTestSit6 db 'build\hall-expansion\npc-chair-sit-6.bmp',0
|
||||
ncTestSit7 db 'build\hall-expansion\npc-chair-sit-7.bmp',0
|
||||
ncTestSit8 db 'build\hall-expansion\npc-chair-sit-8.bmp',0
|
||||
ncTestSit9 db 'build\hall-expansion\npc-chair-sit-9.bmp',0
|
||||
ncTestChat db 'build\hall-expansion\npc-chair-chat.bmp',0
|
||||
ncTestRise0 db 'build\hall-expansion\npc-chair-rise-0.bmp',0
|
||||
ncTestRise1 db 'build\hall-expansion\npc-chair-rise-1.bmp',0
|
||||
ncTestRise2 db 'build\hall-expansion\npc-chair-rise-2.bmp',0
|
||||
ncTestRise3 db 'build\hall-expansion\npc-chair-rise-3.bmp',0
|
||||
ncTestRise4 db 'build\hall-expansion\npc-chair-rise-4.bmp',0
|
||||
ncTestRise5 db 'build\hall-expansion\npc-chair-rise-5.bmp',0
|
||||
ncTestRise6 db 'build\hall-expansion\npc-chair-rise-6.bmp',0
|
||||
ncTestRise7 db 'build\hall-expansion\npc-chair-rise-7.bmp',0
|
||||
ncTestRise8 db 'build\hall-expansion\npc-chair-rise-8.bmp',0
|
||||
ncTestSitPaths dd OFFSET ncTestSit0,OFFSET ncTestSit1,OFFSET ncTestSit2,OFFSET ncTestSit3,OFFSET ncTestSit4
|
||||
dd OFFSET ncTestSit5,OFFSET ncTestSit6,OFFSET ncTestSit7,OFFSET ncTestSit8,OFFSET ncTestSit9
|
||||
ncTestRisePaths dd OFFSET ncTestRise0,OFFSET ncTestRise1,OFFSET ncTestRise2,OFFSET ncTestRise3,OFFSET ncTestRise4
|
||||
dd OFFSET ncTestRise5,OFFSET ncTestRise6,OFFSET ncTestRise7,OFFSET ncTestRise8
|
||||
.code
|
||||
NpcChairMotionNativeTests PROC uses ebx esi edi
|
||||
local startX:DWORD,startY:DWORD,endX:DWORD,endY:DWORD,px:DWORD,py:DWORD
|
||||
local ticks:DWORD,lastX:DWORD,lastY:DWORD
|
||||
mov expansionStage,210
|
||||
call InitNpcLife3D
|
||||
mov playerX,FP_1*305/10
|
||||
mov playerY,FP_1*305/10
|
||||
invoke NpcPlanPath3D,0,7
|
||||
cmp eax,1
|
||||
jne nc_test_fail
|
||||
mov eax,casinoNpcs3D.posX
|
||||
mov startX,eax
|
||||
mov eax,casinoNpcs3D.posY
|
||||
mov startY,eax
|
||||
mov esi,npcLife3D.pathCount
|
||||
nc_test_edge:
|
||||
dec esi
|
||||
mov eax,npcPaths3D[esi*4]
|
||||
mov edx,eax
|
||||
and eax,31
|
||||
shl eax,16
|
||||
add eax,FP_HALF
|
||||
mov endX,eax
|
||||
shr edx,5
|
||||
shl edx,16
|
||||
add edx,FP_HALF
|
||||
mov endY,edx
|
||||
mov edi,1
|
||||
nc_test_edge_sample:
|
||||
mov eax,endX
|
||||
sub eax,startX
|
||||
imul eax,edi
|
||||
sar eax,2
|
||||
add eax,startX
|
||||
mov px,eax
|
||||
mov eax,endY
|
||||
sub eax,startY
|
||||
imul eax,edi
|
||||
sar eax,2
|
||||
add eax,startY
|
||||
mov py,eax
|
||||
invoke CanWalk3D,px,py
|
||||
cmp eax,1
|
||||
jne nc_test_fail
|
||||
inc edi
|
||||
cmp edi,4
|
||||
jbe nc_test_edge_sample
|
||||
mov eax,endX
|
||||
mov startX,eax
|
||||
mov eax,endY
|
||||
mov startY,eax
|
||||
test esi,esi
|
||||
jnz nc_test_edge
|
||||
mov expansionStage,211
|
||||
mov npcLife3D.destination,7
|
||||
mov casinoNpcs3D.posX,FP_1*135/10
|
||||
mov casinoNpcs3D.posY,FP_1*195/10
|
||||
invoke NpcArrive3D,0
|
||||
mov npcSprite3D.posX,FP_1*135/10
|
||||
mov npcSprite3D.posY,FP_1*195/10
|
||||
invoke NpcResolveVisitPose3D,0
|
||||
cmp npcSprite3D.posX,FP_1*135/10
|
||||
jne nc_test_fail
|
||||
cmp npcSprite3D.posY,FP_1*195/10
|
||||
jne nc_test_fail
|
||||
mov expansionStage,212
|
||||
call InitNpcLife3D
|
||||
mov esi,1
|
||||
nc_test_hide:
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov npcLife3D[ebx].state,NPC_AWAY
|
||||
mov npcLife3D[ebx].remaining,1000000
|
||||
invoke NpcReleaseStation3D,esi
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
jb nc_test_hide
|
||||
; The guest from the reported screenshot approaches the chair through gameplay.
|
||||
mov npcLife3D.identity,3
|
||||
invoke NpcReleaseStation3D,0
|
||||
invoke NpcPlanPath3D,0,7
|
||||
cmp eax,1
|
||||
jne nc_test_fail
|
||||
mov npcStationOwner3D[7*4],0
|
||||
mov npcLife3D.state,NPC_WALK
|
||||
mov npcVisitActivity3D,NV_IDLE
|
||||
mov deltaTime3D,16
|
||||
mov ticks,1500
|
||||
nc_test_real_approach:
|
||||
call UpdateNpcLife3D
|
||||
cmp npcLife3D.state,NPC_SIT
|
||||
je nc_test_sit_begin
|
||||
cmp npcLife3D.state,NPC_WALK
|
||||
jne nc_test_fail
|
||||
dec ticks
|
||||
jnz nc_test_real_approach
|
||||
jmp nc_test_fail
|
||||
nc_test_sit_begin:
|
||||
cmp npcSitTime3D,0
|
||||
jne nc_test_fail
|
||||
mov playerX,14*FP_1
|
||||
mov playerY,FP_1*222/10
|
||||
mov playerAngle,384
|
||||
call UpdateInteriorEye3D
|
||||
xor esi,esi
|
||||
mov deltaTime3D,0
|
||||
nc_test_sit_frames:
|
||||
call UpdateNpcLife3D
|
||||
call ExpansionFrame
|
||||
invoke ExpansionSnapshot,ncTestSitPaths[esi*4]
|
||||
mov eax,npcSprite3D.frame
|
||||
xor edx,edx
|
||||
mov ecx,CAST_STRIDE
|
||||
div ecx
|
||||
mov ebx,edx
|
||||
cmp esi,8
|
||||
jae nc_test_sit_hold
|
||||
lea eax,[esi+56]
|
||||
cmp ebx,eax
|
||||
jne nc_test_fail
|
||||
jmp nc_test_sit_anchor
|
||||
nc_test_sit_hold:
|
||||
cmp ebx,12
|
||||
jb nc_test_fail
|
||||
cmp ebx,15
|
||||
ja nc_test_fail
|
||||
nc_test_sit_anchor:
|
||||
mov eax,npcSprite3D.posX
|
||||
test esi,esi
|
||||
jz nc_test_sit_save
|
||||
mov edx,lastX
|
||||
sub edx,eax
|
||||
cmp edx,0
|
||||
jl nc_test_fail
|
||||
cmp edx,FP_1/10
|
||||
jg nc_test_fail
|
||||
nc_test_sit_save:
|
||||
mov lastX,eax
|
||||
mov eax,npcSprite3D.posY
|
||||
mov lastY,eax
|
||||
mov deltaTime3D,100
|
||||
inc esi
|
||||
cmp esi,10
|
||||
jb nc_test_sit_frames
|
||||
mov expansionStage,213
|
||||
; Changing from resting to conversation must not restart the sit-down strip.
|
||||
invoke NpcEntity3D,1
|
||||
mov [eax].NpcMindEntity.posX,FP_1*155/10
|
||||
mov [eax].NpcMindEntity.posY,FP_1*195/10
|
||||
mov npcLife3D[SIZEOF NpcLife3D].state,NPC_SIT
|
||||
invoke NpcAdvanceVisit3D,0
|
||||
cmp npcVisitActivity3D,NV_CHAT
|
||||
jne nc_test_fail
|
||||
cmp npcLife3D.poseClock,0
|
||||
jne nc_test_fail
|
||||
mov npcLife3D[SIZEOF NpcLife3D].state,NPC_AWAY
|
||||
call ExpansionFrame
|
||||
mov eax,npcSprite3D.frame
|
||||
xor edx,edx
|
||||
mov ecx,CAST_STRIDE
|
||||
div ecx
|
||||
cmp edx,16
|
||||
jne nc_test_fail
|
||||
mov eax,npcSprite3D.posX
|
||||
cmp eax,lastX
|
||||
jne nc_test_fail
|
||||
mov eax,npcSprite3D.posY
|
||||
cmp eax,lastY
|
||||
jne nc_test_fail
|
||||
invoke ExpansionSnapshot,OFFSET ncTestChat
|
||||
invoke NpcChooseVisit3D,0
|
||||
cmp eax,1
|
||||
jne nc_test_fail
|
||||
cmp npcRise3D,800
|
||||
jne nc_test_fail
|
||||
mov deltaTime3D,0
|
||||
xor esi,esi
|
||||
nc_test_rise_frames:
|
||||
call UpdateNpcLife3D
|
||||
call ExpansionFrame
|
||||
invoke ExpansionSnapshot,ncTestRisePaths[esi*4]
|
||||
mov eax,npcSprite3D.frame
|
||||
xor edx,edx
|
||||
mov ecx,CAST_STRIDE
|
||||
div ecx
|
||||
mov ebx,edx
|
||||
test esi,esi
|
||||
jnz nc_test_rise_anchor
|
||||
mov eax,npcSprite3D.posX
|
||||
cmp eax,lastX
|
||||
jne nc_test_fail
|
||||
mov eax,npcSprite3D.posY
|
||||
cmp eax,lastY
|
||||
jne nc_test_fail
|
||||
nc_test_rise_anchor:
|
||||
cmp esi,8
|
||||
jae nc_test_rise_end
|
||||
mov eax,63
|
||||
sub eax,esi
|
||||
cmp ebx,eax
|
||||
jne nc_test_fail
|
||||
jmp nc_test_rise_next
|
||||
nc_test_rise_end:
|
||||
cmp ebx,3
|
||||
ja nc_test_fail
|
||||
nc_test_rise_next:
|
||||
mov deltaTime3D,100
|
||||
inc esi
|
||||
cmp esi,9
|
||||
jb nc_test_rise_frames
|
||||
ret
|
||||
nc_test_fail:
|
||||
invoke ExitProcess,expansionStage
|
||||
ret
|
||||
NpcChairMotionNativeTests ENDP
|
||||
|
|
@ -70,8 +70,9 @@ npc_test_simulate:
|
|||
call UpdateNpcLife3D
|
||||
xor esi,esi
|
||||
npc_test_person_bounds:
|
||||
imul ebx,esi,SIZEOF NpcMindEntity
|
||||
invoke CanWalk3D,casinoNpcs3D[ebx].posX,casinoNpcs3D[ebx].posY
|
||||
invoke NpcEntity3D,esi
|
||||
mov ebx,eax
|
||||
invoke CanWalk3D,[ebx].NpcMindEntity.posX,[ebx].NpcMindEntity.posY
|
||||
cmp eax,1
|
||||
jne npc_test_fail
|
||||
imul edi,esi,SIZEOF NpcLife3D
|
||||
|
|
|
|||
268
tools/tests/npc_visits_test.inc
Normal file
268
tools/tests/npc_visits_test.inc
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
.data
|
||||
nvTestPath db 'build\hall-expansion\npc-visits.bin',0
|
||||
nvTestOrder db 'build\hall-expansion\npc-visit-order.bmp',0
|
||||
nvTestDrink db 'build\hall-expansion\npc-visit-drink.bmp',0
|
||||
nvTestSeat db 'build\hall-expansion\npc-visit-seat.bmp',0
|
||||
nvTestWin db 'build\hall-expansion\npc-visit-win.bmp',0
|
||||
nvTestLoss db 'build\hall-expansion\npc-visit-loss.bmp',0
|
||||
; slot, identity, cast, activities, destinations, walking ticks, journeys, chips.
|
||||
nvTestRecords dd NPC_LIFE_COUNT*8 dup(0)
|
||||
.code
|
||||
NpcVisitsNativeTests PROC uses ebx esi edi
|
||||
local ticks:DWORD,bank:DWORD,rng:DWORD,handle:DWORD,count:DWORD,bits:DWORD
|
||||
local savedClock:DWORD,seenResults:DWORD
|
||||
mov expansionStage,200
|
||||
mov hallLevel3D,0
|
||||
mov engineMode,MODE_WALK
|
||||
mov worldMap3D,OFFSET casinoMap
|
||||
mov playerX,FP_1*305/10
|
||||
mov playerY,FP_1*305/10
|
||||
mov eax,bankroll
|
||||
mov bank,eax
|
||||
mov eax,seed
|
||||
mov rng,eax
|
||||
call NpcChairMotionNativeTests
|
||||
call InitNpcLife3D
|
||||
mov bits,0
|
||||
xor esi,esi
|
||||
nv_test_identity:
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
imul edi,esi,32
|
||||
mov nvTestRecords[edi],esi
|
||||
mov eax,npcLife3D[ebx].identity
|
||||
mov nvTestRecords[edi+4],eax
|
||||
mov eax,npcGuestAppearance3D[eax*4]
|
||||
mov nvTestRecords[edi+8],eax
|
||||
bts bits,eax
|
||||
jc nv_test_fail
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
jb nv_test_identity
|
||||
cmp bits,1023
|
||||
jne nv_test_fail
|
||||
xor esi,esi
|
||||
nv_test_paths:
|
||||
invoke NpcPlanPath3D,0,esi
|
||||
cmp eax,1
|
||||
jne nv_test_fail
|
||||
inc esi
|
||||
cmp esi,NPC_DEST_COUNT
|
||||
jb nv_test_paths
|
||||
call InitNpcLife3D
|
||||
mov expansionStage,201
|
||||
mov deltaTime3D,50
|
||||
mov ticks,9600
|
||||
nv_test_tick:
|
||||
call UpdateNpcLife3D
|
||||
xor esi,esi
|
||||
nv_test_person:
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
imul edi,esi,32
|
||||
mov eax,npcLife3D[ebx].identity
|
||||
cmp eax,nvTestRecords[edi+4]
|
||||
jne nv_test_fail
|
||||
cmp npcVisitChips3D[esi*4],0
|
||||
jl nv_test_fail
|
||||
cmp npcVisitChips3D[esi*4],100000
|
||||
ja nv_test_fail
|
||||
mov eax,npcVisitActivity3D[esi*4]
|
||||
cmp eax,NV_YIELD
|
||||
ja nv_test_fail
|
||||
bts nvTestRecords[edi+12],eax
|
||||
mov eax,npcLife3D[ebx].destination
|
||||
cmp eax,NPC_DEST_COUNT
|
||||
jae nv_test_fail
|
||||
cmp npcLife3D[ebx].state,NPC_WALK
|
||||
jne @F
|
||||
inc nvTestRecords[edi+20]
|
||||
jmp nv_test_bounds
|
||||
@@:
|
||||
cmp npcVisitActivity3D[esi*4],NV_IDLE
|
||||
je nv_test_bounds
|
||||
cmp npcVisitActivity3D[esi*4],NV_YIELD
|
||||
je nv_test_bounds
|
||||
bts nvTestRecords[edi+16],eax
|
||||
nv_test_bounds:
|
||||
invoke NpcEntity3D,esi
|
||||
mov ebx,eax
|
||||
invoke CanWalk3D,[ebx].NpcMindEntity.posX,[ebx].NpcMindEntity.posY
|
||||
cmp eax,1
|
||||
jne nv_test_fail
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
jb nv_test_person
|
||||
xor esi,esi
|
||||
mov bits,0
|
||||
nv_test_station:
|
||||
mov eax,npcStationOwner3D[esi*4]
|
||||
cmp eax,-1
|
||||
je nv_test_station_next
|
||||
cmp eax,NPC_LIFE_COUNT
|
||||
jae nv_test_fail
|
||||
bts bits,eax
|
||||
jc nv_test_fail
|
||||
imul ebx,eax,SIZEOF NpcLife3D
|
||||
cmp npcLife3D[ebx].destination,esi
|
||||
jne nv_test_fail
|
||||
cmp npcLife3D[ebx].state,NPC_AWAY
|
||||
je nv_test_fail
|
||||
nv_test_station_next:
|
||||
inc esi
|
||||
cmp esi,NPC_DEST_COUNT
|
||||
jb nv_test_station
|
||||
dec ticks
|
||||
jnz nv_test_tick
|
||||
mov expansionStage,202
|
||||
xor esi,esi
|
||||
nv_test_record:
|
||||
imul edi,esi,32
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov eax,npcLife3D[ebx].routeStep
|
||||
mov nvTestRecords[edi+24],eax
|
||||
mov eax,npcVisitChips3D[esi*4]
|
||||
mov nvTestRecords[edi+28],eax
|
||||
cmp nvTestRecords[edi+20],50
|
||||
jb nv_test_fail
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
jb nv_test_record
|
||||
invoke CreateFileA,OFFSET nvTestPath,40000000h,0,0,2,80h,0
|
||||
mov handle,eax
|
||||
invoke WriteFile,handle,OFFSET nvTestRecords,SIZEOF nvTestRecords,ADDR count,0
|
||||
invoke CloseHandle,handle
|
||||
mov eax,bankroll
|
||||
cmp eax,bank
|
||||
jne nv_test_fail
|
||||
mov eax,seed
|
||||
cmp eax,rng
|
||||
jne nv_test_fail
|
||||
mov eax,npcLifeClock3D
|
||||
mov savedClock,eax
|
||||
mov engineMode,MODE_NPC_DIALOG
|
||||
call UpdateNpcLife3D
|
||||
mov eax,savedClock
|
||||
cmp npcLifeClock3D,eax
|
||||
jne nv_test_fail
|
||||
mov engineMode,MODE_WALK
|
||||
mov hallLevel3D,HALL_ROOF
|
||||
call UpdateNpcLife3D
|
||||
mov eax,savedClock
|
||||
cmp npcLifeClock3D,eax
|
||||
jne nv_test_fail
|
||||
mov hallLevel3D,0
|
||||
mov expansionStage,204
|
||||
call InitNpcLife3D
|
||||
mov esi,1
|
||||
nv_test_yield_clear:
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov npcLife3D[ebx].state,NPC_AWAY
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
jb nv_test_yield_clear
|
||||
invoke NpcReleaseStation3D,0
|
||||
invoke NpcPlanPath3D,0,5
|
||||
cmp eax,1
|
||||
jne nv_test_fail
|
||||
mov npcStationOwner3D[5*4],0
|
||||
mov npcLife3D.state,NPC_WALK
|
||||
mov eax,casinoNpcs3D.posX
|
||||
mov playerX,eax
|
||||
mov eax,casinoNpcs3D.posY
|
||||
mov playerY,eax
|
||||
invoke NpcMove3D,0,16
|
||||
cmp npcVisitActivity3D,NV_YIELD
|
||||
jne nv_test_fail
|
||||
cmp npcLife3D.pathCount,0
|
||||
je nv_test_fail
|
||||
mov ticks,7
|
||||
nv_test_yield_retry:
|
||||
invoke NpcAdvanceVisit3D,0
|
||||
invoke NpcMove3D,0,16
|
||||
dec ticks
|
||||
jnz nv_test_yield_retry
|
||||
cmp npcLife3D.pathCount,0
|
||||
jne nv_test_fail
|
||||
cmp npcStationOwner3D[5*4],-1
|
||||
jne nv_test_fail
|
||||
cmp npcWalkDistance3D,0
|
||||
jne nv_test_fail
|
||||
mov expansionStage,203
|
||||
call InitNpcLife3D
|
||||
xor esi,esi
|
||||
nv_test_hide:
|
||||
imul ebx,esi,SIZEOF NpcLife3D
|
||||
mov npcLife3D[ebx].state,NPC_AWAY
|
||||
inc esi
|
||||
cmp esi,NPC_LIFE_COUNT
|
||||
jb nv_test_hide
|
||||
mov npcLife3D.destination,10
|
||||
mov casinoNpcs3D.posX,FP_1*65/10
|
||||
mov casinoNpcs3D.posY,FP_1*255/10
|
||||
invoke NpcArrive3D,0
|
||||
mov playerX,FP_1*65/10
|
||||
mov playerY,FP_1*282/10
|
||||
mov playerAngle,384
|
||||
call UpdateInteriorEye3D
|
||||
call ExpansionFrame
|
||||
invoke ExpansionSnapshot,OFFSET nvTestOrder
|
||||
invoke NpcAdvanceVisit3D,0
|
||||
cmp npcVisitActivity3D,NV_DRINK
|
||||
jne nv_test_fail
|
||||
mov npcLife3D.poseClock,360
|
||||
call ExpansionFrame
|
||||
invoke ExpansionSnapshot,OFFSET nvTestDrink
|
||||
mov npcLife3D.destination,7
|
||||
mov casinoNpcs3D.posX,FP_1*135/10
|
||||
mov casinoNpcs3D.posY,FP_1*195/10
|
||||
invoke NpcArrive3D,0
|
||||
mov npcLife3D.poseClock,1200
|
||||
mov npcSitTime3D,800
|
||||
mov playerX,13*FP_1
|
||||
mov playerY,FP_1*215/10
|
||||
call ExpansionFrame
|
||||
invoke ExpansionSnapshot,OFFSET nvTestSeat
|
||||
mov npcSprite3D.posX,FP_1*135/10
|
||||
mov npcSprite3D.posY,FP_1*195/10
|
||||
invoke NpcResolveVisitPose3D,0
|
||||
cmp eax,CAST_SEAT
|
||||
jne nv_test_fail
|
||||
cmp npcSprite3D.posX,13*FP_1
|
||||
jne nv_test_fail
|
||||
cmp npcSprite3D.posY,FP_1*195/10-FP_1*35/100
|
||||
jne nv_test_fail
|
||||
mov seenResults,0
|
||||
mov ticks,32
|
||||
mov npcLife3D.destination,2
|
||||
mov casinoNpcs3D.posX,FP_1*105/10
|
||||
mov casinoNpcs3D.posY,FP_1*135/10
|
||||
mov playerX,FP_1*105/10
|
||||
mov playerY,16*FP_1
|
||||
nv_test_result:
|
||||
invoke NpcArrive3D,0
|
||||
invoke NpcAdvanceVisit3D,0
|
||||
mov npcLife3D.poseClock,360
|
||||
call ExpansionFrame
|
||||
cmp npcVisitActivity3D,NV_WIN
|
||||
jne nv_test_loss
|
||||
invoke ExpansionSnapshot,OFFSET nvTestWin
|
||||
or seenResults,1
|
||||
jmp nv_test_result_next
|
||||
nv_test_loss:
|
||||
cmp npcVisitActivity3D,NV_LOSS
|
||||
jne nv_test_fail
|
||||
invoke ExpansionSnapshot,OFFSET nvTestLoss
|
||||
or seenResults,2
|
||||
nv_test_result_next:
|
||||
cmp seenResults,3
|
||||
je nv_test_done
|
||||
dec ticks
|
||||
jnz nv_test_result
|
||||
jmp nv_test_fail
|
||||
nv_test_done:
|
||||
call InitNpcLife3D
|
||||
ret
|
||||
nv_test_fail:
|
||||
invoke ExitProcess,expansionStage
|
||||
ret
|
||||
NpcVisitsNativeTests ENDP
|
||||
include tools/tests/npc_chair_motion_test.inc
|
||||
Loading…
Add table
Reference in a new issue