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
|
static class Program
|
||||||
{
|
{
|
||||||
const string ExpectedPokerSha256 = "3D0237E09CAED350548457BFAB24C4D67D6FAFC3D689C2D87C8BE360B64EC0AF";
|
const string ExpectedPokerSha256 = "536E23BED4055562BC63871826FF44FFED037923A9BE8E0F591131DB4FBD104B";
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
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;
|
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.
|
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
|
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.
|
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.
|
After a completed match, click or Space starts a fresh match.
|
||||||
|
|
||||||
The player game uses an arcade, not regulation-grade, collision approximation:
|
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
|
Each 16-ms fixed tick has four 4-ms collision substeps. Normal impulses include
|
||||||
and pin friction. Gutters latch once entered. Pins knocked by the ball can knock
|
relative velocity, restitution and the ball/pin mass ratio; overlap correction
|
||||||
other pins; removed pins cannot be scored again. The opponent uses the identical
|
does not apply a second impulse to opening contacts. Billiards-style contact
|
||||||
solver, with private lane RNG choosing only its launch aim and power. The camera
|
resolution is reused without changing the billiards module. Contact normals and
|
||||||
follows the rolling ball; the bot uses a full-body shared-cast throwing animation.
|
pin axes retain fractional precision and are renormalized after yaw: even tiny
|
||||||
The blue ball is a native shaded sphere with a procedural marble surface and
|
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.
|
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
|
## Visitor Simulation
|
||||||
|
|
||||||
Each occupied lane owns a timer, rack mask, two players, frame counters and roll
|
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
|
## Sources And Rebuild
|
||||||
|
|
||||||
- `src_graphics/bowling*.inc`: native room and lane simulation.
|
- `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,
|
- `tools/generators/pack_bowling.py`: offline atlas packing, frame normalization,
|
||||||
in-between frames and furniture/collision tables.
|
in-between frames and furniture/collision tables.
|
||||||
- `assets/sprites/bowling/`: retained image-generation sources.
|
- `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,
|
events, stage separation, deterministic impacts at two frame deltas, gutters,
|
||||||
empty/remaining racks, alternating turns, spare feedback, perfect games and the
|
empty/remaining racks, alternating turns, spare feedback, perfect games and the
|
||||||
tenth-frame bonuses, unresolved score cells, scene captures and exit restoration.
|
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
|
The complete hall suite includes the same bowling checks alongside existing
|
||||||
stairs, doors, rooftop, fortune-room, bar and cabaret regressions. `--parity`
|
stairs, doors, rooftop, fortune-room, bar and cabaret regressions. `--parity`
|
||||||
compares the tested procedures with the shipping assembly object.
|
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;
|
The historical twelve-slot NPC journal is preserved for save compatibility;
|
||||||
its appearance mapping resolves to the ten shared visual identities.
|
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
|
||||||
|
|
||||||
- `assets/sprites/characters/person-00-source-v1.png` through `person-09-source-v1.png`:
|
- `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.
|
; Native room, automatic lane simulation and full-body visitors; no AI service.
|
||||||
InitBowling3D PROC uses esi edi
|
InitBowling3D PROC uses esi edi
|
||||||
mov bpActive3D,0
|
mov bpActive3D,0
|
||||||
|
mov bpWeightKg3D,6
|
||||||
|
mov bpBotWeightKg3D,6
|
||||||
call InitBowlingBallSurface3D
|
call InitBowlingBallSurface3D
|
||||||
|
call InitBowlingSetterSurface3D
|
||||||
mov bwClock3D,-1
|
mov bwClock3D,-1
|
||||||
mov bwMonitorClock3D,-1
|
mov bwMonitorClock3D,-1
|
||||||
mov bwSeat3D,0
|
mov bwSeat3D,0
|
||||||
|
|
@ -48,12 +51,18 @@ LoadBowling3D PROC
|
||||||
invoke LoadAnimPack3D,OFFSET bwArt3D,OFFSET bwArtPath3D
|
invoke LoadAnimPack3D,OFFSET bwArt3D,OFFSET bwArtPath3D
|
||||||
invoke ValidateCityPack3D,OFFSET bwArt3D,256,256,14
|
invoke ValidateCityPack3D,OFFSET bwArt3D,256,256,14
|
||||||
call LoadCharacterCast3D
|
call LoadCharacterCast3D
|
||||||
|
invoke LoadAnimPack3D,OFFSET bpHandArt3D,OFFSET bpHandPath3D
|
||||||
|
invoke ValidateCityPack3D,OFFSET bpHandArt3D,256,256,33
|
||||||
|
mov bpRackHandFrame3D,-1
|
||||||
|
mov bpRackHandKg3D,-1
|
||||||
call RefreshBowlingMonitors3D
|
call RefreshBowlingMonitors3D
|
||||||
bw_load_done:
|
bw_load_done:
|
||||||
ret
|
ret
|
||||||
LoadBowling3D ENDP
|
LoadBowling3D ENDP
|
||||||
|
|
||||||
FreeBowling3D PROC
|
FreeBowling3D PROC
|
||||||
|
call BowlingAudioClose3D
|
||||||
|
invoke FreeAnimPack3D,OFFSET bpHandArt3D
|
||||||
invoke FreeAnimPack3D,OFFSET bwArt3D
|
invoke FreeAnimPack3D,OFFSET bwArt3D
|
||||||
invoke FreeAnimPack3D,OFFSET bwMotionArt3D
|
invoke FreeAnimPack3D,OFFSET bwMotionArt3D
|
||||||
invoke FreeAnimPack3D,OFFSET bwSeatedArt3D
|
invoke FreeAnimPack3D,OFFSET bwSeatedArt3D
|
||||||
|
|
@ -62,6 +71,24 @@ FreeBowling3D ENDP
|
||||||
|
|
||||||
ResolveBowlingSurface3D PROC material:DWORD
|
ResolveBowlingSurface3D PROC material:DWORD
|
||||||
mov eax,material
|
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
|
cmp eax,253
|
||||||
jne @F
|
jne @F
|
||||||
mov eax,OFFSET bpBallSurface3D
|
mov eax,OFFSET bpBallSurface3D
|
||||||
|
|
@ -173,6 +200,36 @@ BowlingCanWalk3D PROC uses esi edi px:DWORD,py:DWORD
|
||||||
cmp py,FP_1*223/10
|
cmp py,FP_1*223/10
|
||||||
jb bw_walk_block
|
jb bw_walk_block
|
||||||
bw_walk_furniture:
|
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
|
lea esi,bwCollision3D
|
||||||
mov edi,BOWL_COLLISION_COUNT
|
mov edi,BOWL_COLLISION_COUNT
|
||||||
bw_walk_prop:
|
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_SEAT equ 53
|
||||||
INTERACT_BOWL_WATCH equ 54
|
INTERACT_BOWL_WATCH equ 54
|
||||||
BW_MATERIAL equ 230
|
BW_MATERIAL equ 230
|
||||||
BW_LAST_MATERIAL equ 253
|
BW_LAST_MATERIAL equ 257
|
||||||
BW_LANES equ 8
|
BW_LANES equ 8
|
||||||
BW_LANE_STEP equ FP_1*19/10
|
BW_LANE_STEP equ FP_1*19/10
|
||||||
InitBowling3D PROTO
|
InitBowling3D PROTO
|
||||||
|
|
@ -22,6 +22,7 @@ RenderBowlingLanes3D PROTO
|
||||||
RenderBowlingVisitors3D PROTO
|
RenderBowlingVisitors3D PROTO
|
||||||
DrawBowlingPin3D PROTO :DWORD,:DWORD,:DWORD
|
DrawBowlingPin3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
DrawBowlingBall3D PROTO :DWORD,:DWORD,:DWORD
|
DrawBowlingBall3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
|
DrawBowlingBallAt3D PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
BowlingImpact3D PROTO :DWORD
|
BowlingImpact3D PROTO :DWORD
|
||||||
BowlingRegisterRoll3D PROTO :DWORD,:DWORD
|
BowlingRegisterRoll3D PROTO :DWORD,:DWORD
|
||||||
BowlingScore3D PROTO :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 paused3D,0
|
||||||
mov bwSeat3D,0
|
mov bwSeat3D,0
|
||||||
call ResetBowlingPlay3D
|
call ResetBowlingPlay3D
|
||||||
|
mov bpState3D,BP_SELECT_BALL
|
||||||
|
call BowlingAudioOpen3D
|
||||||
mov eax,1
|
mov eax,1
|
||||||
ret
|
ret
|
||||||
bp_begin_no:
|
bp_begin_no:
|
||||||
|
|
@ -56,6 +58,8 @@ ResetBowlingPlay3D PROC uses ebx esi edi
|
||||||
mov bpScoreOpen3D,0
|
mov bpScoreOpen3D,0
|
||||||
mov bpLast3D,0
|
mov bpLast3D,0
|
||||||
mov bpLastKind3D,0
|
mov bpLastKind3D,0
|
||||||
|
mov bpReactionTime3D,0
|
||||||
|
mov bpAfterReturn3D,BP_DIRECTION
|
||||||
call BowlingPlayRack3D
|
call BowlingPlayRack3D
|
||||||
call ClearKeys3D
|
call ClearKeys3D
|
||||||
mov mouseClick3D,0
|
mov mouseClick3D,0
|
||||||
|
|
@ -77,6 +81,7 @@ BowlingPlayStartAim3D ENDP
|
||||||
LeaveBowlingPlay3D PROC uses esi
|
LeaveBowlingPlay3D PROC uses esi
|
||||||
cmp bpActive3D,0
|
cmp bpActive3D,0
|
||||||
je bp_leave_done
|
je bp_leave_done
|
||||||
|
call BowlingAudioClose3D
|
||||||
mov esi,bpLane3D
|
mov esi,bpLane3D
|
||||||
mov bwBusy3D[esi*4],0
|
mov bwBusy3D[esi*4],0
|
||||||
mov bwRack3D[esi*4],1023
|
mov bwRack3D[esi*4],1023
|
||||||
|
|
@ -109,180 +114,78 @@ bp_rack_pin:
|
||||||
mov bpPinY3D[esi*4],eax
|
mov bpPinY3D[esi*4],eax
|
||||||
mov bpPinVX3D[esi*4],0
|
mov bpPinVX3D[esi*4],0
|
||||||
mov bpPinVY3D[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
|
inc esi
|
||||||
cmp esi,10
|
cmp esi,10
|
||||||
jb bp_rack_pin
|
jb bp_rack_pin
|
||||||
mov bpHitMask3D,0
|
mov bpHitMask3D,0
|
||||||
mov bpGutter3D,0
|
mov bpGutter3D,0
|
||||||
mov bpAccumulator3D,0
|
mov bpAccumulator3D,0
|
||||||
mov bpBallX3D,0
|
mov bpPhysicsTicks3D,0
|
||||||
mov bpBallY3D,FP_1*225/10
|
mov bpEndTicks3D,0
|
||||||
|
mov bpImpactEnergy3D,0
|
||||||
|
mov bpImpactCooldown3D,0
|
||||||
|
mov bpAudioReleased3D,0
|
||||||
|
mov bpBallX3D,FP_1/2
|
||||||
|
mov bpBallY3D,24*FP_1
|
||||||
ret
|
ret
|
||||||
BowlingPlayRack3D ENDP
|
BowlingPlayRack3D ENDP
|
||||||
|
|
||||||
BowlingPlayLaunch3D PROC
|
BowlingPlayLaunch3D PROC
|
||||||
|
local speed:DWORD,aimX:DWORD,aimLength:REAL8
|
||||||
mov bpState3D,BP_RELEASE
|
mov bpState3D,BP_RELEASE
|
||||||
mov bpTime3D,0
|
mov bpTime3D,0
|
||||||
mov bpAccumulator3D,0
|
mov bpAccumulator3D,0
|
||||||
|
call BowlingApplyBallMass3D
|
||||||
mov eax,bpLockedPower3D
|
mov eax,bpLockedPower3D
|
||||||
imul eax,6*FP_1
|
imul eax,6*FP_1
|
||||||
cdq
|
cdq
|
||||||
mov ecx,100
|
mov ecx,100
|
||||||
idiv ecx
|
idiv ecx
|
||||||
add eax,3*FP_1
|
add eax,3*FP_1
|
||||||
imul eax,16
|
mov speed,eax
|
||||||
cdq
|
; The gauge fixes launch work, calibrated to the existing six-kilogram ball.
|
||||||
mov ecx,1000
|
; v = v_reference * sqrt(m_reference / m); no mass-dependent aim noise.
|
||||||
idiv ecx
|
fild bpReferenceKg3D
|
||||||
mov ecx,eax
|
fidiv bpShotWeightKg3D
|
||||||
neg eax
|
fsqrt
|
||||||
mov bpBallVY3D,eax
|
fimul speed
|
||||||
|
fist bpLaunchSpeed3D
|
||||||
|
fimul bpTickMs3D
|
||||||
|
fidiv bpSecondMs3D
|
||||||
|
fistp speed
|
||||||
mov eax,bpLockedAim3D
|
mov eax,bpLockedAim3D
|
||||||
imul ecx
|
sub eax,bpBallX3D
|
||||||
mov ecx,18*FP_1
|
mov aimX,eax
|
||||||
idiv ecx
|
fild aimX
|
||||||
mov bpBallVX3D,eax
|
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
|
ret
|
||||||
BowlingPlayLaunch3D ENDP
|
BowlingPlayLaunch3D ENDP
|
||||||
|
|
||||||
BowlingPlayHit3D PROC uses esi pin:DWORD,vx:DWORD,vy:DWORD
|
include src_graphics\bowling_physics.inc
|
||||||
mov esi,pin
|
include src_graphics\bowling_audio.inc
|
||||||
mov ecx,esi
|
include src_graphics\bowling_return.inc
|
||||||
mov eax,1
|
include src_graphics\bowling_weight.inc
|
||||||
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
|
|
||||||
|
|
||||||
BowlingPlayFinishRoll3D PROC uses esi
|
BowlingPlayFinishRoll3D PROC uses esi
|
||||||
mov eax,bpHitMask3D
|
mov eax,bpHitMask3D
|
||||||
|
|
@ -296,6 +199,12 @@ bp_finish_count:
|
||||||
jmp bp_finish_count
|
jmp bp_finish_count
|
||||||
bp_finish_register:
|
bp_finish_register:
|
||||||
mov bpLast3D,ecx
|
mov bpLast3D,ecx
|
||||||
|
mov bpReaction3D,CAST_TALK
|
||||||
|
cmp ecx,7
|
||||||
|
jb @F
|
||||||
|
mov bpReaction3D,CAST_CHEER
|
||||||
|
@@:
|
||||||
|
mov bpReactionTime3D,6500
|
||||||
mov bpLastKind3D,0
|
mov bpLastKind3D,0
|
||||||
mov esi,bpLane3D
|
mov esi,bpLane3D
|
||||||
cmp bwBall3D[esi*4],1
|
cmp bwBall3D[esi*4],1
|
||||||
|
|
@ -313,7 +222,17 @@ bp_finish_strike:
|
||||||
jne bp_finish_register_score
|
jne bp_finish_register_score
|
||||||
mov bpLastKind3D,1
|
mov bpLastKind3D,1
|
||||||
bp_finish_register_score:
|
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 bpState3D,BP_SETTLE
|
||||||
mov bpTime3D,0
|
mov bpTime3D,0
|
||||||
mov bwMonitorClock3D,-1
|
mov bwMonitorClock3D,-1
|
||||||
|
|
@ -356,7 +275,16 @@ bp_next_ready:
|
||||||
BowlingPlayNext3D ENDP
|
BowlingPlayNext3D ENDP
|
||||||
|
|
||||||
HandleBowlingPlay3D PROC uses ebx esi
|
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
|
invoke Pressed3D,9
|
||||||
test eax,eax
|
test eax,eax
|
||||||
jz @F
|
jz @F
|
||||||
|
|
@ -364,6 +292,7 @@ HandleBowlingPlay3D PROC uses ebx esi
|
||||||
@@:
|
@@:
|
||||||
mov eax,mouseClick3D
|
mov eax,mouseClick3D
|
||||||
mov click,eax
|
mov click,eax
|
||||||
|
mov mousePress,eax
|
||||||
mov mouseClick3D,0
|
mov mouseClick3D,0
|
||||||
cmp click,0
|
cmp click,0
|
||||||
je @F
|
je @F
|
||||||
|
|
@ -383,6 +312,7 @@ HandleBowlingPlay3D PROC uses ebx esi
|
||||||
cmp click,0
|
cmp click,0
|
||||||
je bp_handle_done
|
je bp_handle_done
|
||||||
call ResetBowlingPlay3D
|
call ResetBowlingPlay3D
|
||||||
|
mov bpState3D,BP_SELECT_BALL
|
||||||
ret
|
ret
|
||||||
bp_handle_clock:
|
bp_handle_clock:
|
||||||
mov eax,deltaTime3D
|
mov eax,deltaTime3D
|
||||||
|
|
@ -393,8 +323,23 @@ bp_handle_clock:
|
||||||
mov elapsed,eax
|
mov elapsed,eax
|
||||||
add bpClock3D,eax
|
add bpClock3D,eax
|
||||||
add bpTime3D,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
|
cmp bpState3D,BP_DIRECTION
|
||||||
jne bp_handle_power
|
jne bp_handle_power
|
||||||
|
invoke HandleBowlingWeight3D,mousePress
|
||||||
|
test eax,eax
|
||||||
|
jnz bp_handle_done
|
||||||
mov eax,bpClock3D
|
mov eax,bpClock3D
|
||||||
xor edx,edx
|
xor edx,edx
|
||||||
mov ecx,4
|
mov ecx,4
|
||||||
|
|
@ -437,7 +382,7 @@ bp_handle_release:
|
||||||
cmp bpState3D,BP_RELEASE
|
cmp bpState3D,BP_RELEASE
|
||||||
jne bp_handle_roll
|
jne bp_handle_roll
|
||||||
mov esi,bpLane3D
|
mov esi,bpLane3D
|
||||||
mov ecx,350
|
mov ecx,BP_RELEASE_MS
|
||||||
cmp bwTurn3D[esi*4],0
|
cmp bwTurn3D[esi*4],0
|
||||||
je @F
|
je @F
|
||||||
mov ecx,2400
|
mov ecx,2400
|
||||||
|
|
@ -457,25 +402,52 @@ bp_handle_fixed_step:
|
||||||
jb bp_handle_roll_end
|
jb bp_handle_roll_end
|
||||||
sub bpAccumulator3D,16
|
sub bpAccumulator3D,16
|
||||||
call BowlingPlayStep3D
|
call BowlingPlayStep3D
|
||||||
cmp bpBallY3D,3*FP_1
|
call BowlingPlayReady3D
|
||||||
jl bp_handle_impact_done
|
test eax,eax
|
||||||
|
jnz bp_handle_impact_done
|
||||||
jmp bp_handle_fixed_step
|
jmp bp_handle_fixed_step
|
||||||
bp_handle_roll_end:
|
bp_handle_roll_end:
|
||||||
cmp bpBallY3D,3*FP_1
|
jmp bp_handle_done
|
||||||
jl bp_handle_impact_done
|
|
||||||
cmp bpTime3D,12000
|
|
||||||
jb bp_handle_done
|
|
||||||
bp_handle_impact_done:
|
bp_handle_impact_done:
|
||||||
call BowlingPlayFinishRoll3D
|
call BowlingPlayFinishRoll3D
|
||||||
ret
|
ret
|
||||||
bp_handle_settle:
|
bp_handle_settle:
|
||||||
cmp bpState3D,BP_SETTLE
|
cmp bpState3D,BP_SETTLE
|
||||||
jne bp_handle_bot
|
jne bp_handle_reset
|
||||||
cmp bpTime3D,1800
|
cmp bpTime3D,1600
|
||||||
jb bp_handle_done
|
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
|
ret
|
||||||
bp_handle_bot:
|
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
|
cmp bpState3D,BP_BOT
|
||||||
jne bp_handle_done
|
jne bp_handle_done
|
||||||
cmp bpTime3D,1100
|
cmp bpTime3D,1100
|
||||||
|
|
@ -501,6 +473,7 @@ bp_handle_bot:
|
||||||
mov bpLockedPower3D,eax
|
mov bpLockedPower3D,eax
|
||||||
call BowlingPlayLaunch3D
|
call BowlingPlayLaunch3D
|
||||||
bp_handle_done:
|
bp_handle_done:
|
||||||
|
call BowlingAudioUpdate3D
|
||||||
ret
|
ret
|
||||||
HandleBowlingPlay3D ENDP
|
HandleBowlingPlay3D ENDP
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,37 @@ BP_ROLL equ 3
|
||||||
BP_SETTLE equ 4
|
BP_SETTLE equ 4
|
||||||
BP_BOT equ 5
|
BP_BOT equ 5
|
||||||
BP_FINISHED equ 6
|
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
|
BeginBowlingPlay3D PROTO :DWORD
|
||||||
LeaveBowlingPlay3D PROTO
|
LeaveBowlingPlay3D PROTO
|
||||||
ResetBowlingPlay3D PROTO
|
ResetBowlingPlay3D PROTO
|
||||||
|
|
@ -23,7 +54,17 @@ DrawBowlingPlayPin3D PROTO :DWORD,:DWORD
|
||||||
BowlingFrameTotal3D PROTO :DWORD,:DWORD
|
BowlingFrameTotal3D PROTO :DWORD,:DWORD
|
||||||
DrawBowlingPlayScores3D PROTO
|
DrawBowlingPlayScores3D PROTO
|
||||||
InitBowlingBallSurface3D PROTO
|
InitBowlingBallSurface3D PROTO
|
||||||
|
InitBowlingSetterSurface3D PROTO
|
||||||
DrawBowlingGaugeLine3D PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
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
|
.data
|
||||||
bpActive3D dd 0
|
bpActive3D dd 0
|
||||||
bpLane3D dd 1
|
bpLane3D dd 1
|
||||||
|
|
@ -35,6 +76,23 @@ bpAim3D dd 0
|
||||||
bpPower3D dd 50
|
bpPower3D dd 50
|
||||||
bpLockedAim3D dd 0
|
bpLockedAim3D dd 0
|
||||||
bpLockedPower3D dd 50
|
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
|
bpLast3D dd 0
|
||||||
bpLastKind3D dd 0
|
bpLastKind3D dd 0
|
||||||
bpGutter3D dd 0
|
bpGutter3D dd 0
|
||||||
|
|
@ -45,19 +103,66 @@ bpBallY3D dd 0
|
||||||
bpBallVX3D dd 0
|
bpBallVX3D dd 0
|
||||||
bpBallVY3D dd 0
|
bpBallVY3D dd 0
|
||||||
bpHitMask3D dd 0
|
bpHitMask3D dd 0
|
||||||
bpPinX3D dd 10 dup(0)
|
; Inverse masses are Q16, normalized to a 1600-gram pin. Last body is the ball.
|
||||||
bpPinY3D dd 10 dup(0)
|
bpPinX3D dd BP_BODY_COUNT dup(0)
|
||||||
bpPinVX3D dd 10 dup(0)
|
bpPinY3D dd BP_BODY_COUNT dup(0)
|
||||||
bpPinVY3D dd 10 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
|
bpCentre3D dd 0
|
||||||
bpHomeX3D dd 0
|
bpHomeX3D dd 0
|
||||||
bpHomeY3D dd 0
|
bpHomeY3D dd 0
|
||||||
bpHomeAngle3D dd 0
|
bpHomeAngle3D dd 0
|
||||||
bpText3D db 24 dup(0)
|
bpText3D db 24 dup(0)
|
||||||
bpMonitorTexts3D dd OFFSET bpDirectionText,OFFSET bpPowerText,OFFSET bpRollText,OFFSET bpRollText
|
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?
|
.data?
|
||||||
bpBallSurface3D dd 64*64 dup(?)
|
bpBallSurface3D dd 4*64*64 dup(?)
|
||||||
|
bpTintedHandPixels3D dd 256*256 dup(?)
|
||||||
|
bpSetterSurface3D dd 64*64 dup(?)
|
||||||
.data
|
.data
|
||||||
bpPlayPrompt db 200,195,208,192,210,220,32,194,32,193,206,211,203,200,205,195,0
|
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
|
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
|
bpGutterText db 198,197,203,206,193,0
|
||||||
bpStrikeText db 209,210,208,192,201,202,0
|
bpStrikeText db 209,210,208,192,201,202,0
|
||||||
bpSpareText db 209,207,221,208,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
|
.code
|
||||||
|
|
|
||||||
|
|
@ -34,44 +34,97 @@ bp_ball_tex_pixel:
|
||||||
inc esi
|
inc esi
|
||||||
cmp esi,64
|
cmp esi,64
|
||||||
jb bp_ball_tex_row
|
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
|
ret
|
||||||
InitBowlingBallSurface3D ENDP
|
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
|
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 esi,pin
|
||||||
mov ecx,esi
|
invoke BowlingPinsetterPose3D,esi
|
||||||
mov ebx,1
|
test eax,eax
|
||||||
shl ebx,cl
|
|
||||||
mov edi,bpLane3D
|
|
||||||
test bwRack3D[edi*4],ebx
|
|
||||||
jz bp_pin_done
|
jz bp_pin_done
|
||||||
mov eax,bpPinX3D[esi*4]
|
mov eax,bpVisualPinX3D
|
||||||
add eax,centre
|
add eax,centre
|
||||||
mov x,eax
|
mov baseX,eax
|
||||||
mov eax,bpPinY3D[esi*4]
|
mov eax,bpVisualPinY3D
|
||||||
mov y,eax
|
mov baseY,eax
|
||||||
mov headY,eax
|
mov eax,bpVisualPinTilt3D
|
||||||
mov z,FP_1*15/100
|
shr eax,8
|
||||||
mov ry,FP_1/10
|
cmp eax,128
|
||||||
mov rz,FP_1*13/100
|
jbe @F
|
||||||
test bpHitMask3D,ebx
|
mov eax,128
|
||||||
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
|
|
||||||
@@:
|
@@:
|
||||||
invoke DrawRoofEllipsoid3D,x,headY,eax,FP_1*65/1000,FP_1*65/1000,FP_1*6/100,239
|
mov edi,tableSin[eax*4]
|
||||||
mov eax,z
|
mov ecx,edi
|
||||||
add eax,rz
|
neg ecx
|
||||||
invoke DrawRoofEllipsoid3D,x,headY,eax,FP_1*45/1000,FP_1*45/1000,FP_1*25/1000,240
|
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:
|
bp_pin_done:
|
||||||
ret
|
ret
|
||||||
DrawBowlingPlayPin3D ENDP
|
DrawBowlingPlayPin3D ENDP
|
||||||
|
|
@ -126,59 +179,7 @@ bp_frame_pending:
|
||||||
ret
|
ret
|
||||||
BowlingFrameTotal3D ENDP
|
BowlingFrameTotal3D ENDP
|
||||||
|
|
||||||
DrawBowlingPlayScores3D PROC uses ebx esi edi
|
include src_graphics\bowling_scorecard.inc
|
||||||
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
|
|
||||||
|
|
||||||
DrawBowlingGaugeLine3D PROC uses ebx esi edi x0:DWORD,y0:DWORD,x1:DWORD,y1:DWORD
|
DrawBowlingGaugeLine3D PROC uses ebx esi edi x0:DWORD,y0:DWORD,x1:DWORD,y1:DWORD
|
||||||
local px:DWORD,py:DWORD,stepX:DWORD,stepY:DWORD
|
local px:DWORD,py:DWORD,stepX:DWORD,stepY:DWORD
|
||||||
|
|
@ -235,6 +236,8 @@ bp_gauge_line:
|
||||||
ret
|
ret
|
||||||
DrawBowlingGaugeLine3D ENDP
|
DrawBowlingGaugeLine3D ENDP
|
||||||
|
|
||||||
|
include src_graphics\bowling_performance.inc
|
||||||
|
|
||||||
RenderBowlingPlay3D PROC uses ebx esi edi
|
RenderBowlingPlay3D PROC uses ebx esi edi
|
||||||
local x:DWORD,y:DWORD,color:DWORD,owner:DWORD,startY:DWORD
|
local x:DWORD,y:DWORD,color:DWORD,owner:DWORD,startY:DWORD
|
||||||
mov eax,bpCentre3D
|
mov eax,bpCentre3D
|
||||||
|
|
@ -252,6 +255,8 @@ RenderBowlingPlay3D PROC uses ebx esi edi
|
||||||
cmp bpState3D,BP_ROLL
|
cmp bpState3D,BP_ROLL
|
||||||
je bp_camera_follow
|
je bp_camera_follow
|
||||||
cmp bpState3D,BP_SETTLE
|
cmp bpState3D,BP_SETTLE
|
||||||
|
je bp_camera_follow
|
||||||
|
cmp bpState3D,BP_RESET
|
||||||
jne bp_camera_ready
|
jne bp_camera_ready
|
||||||
bp_camera_follow:
|
bp_camera_follow:
|
||||||
mov eax,bpBallY3D
|
mov eax,bpBallY3D
|
||||||
|
|
@ -262,6 +267,40 @@ bp_camera_follow:
|
||||||
@@:
|
@@:
|
||||||
mov playerY,eax
|
mov playerY,eax
|
||||||
mov viewEye3D,FP_1*7/10
|
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
|
cmp bpState3D,BP_ROLL
|
||||||
jne bp_camera_ready
|
jne bp_camera_ready
|
||||||
mov ebx,bpTime3D
|
mov ebx,bpTime3D
|
||||||
|
|
@ -274,15 +313,48 @@ bp_camera_follow:
|
||||||
idiv ecx
|
idiv ecx
|
||||||
add eax,startY
|
add eax,startY
|
||||||
mov playerY,eax
|
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
|
cdq
|
||||||
idiv ecx
|
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
|
mov edx,HALL_STANDING_EYE
|
||||||
sub edx,eax
|
sub edx,eax
|
||||||
mov viewEye3D,edx
|
mov viewEye3D,edx
|
||||||
bp_camera_ready:
|
@@:
|
||||||
call UpdateCamera3D
|
call UpdateCamera3D
|
||||||
call RenderBowling3D
|
call RenderBowling3D
|
||||||
|
call RenderBowlingPinsetter3D
|
||||||
mov esi,bpLane3D
|
mov esi,bpLane3D
|
||||||
cmp bwTurn3D[esi*4],1
|
cmp bwTurn3D[esi*4],1
|
||||||
jne bp_render_ball
|
jne bp_render_ball
|
||||||
|
|
@ -306,12 +378,31 @@ bp_render_bot_draw:
|
||||||
mov bwActor3D.posY,FP_1*235/10
|
mov bwActor3D.posY,FP_1*235/10
|
||||||
invoke DrawCityObject3D,OFFSET bwActor3D,0
|
invoke DrawCityObject3D,OFFSET bwActor3D,0
|
||||||
bp_render_ball:
|
bp_render_ball:
|
||||||
|
call RenderBowlingReactions3D
|
||||||
|
cmp bpState3D,BP_SELECT_BALL
|
||||||
|
je bp_render_hud
|
||||||
cmp bpState3D,BP_FINISHED
|
cmp bpState3D,BP_FINISHED
|
||||||
je bp_render_hud
|
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
|
mov eax,bpBallX3D
|
||||||
add eax,bpCentre3D
|
add eax,bpCentre3D
|
||||||
invoke DrawBowlingBall3D,eax,bpBallY3D,253
|
mov x,eax
|
||||||
|
invoke BowlingBallMaterial3D,bpShotWeightKg3D
|
||||||
|
invoke DrawBowlingBall3D,x,bpBallY3D,eax
|
||||||
bp_render_hud:
|
bp_render_hud:
|
||||||
|
call DrawBowlingPlayerHand3D
|
||||||
invoke DrawBox,0,0,320,17,00121B20h
|
invoke DrawBox,0,0,320,17,00121B20h
|
||||||
invoke DrawString8x8,8,4,OFFSET bpTitle,00E8D7ADh
|
invoke DrawString8x8,8,4,OFFSET bpTitle,00E8D7ADh
|
||||||
mov eax,bpLane3D
|
mov eax,bpLane3D
|
||||||
|
|
@ -338,7 +429,10 @@ bp_render_hud:
|
||||||
mov ebx,owner
|
mov ebx,owner
|
||||||
mov eax,bwFrames3D[ebx*4]
|
mov eax,bwFrames3D[ebx*4]
|
||||||
cmp bpState3D,BP_SETTLE
|
cmp bpState3D,BP_SETTLE
|
||||||
|
je bp_frame_result
|
||||||
|
cmp bpState3D,BP_RESET
|
||||||
jne @F
|
jne @F
|
||||||
|
bp_frame_result:
|
||||||
cmp bwFrameDone3D[esi*4],0
|
cmp bwFrameDone3D[esi*4],0
|
||||||
je @F
|
je @F
|
||||||
dec eax
|
dec eax
|
||||||
|
|
@ -353,12 +447,24 @@ bp_render_hud:
|
||||||
invoke DrawString8x8,116,227,OFFSET bpText3D,00FFFFFFh
|
invoke DrawString8x8,116,227,OFFSET bpText3D,00FFFFFFh
|
||||||
cmp bpState3D,BP_DIRECTION
|
cmp bpState3D,BP_DIRECTION
|
||||||
je bp_render_direction
|
je bp_render_direction
|
||||||
|
cmp bpState3D,BP_SELECT_BALL
|
||||||
|
je bp_render_done
|
||||||
cmp bpState3D,BP_POWER
|
cmp bpState3D,BP_POWER
|
||||||
je bp_render_power
|
je bp_render_power
|
||||||
cmp bpState3D,BP_SETTLE
|
cmp bpState3D,BP_SETTLE
|
||||||
je bp_render_result
|
je bp_render_result
|
||||||
cmp bpState3D,BP_FINISHED
|
cmp bpState3D,BP_FINISHED
|
||||||
je bp_render_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
|
invoke DrawString8x8,8,204,OFFSET bpRollText,00E8D7ADh
|
||||||
jmp bp_render_done
|
jmp bp_render_done
|
||||||
bp_render_direction:
|
bp_render_direction:
|
||||||
|
|
@ -403,11 +509,11 @@ bp_render_arc:
|
||||||
invoke DrawBowlingGaugeLine3D,eax,162,ebx,168
|
invoke DrawBowlingGaugeLine3D,eax,162,ebx,168
|
||||||
jmp bp_render_done
|
jmp bp_render_done
|
||||||
bp_render_power:
|
bp_render_power:
|
||||||
invoke DrawString8x8,246,62,OFFSET bpPowerText,00E8D7ADh
|
invoke DrawString8x8,16,62,OFFSET bpPowerText,00E8D7ADh
|
||||||
invoke DrawBoxBorder,276,79,13,124,00121B20h,00AABDB6h,1
|
invoke DrawBoxBorder,30,79,13,124,00121B20h,00AABDB6h,1
|
||||||
invoke DrawBox,278,82,9,118,00D67057h
|
invoke DrawBox,32,82,9,118,00D67057h
|
||||||
invoke DrawBox,278,128,9,38,00E7C455h
|
invoke DrawBox,32,128,9,38,00E7C455h
|
||||||
invoke DrawBox,278,82,9,46,005BC98Ch
|
invoke DrawBox,32,82,9,46,005BC98Ch
|
||||||
mov eax,bpPower3D
|
mov eax,bpPower3D
|
||||||
imul eax,116
|
imul eax,116
|
||||||
xor edx,edx
|
xor edx,edx
|
||||||
|
|
@ -416,9 +522,9 @@ bp_render_power:
|
||||||
mov edx,198
|
mov edx,198
|
||||||
sub edx,eax
|
sub edx,eax
|
||||||
mov y,edx
|
mov y,edx
|
||||||
invoke DrawBox,270,y,25,2,00FFFFFFh
|
invoke DrawBox,24,y,25,2,00FFFFFFh
|
||||||
invoke FormatNumber,bpPower3D,OFFSET bpText3D
|
invoke FormatNumber,bpPower3D,OFFSET bpText3D
|
||||||
invoke DrawString8x8,246,180,OFFSET bpText3D,00FFFFFFh
|
invoke DrawString8x8,50,180,OFFSET bpText3D,00FFFFFFh
|
||||||
jmp bp_render_done
|
jmp bp_render_done
|
||||||
bp_render_result:
|
bp_render_result:
|
||||||
mov eax,OFFSET bpResultText
|
mov eax,OFFSET bpResultText
|
||||||
|
|
@ -451,6 +557,7 @@ bp_render_finished:
|
||||||
invoke DrawString8x8,88,161,ebx,00E8D7ADh
|
invoke DrawString8x8,88,161,ebx,00E8D7ADh
|
||||||
invoke DrawString8x8,136,187,OFFSET bpAgainText,00FFFFFFh
|
invoke DrawString8x8,136,187,OFFSET bpAgainText,00FFFFFFh
|
||||||
bp_render_done:
|
bp_render_done:
|
||||||
|
call DrawBowlingWeight3D
|
||||||
cmp bpScoreOpen3D,0
|
cmp bpScoreOpen3D,0
|
||||||
je @F
|
je @F
|
||||||
call DrawBowlingPlayScores3D
|
call DrawBowlingPlayScores3D
|
||||||
|
|
|
||||||
|
|
@ -158,14 +158,25 @@ bw_planes_done:
|
||||||
RenderBowlingPlanes3D ENDP
|
RenderBowlingPlanes3D ENDP
|
||||||
|
|
||||||
DrawBowlingBall3D PROC uses ebx esi x:DWORD,y:DWORD,mat:DWORD
|
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
|
mov eax,y
|
||||||
sar eax,8
|
sar eax,8
|
||||||
and eax,511
|
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]
|
mov eax,tableCos[eax*4]
|
||||||
test eax,eax
|
test eax,eax
|
||||||
jle bw_ball_done
|
jle bw_ball_done
|
||||||
|
|
@ -180,7 +191,7 @@ DrawBowlingBall3D PROC uses ebx esi x:DWORD,y:DWORD,mat:DWORD
|
||||||
imul eax,11
|
imul eax,11
|
||||||
cdq
|
cdq
|
||||||
idiv ecx
|
idiv ecx
|
||||||
add eax,FP_1*135/1000
|
add eax,z
|
||||||
mov holeZ,eax
|
mov holeZ,eax
|
||||||
mov eax,x
|
mov eax,x
|
||||||
sub eax,FP_1*35/1000
|
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
|
invoke DrawRoofEllipsoid3D,x,holeY,eax,FP_1*18/1000,FP_1*18/1000,FP_1*18/1000,233
|
||||||
bw_ball_done:
|
bw_ball_done:
|
||||||
ret
|
ret
|
||||||
DrawBowlingBall3D ENDP
|
DrawBowlingBallAt3D ENDP
|
||||||
|
|
||||||
DrawBowlingPin3D PROC uses ebx esi edi lane:DWORD,pin:DWORD,centre:DWORD
|
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
|
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.
|
; The match opponent leaves this restaurant seat instead of appearing twice.
|
||||||
cmp bpActive3D,0
|
cmp bpActive3D,0
|
||||||
je @F
|
je @F
|
||||||
test esi,esi
|
cmp esi,3
|
||||||
jz bw_cast_dining_next
|
jb bw_cast_dining_next
|
||||||
@@:
|
@@:
|
||||||
mov eax,bwVisitorX3D[esi*4]
|
mov eax,bwVisitorX3D[esi*4]
|
||||||
mov bwSmallActor3D.posX,eax
|
mov bwSmallActor3D.posX,eax
|
||||||
|
|
@ -602,32 +613,8 @@ bw_detail_return:
|
||||||
add eax,FP_1*64/100
|
add eax,FP_1*64/100
|
||||||
mov x1,eax
|
mov x1,eax
|
||||||
invoke DrawCityVertical3D,1,26*FP_1+512,x0,x1,FP_1/20,FP_1*62/100,241
|
invoke DrawCityVertical3D,1,26*FP_1+512,x0,x1,FP_1/20,FP_1*62/100,241
|
||||||
xor edi,edi
|
invoke RenderBowlingReturnMachine3D,centerX
|
||||||
bw_detail_rack_ball:
|
invoke RenderBowlingBallRack3D,centerX,esi
|
||||||
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
|
|
||||||
mov eax,centerX
|
mov eax,centerX
|
||||||
sub eax,FP_1*27/100
|
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
|
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
|
inc esi
|
||||||
cmp esi,4
|
cmp esi,4
|
||||||
jb bw_detail_return
|
jb bw_detail_return
|
||||||
|
call RenderBowlingReturnedBall3D
|
||||||
xor esi,esi
|
xor esi,esi
|
||||||
bw_detail_dining:
|
bw_detail_dining:
|
||||||
mov eax,esi
|
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
|
mov npcSelected3D,-1
|
||||||
npc_life_init:
|
npc_life_init:
|
||||||
imul ebx,esi,SIZEOF NpcLife3D
|
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 npcLife3D[ebx].state,NPC_STAND
|
||||||
mov eax,esi
|
mov eax,esi
|
||||||
imul eax,900
|
imul eax,900
|
||||||
add eax,1800
|
add eax,1800
|
||||||
mov npcLife3D[ebx].remaining,eax
|
mov npcLife3D[ebx].remaining,eax
|
||||||
mov npcLife3D[ebx].routeStep,esi
|
mov npcLife3D[ebx].routeStep,0
|
||||||
mov npcLife3D[ebx].pathCount,0
|
mov npcLife3D[ebx].pathCount,0
|
||||||
mov npcLife3D[ebx].remainder,0
|
mov npcLife3D[ebx].remainder,0
|
||||||
mov npcLife3D[ebx].poseClock,0
|
mov npcLife3D[ebx].poseClock,0
|
||||||
|
|
@ -19,30 +20,29 @@ npc_life_init:
|
||||||
mov npcWalkVelocityX3D[esi*4],0
|
mov npcWalkVelocityX3D[esi*4],0
|
||||||
mov npcWalkVelocityY3D[esi*4],0
|
mov npcWalkVelocityY3D[esi*4],0
|
||||||
mov npcRise3D[esi*4],0
|
mov npcRise3D[esi*4],0
|
||||||
|
mov npcSitTime3D[esi*4],0
|
||||||
mov eax,npcStartDest3D[esi*4]
|
mov eax,npcStartDest3D[esi*4]
|
||||||
mov npcLife3D[ebx].destination,eax
|
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 ecx,npcDestX3D[eax*4]
|
||||||
mov casinoNpcs3D[edi].posX,ecx
|
mov [edi].NpcMindEntity.posX,ecx
|
||||||
mov ecx,npcDestY3D[eax*4]
|
mov ecx,npcDestY3D[eax*4]
|
||||||
mov casinoNpcs3D[edi].posY,ecx
|
mov [edi].NpcMindEntity.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
|
|
||||||
npc_life_init_next:
|
npc_life_init_next:
|
||||||
inc esi
|
inc esi
|
||||||
cmp esi,NPC_LIFE_COUNT
|
cmp esi,NPC_LIFE_COUNT
|
||||||
jb npc_life_init
|
jb npc_life_init
|
||||||
|
call InitNpcVisits3D
|
||||||
mov npcLifeReady3D,1
|
mov npcLifeReady3D,1
|
||||||
ret
|
ret
|
||||||
InitNpcLife3D ENDP
|
InitNpcLife3D ENDP
|
||||||
|
|
||||||
; BFS visits each tile at most once. Body clearance includes furniture and the stage.
|
; 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
|
mov esi,cell
|
||||||
cmp esi,NPC_PATH_CAP
|
cmp esi,NPC_PATH_CAP
|
||||||
jae npc_cell_done
|
jae npc_cell_done
|
||||||
|
|
@ -56,9 +56,41 @@ NpcTryCell3D PROC uses ebx esi cell:DWORD,parent:DWORD
|
||||||
shr edx,5
|
shr edx,5
|
||||||
shl edx,16
|
shl edx,16
|
||||||
add edx,FP_HALF
|
add edx,FP_HALF
|
||||||
|
mov endX,eax
|
||||||
|
mov endY,edx
|
||||||
invoke CanWalk3D,eax,edx
|
invoke CanWalk3D,eax,edx
|
||||||
test eax,eax
|
test eax,eax
|
||||||
jz npc_cell_done
|
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 eax,parent
|
||||||
mov npcParents3D[esi*4],eax
|
mov npcParents3D[esi*4],eax
|
||||||
mov ebx,npcSearchTail3D
|
mov ebx,npcSearchTail3D
|
||||||
|
|
@ -78,11 +110,12 @@ NpcPlanPath3D PROC uses ebx esi edi slot:DWORD,destination:DWORD
|
||||||
jae npc_plan_fail
|
jae npc_plan_fail
|
||||||
imul ebx,slot,SIZEOF NpcLife3D
|
imul ebx,slot,SIZEOF NpcLife3D
|
||||||
mov npcLife3D[ebx].pathCount,0
|
mov npcLife3D[ebx].pathCount,0
|
||||||
imul esi,slot,SIZEOF NpcMindEntity
|
invoke NpcEntity3D,slot
|
||||||
mov eax,casinoNpcs3D[esi].posY
|
mov esi,eax
|
||||||
|
mov eax,[esi].NpcMindEntity.posY
|
||||||
sar eax,16
|
sar eax,16
|
||||||
shl eax,5
|
shl eax,5
|
||||||
mov ecx,casinoNpcs3D[esi].posX
|
mov ecx,[esi].NpcMindEntity.posX
|
||||||
sar ecx,16
|
sar ecx,16
|
||||||
add eax,ecx
|
add eax,ecx
|
||||||
cmp eax,NPC_PATH_CAP
|
cmp eax,NPC_PATH_CAP
|
||||||
|
|
@ -190,16 +223,17 @@ npc_space_person:
|
||||||
imul ebx,esi,SIZEOF NpcLife3D
|
imul ebx,esi,SIZEOF NpcLife3D
|
||||||
cmp npcLife3D[ebx].state,NPC_AWAY
|
cmp npcLife3D[ebx].state,NPC_AWAY
|
||||||
je npc_space_next
|
je npc_space_next
|
||||||
imul ebx,esi,SIZEOF NpcMindEntity
|
invoke NpcEntity3D,esi
|
||||||
|
mov ebx,eax
|
||||||
mov eax,px
|
mov eax,px
|
||||||
sub eax,casinoNpcs3D[ebx].posX
|
sub eax,[ebx].NpcMindEntity.posX
|
||||||
jns @F
|
jns @F
|
||||||
neg eax
|
neg eax
|
||||||
@@:
|
@@:
|
||||||
cmp eax,FP_1*2/5
|
cmp eax,FP_1*2/5
|
||||||
jae npc_space_next
|
jae npc_space_next
|
||||||
mov eax,py
|
mov eax,py
|
||||||
sub eax,casinoNpcs3D[ebx].posY
|
sub eax,[ebx].NpcMindEntity.posY
|
||||||
jns @F
|
jns @F
|
||||||
neg eax
|
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 budget:DWORD,wx:DWORD,wy:DWORD,mind:DWORD,pathBase:DWORD
|
||||||
local oldX:DWORD,oldY:DWORD
|
local oldX:DWORD,oldY:DWORD
|
||||||
imul ebx,slot,SIZEOF NpcLife3D
|
imul ebx,slot,SIZEOF NpcLife3D
|
||||||
imul eax,slot,SIZEOF NpcMindEntity
|
invoke NpcEntity3D,slot
|
||||||
lea esi,casinoNpcs3D[eax]
|
mov esi,eax
|
||||||
mov mind,esi
|
mov mind,esi
|
||||||
mov eax,[esi].NpcMindEntity.posX
|
mov eax,[esi].NpcMindEntity.posX
|
||||||
mov oldX,eax
|
mov oldX,eax
|
||||||
|
|
@ -234,7 +268,8 @@ NpcMove3D PROC uses ebx esi edi slot:DWORD,milliseconds:DWORD
|
||||||
add eax,OFFSET npcPaths3D
|
add eax,OFFSET npcPaths3D
|
||||||
mov pathBase,eax
|
mov pathBase,eax
|
||||||
mov eax,milliseconds
|
mov eax,milliseconds
|
||||||
mov ecx,55000
|
mov ecx,slot
|
||||||
|
mov ecx,npcVisitSpeed3D[ecx*4]
|
||||||
mul ecx
|
mul ecx
|
||||||
add eax,npcLife3D[ebx].remainder
|
add eax,npcLife3D[ebx].remainder
|
||||||
adc edx,0
|
adc edx,0
|
||||||
|
|
@ -338,28 +373,26 @@ npc_move_y:
|
||||||
cmp npcLife3D[ebx].pathCount,0
|
cmp npcLife3D[ebx].pathCount,0
|
||||||
jne npc_move_done
|
jne npc_move_done
|
||||||
npc_move_arrived:
|
npc_move_arrived:
|
||||||
mov eax,npcLife3D[ebx].destination
|
invoke NpcArrive3D,slot
|
||||||
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
|
|
||||||
jmp npc_move_done
|
jmp npc_move_done
|
||||||
npc_move_blocked:
|
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].state,NPC_STAND
|
||||||
mov npcLife3D[ebx].remaining,1000
|
mov npcLife3D[ebx].remaining,1000
|
||||||
mov npcLife3D[ebx].pathCount,0
|
mov npcLife3D[ebx].pathCount,0
|
||||||
|
mov eax,slot
|
||||||
|
mov npcVisitActivity3D[eax*4],NV_IDLE
|
||||||
npc_move_done:
|
npc_move_done:
|
||||||
; Advance gait by successful displacement only, including partial blocked steps.
|
; Advance gait by successful displacement only, including partial blocked steps.
|
||||||
mov esi,mind
|
mov esi,mind
|
||||||
|
|
@ -372,6 +405,7 @@ npc_move_done:
|
||||||
mov edi,eax
|
mov edi,eax
|
||||||
or eax,ecx
|
or eax,ecx
|
||||||
jz npc_move_no_stride
|
jz npc_move_no_stride
|
||||||
|
mov npcVisitBlocked3D[ebx*4],0
|
||||||
mov npcWalkVelocityX3D[ebx*4],ecx
|
mov npcWalkVelocityX3D[ebx*4],ecx
|
||||||
mov npcWalkVelocityY3D[ebx*4],edi
|
mov npcWalkVelocityY3D[ebx*4],edi
|
||||||
mov eax,ecx
|
mov eax,ecx
|
||||||
|
|
@ -389,16 +423,25 @@ npc_move_done:
|
||||||
mov ecx,FP_1*3/4
|
mov ecx,FP_1*3/4
|
||||||
div ecx
|
div ecx
|
||||||
mov npcWalkDistance3D[ebx*4],edx
|
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:
|
npc_move_no_stride:
|
||||||
|
mov eax,slot
|
||||||
|
mov npcWalkVelocityX3D[eax*4],0
|
||||||
|
mov npcWalkVelocityY3D[eax*4],0
|
||||||
ret
|
ret
|
||||||
NpcMove3D ENDP
|
NpcMove3D ENDP
|
||||||
|
|
||||||
UpdateNpcLife3D PROC uses ebx esi edi
|
UpdateNpcLife3D PROC uses ebx esi edi
|
||||||
local milliseconds:DWORD,destination:DWORD
|
local milliseconds:DWORD
|
||||||
cmp npcLifeReady3D,1
|
cmp npcLifeReady3D,1
|
||||||
jne npc_update_done
|
jne npc_update_done
|
||||||
cmp hallLevel3D,0
|
cmp hallLevel3D,0
|
||||||
jne npc_update_done
|
jne npc_update_done
|
||||||
|
cmp engineMode,MODE_WALK
|
||||||
|
jne npc_update_done
|
||||||
mov eax,deltaTime3D
|
mov eax,deltaTime3D
|
||||||
cmp eax,250
|
cmp eax,250
|
||||||
jbe @F
|
jbe @F
|
||||||
|
|
@ -411,6 +454,20 @@ npc_update_person:
|
||||||
imul ebx,esi,SIZEOF NpcLife3D
|
imul ebx,esi,SIZEOF NpcLife3D
|
||||||
mov eax,milliseconds
|
mov eax,milliseconds
|
||||||
add npcLife3D[ebx].poseClock,eax
|
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
|
cmp npcLife3D[ebx].state,NPC_WALK
|
||||||
jne npc_update_wait
|
jne npc_update_wait
|
||||||
cmp npcRise3D[esi*4],0
|
cmp npcRise3D[esi*4],0
|
||||||
|
|
@ -425,51 +482,23 @@ npc_update_move:
|
||||||
npc_update_wait:
|
npc_update_wait:
|
||||||
sub npcLife3D[ebx].remaining,eax
|
sub npcLife3D[ebx].remaining,eax
|
||||||
ja npc_update_sync
|
ja npc_update_sync
|
||||||
cmp npcLife3D[ebx].state,NPC_AWAY
|
invoke NpcAdvanceVisit3D,esi
|
||||||
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
|
|
||||||
npc_update_sync:
|
npc_update_sync:
|
||||||
imul edi,esi,SIZEOF NpcMindEntity
|
invoke NpcEntity3D,esi
|
||||||
|
mov edi,eax
|
||||||
mov eax,npcLife3D[ebx].state
|
mov eax,npcLife3D[ebx].state
|
||||||
mov casinoNpcs3D[edi].state,eax
|
mov [edi].NpcMindEntity.state,eax
|
||||||
mov eax,npcLife3D[ebx].remaining
|
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.
|
; Keep the old public position array coherent for existing world checks.
|
||||||
|
cmp esi,6
|
||||||
|
jae npc_update_sync_next
|
||||||
imul ecx,esi,SIZEOF CityProp3D
|
imul ecx,esi,SIZEOF CityProp3D
|
||||||
mov eax,casinoNpcs3D[edi].posX
|
mov eax,[edi].NpcMindEntity.posX
|
||||||
mov hallGuests3D[ecx].posX,eax
|
mov hallGuests3D[ecx].posX,eax
|
||||||
mov eax,casinoNpcs3D[edi].posY
|
mov eax,[edi].NpcMindEntity.posY
|
||||||
mov hallGuests3D[ecx].posY,eax
|
mov hallGuests3D[ecx].posY,eax
|
||||||
|
npc_update_sync_next:
|
||||||
inc esi
|
inc esi
|
||||||
cmp esi,NPC_LIFE_COUNT
|
cmp esi,NPC_LIFE_COUNT
|
||||||
jb npc_update_person
|
jb npc_update_person
|
||||||
|
|
@ -483,8 +512,9 @@ RenderNpcLife3D PROC uses ebx esi edi
|
||||||
jne npc_draw_done
|
jne npc_draw_done
|
||||||
xor esi,esi
|
xor esi,esi
|
||||||
npc_draw_depth:
|
npc_draw_depth:
|
||||||
imul ebx,esi,SIZEOF NpcMindEntity
|
invoke NpcEntity3D,esi
|
||||||
invoke ProjectCityPoint3D,casinoNpcs3D[ebx].posX,casinoNpcs3D[ebx].posY
|
mov ebx,eax
|
||||||
|
invoke ProjectCityPoint3D,[ebx].NpcMindEntity.posX,[ebx].NpcMindEntity.posY
|
||||||
mov npcDrawDepth3D[esi*4],edx
|
mov npcDrawDepth3D[esi*4],edx
|
||||||
mov npcDrawOrder3D[esi*4],esi
|
mov npcDrawOrder3D[esi*4],esi
|
||||||
inc esi
|
inc esi
|
||||||
|
|
@ -514,24 +544,29 @@ npc_draw_person:
|
||||||
imul ebx,eax,SIZEOF NpcLife3D
|
imul ebx,eax,SIZEOF NpcLife3D
|
||||||
cmp npcLife3D[ebx].state,NPC_AWAY
|
cmp npcLife3D[ebx].state,NPC_AWAY
|
||||||
je npc_draw_next
|
je npc_draw_next
|
||||||
imul edi,eax,SIZEOF NpcMindEntity
|
invoke NpcEntity3D,eax
|
||||||
mov eax,casinoNpcs3D[edi].posX
|
mov edi,eax
|
||||||
|
mov eax,[edi].NpcMindEntity.posX
|
||||||
mov npcSprite3D.posX,eax
|
mov npcSprite3D.posX,eax
|
||||||
mov eax,casinoNpcs3D[edi].posY
|
mov eax,[edi].NpcMindEntity.posY
|
||||||
mov npcSprite3D.posY,eax
|
mov npcSprite3D.posY,eax
|
||||||
mov eax,npcLife3D[ebx].identity
|
mov eax,npcLife3D[ebx].identity
|
||||||
mov eax,npcGuestAppearance3D[eax*4]
|
mov eax,npcGuestAppearance3D[eax*4]
|
||||||
mov castId,eax
|
mov castId,eax
|
||||||
mov castAction,CAST_TALK
|
mov castAction,CAST_IDLE
|
||||||
mov eax,npcLife3D[ebx].poseClock
|
mov eax,npcLife3D[ebx].poseClock
|
||||||
mov castClock,eax
|
mov castClock,eax
|
||||||
mov eax,npcDrawOrder3D[esi*4]
|
mov eax,npcDrawOrder3D[esi*4]
|
||||||
mov slot,eax
|
mov slot,eax
|
||||||
|
invoke NpcResolveVisitPose3D,eax
|
||||||
|
mov castAction,eax
|
||||||
cmp npcLife3D[ebx].state,NPC_SIT
|
cmp npcLife3D[ebx].state,NPC_SIT
|
||||||
jne npc_draw_walk
|
jne npc_draw_walk
|
||||||
mov castAction,CAST_SEAT_TALK
|
mov eax,slot
|
||||||
cmp castClock,800
|
mov eax,npcSitTime3D[eax*4]
|
||||||
|
cmp eax,800
|
||||||
jae npc_draw_sprite
|
jae npc_draw_sprite
|
||||||
|
mov castClock,eax
|
||||||
mov castAction,CAST_SIT_DOWN
|
mov castAction,CAST_SIT_DOWN
|
||||||
jmp npc_draw_sprite
|
jmp npc_draw_sprite
|
||||||
npc_draw_walk:
|
npc_draw_walk:
|
||||||
|
|
@ -546,6 +581,9 @@ npc_draw_walk:
|
||||||
mov castClock,eax
|
mov castClock,eax
|
||||||
jmp npc_draw_sprite
|
jmp npc_draw_sprite
|
||||||
npc_draw_moving:
|
npc_draw_moving:
|
||||||
|
mov eax,npcWalkVelocityX3D[ebx*4]
|
||||||
|
or eax,npcWalkVelocityY3D[ebx*4]
|
||||||
|
jz npc_draw_sprite
|
||||||
mov castAction,CAST_WALK
|
mov castAction,CAST_WALK
|
||||||
mov eax,npcWalkDistance3D[ebx*4]
|
mov eax,npcWalkDistance3D[ebx*4]
|
||||||
mov castClock,eax
|
mov castClock,eax
|
||||||
|
|
@ -553,6 +591,7 @@ npc_draw_sprite:
|
||||||
mov ebx,slot
|
mov ebx,slot
|
||||||
invoke ConfigureCharacter3D,OFFSET npcSprite3D,castId,castAction,castClock,npcWalkVelocityX3D[ebx*4],npcWalkVelocityY3D[ebx*4]
|
invoke ConfigureCharacter3D,OFFSET npcSprite3D,castId,castAction,castClock,npcWalkVelocityX3D[ebx*4],npcWalkVelocityY3D[ebx*4]
|
||||||
invoke DrawCityObject3D,OFFSET npcSprite3D,0
|
invoke DrawCityObject3D,OFFSET npcSprite3D,0
|
||||||
|
invoke NpcDrawRemark3D,slot
|
||||||
npc_draw_next:
|
npc_draw_next:
|
||||||
inc esi
|
inc esi
|
||||||
cmp esi,NPC_LIFE_COUNT
|
cmp esi,NPC_LIFE_COUNT
|
||||||
|
|
@ -576,14 +615,15 @@ npc_interact_person:
|
||||||
imul ebx,esi,SIZEOF NpcLife3D
|
imul ebx,esi,SIZEOF NpcLife3D
|
||||||
cmp npcLife3D[ebx].state,NPC_AWAY
|
cmp npcLife3D[ebx].state,NPC_AWAY
|
||||||
je npc_interact_next
|
je npc_interact_next
|
||||||
imul edi,esi,SIZEOF NpcMindEntity
|
invoke NpcEntity3D,esi
|
||||||
mov eax,casinoNpcs3D[edi].posX
|
mov edi,eax
|
||||||
|
mov eax,[edi].NpcMindEntity.posX
|
||||||
sub eax,playerX
|
sub eax,playerX
|
||||||
sar eax,8
|
sar eax,8
|
||||||
mov deltaX,eax
|
mov deltaX,eax
|
||||||
imul eax,eax
|
imul eax,eax
|
||||||
mov distance,eax
|
mov distance,eax
|
||||||
mov eax,casinoNpcs3D[edi].posY
|
mov eax,[edi].NpcMindEntity.posY
|
||||||
sub eax,playerY
|
sub eax,playerY
|
||||||
sar eax,8
|
sar eax,8
|
||||||
mov deltaY,eax
|
mov deltaY,eax
|
||||||
|
|
@ -640,3 +680,5 @@ npc_interact_next:
|
||||||
npc_interact_done:
|
npc_interact_done:
|
||||||
ret
|
ret
|
||||||
CheckNpcInteractions3D ENDP
|
CheckNpcInteractions3D ENDP
|
||||||
|
|
||||||
|
include src_graphics\npc_visits.inc
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ IFDEF CASINO_ACTION_TEST
|
||||||
DeleteFileA PROTO :DWORD
|
DeleteFileA PROTO :DWORD
|
||||||
ENDIF
|
ENDIF
|
||||||
INTERACT_NPC equ 40
|
INTERACT_NPC equ 40
|
||||||
NPC_LIFE_COUNT equ 6
|
NPC_LIFE_COUNT equ 10
|
||||||
NPC_IDENTITY_COUNT equ 12
|
NPC_IDENTITY_COUNT equ 12
|
||||||
NPC_DEST_COUNT equ 10
|
NPC_DEST_COUNT equ 12
|
||||||
NPC_STAND equ 0
|
NPC_STAND equ 0
|
||||||
NPC_WALK equ 1
|
NPC_WALK equ 1
|
||||||
NPC_SIT equ 2
|
NPC_SIT equ 2
|
||||||
|
|
@ -23,6 +23,16 @@ NpcPlanPath3D PROTO :DWORD,:DWORD
|
||||||
NpcTryCell3D PROTO :DWORD,:DWORD
|
NpcTryCell3D PROTO :DWORD,:DWORD
|
||||||
NpcMove3D PROTO :DWORD,:DWORD
|
NpcMove3D PROTO :DWORD,:DWORD
|
||||||
NpcCanStep3D PROTO :DWORD,: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
|
NpcRecordRound3D PROTO :DWORD,:DWORD
|
||||||
NpcEnsureJournal3D PROTO
|
NpcEnsureJournal3D PROTO
|
||||||
NpcSaveJournal3D PROTO
|
NpcSaveJournal3D PROTO
|
||||||
|
|
@ -43,6 +53,9 @@ NpcLife3D STRUCT
|
||||||
NpcLife3D ENDS
|
NpcLife3D ENDS
|
||||||
.data
|
.data
|
||||||
npcLife3D NpcLife3D NPC_LIFE_COUNT dup(<>)
|
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
|
npcLifeReady3D dd 0
|
||||||
npcGuestArt3D AnimPack3D <>
|
npcGuestArt3D AnimPack3D <>
|
||||||
npcGuestPath3D db "assets\animations\hall\guest-cast-v1.bin",0
|
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)
|
npcWalkVelocityY3D dd NPC_LIFE_COUNT dup(0)
|
||||||
; Keep the twelve-slot historical journal, but resolve every appearance to the shared ten.
|
; Keep the twelve-slot historical journal, but resolve every appearance to the shared ten.
|
||||||
npcRise3D dd NPC_LIFE_COUNT dup(0)
|
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
|
npcGuestAppearance3D dd 0,2,4,1,3,5,6,8,0,7,9,2
|
||||||
npcGuestNames3D dd OFFSET npcName0,OFFSET npcName1,OFFSET npcName2,OFFSET npcGuestAnna3D
|
npcGuestNames3D dd OFFSET npcName0,OFFSET npcName1,OFFSET npcName2,OFFSET npcGuestAnna3D
|
||||||
dd OFFSET npcGuestMarina3D,OFFSET npcGuestVera3D,OFFSET npcName6,OFFSET npcName7
|
dd OFFSET npcGuestMarina3D,OFFSET npcGuestVera3D,OFFSET npcName6,OFFSET npcName7
|
||||||
|
|
@ -71,11 +85,12 @@ npcDialogError3D dd 0
|
||||||
npcNameBuffer3D db 64 dup(0)
|
npcNameBuffer3D db 64 dup(0)
|
||||||
npcJournalIoError3D dd 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
|
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
|
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
|
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
|
||||||
npcVisitRoute3D dd 1,5,8,2,3,6,7,9,1,0
|
dd 25*FP_1+FP_HALF,19*FP_1+FP_HALF
|
||||||
npcStartDest3D dd 1,2,3,6,8,7
|
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>
|
npcSprite3D CityProp3D <0,0,FP_1*3/5,FP_1*6/5,0,OFFSET hallPatrons3D>
|
||||||
npcDrawOrder3D dd NPC_LIFE_COUNT dup(0)
|
npcDrawOrder3D dd NPC_LIFE_COUNT dup(0)
|
||||||
npcDrawDepth3D dd NPC_LIFE_COUNT dup(0)
|
npcDrawDepth3D dd NPC_LIFE_COUNT dup(0)
|
||||||
|
|
@ -91,7 +106,7 @@ npcJournalBasePtr3D dd 0
|
||||||
ENDIF
|
ENDIF
|
||||||
npcDateOverride3D dd 0
|
npcDateOverride3D dd 0
|
||||||
npcSystemTime3D dw 8 dup(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
|
npcJournal3D LABEL DWORD
|
||||||
npcJournalMagic3D dd 3151504Eh
|
npcJournalMagic3D dd 3151504Eh
|
||||||
npcJournalDay3D dd 0
|
npcJournalDay3D dd 0
|
||||||
|
|
@ -157,4 +172,5 @@ npcQueue3D dd NPC_PATH_CAP dup(?)
|
||||||
npcSearchHead3D dd 0
|
npcSearchHead3D dd 0
|
||||||
npcSearchTail3D dd 0
|
npcSearchTail3D dd 0
|
||||||
npcSearchGoal3D dd 0
|
npcSearchGoal3D dd 0
|
||||||
|
include src_graphics\npc_visits_data.inc
|
||||||
.code
|
.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
|
jne bp_test_fail
|
||||||
cmp bwBusy3D[4],2
|
cmp bwBusy3D[4],2
|
||||||
jne bp_test_fail
|
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 expansionStage,151
|
||||||
mov deltaTime3D,0
|
mov deltaTime3D,0
|
||||||
mov bpClock3D,0
|
mov bpClock3D,0
|
||||||
|
|
@ -259,8 +266,15 @@ bp_test_flight:
|
||||||
mov eax,bankroll
|
mov eax,bankroll
|
||||||
cmp eax,bank
|
cmp eax,bank
|
||||||
jne bp_test_fail
|
jne bp_test_fail
|
||||||
|
call BowlingFeelNativeTests
|
||||||
|
call BowlingReturnNativeTests
|
||||||
|
call BowlingWeightNativeTests
|
||||||
ret
|
ret
|
||||||
bp_test_fail:
|
bp_test_fail:
|
||||||
invoke ExitProcess,expansionStage
|
invoke ExitProcess,expansionStage
|
||||||
ret
|
ret
|
||||||
BowlingPlayNativeTests ENDP
|
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
|
call Create3DWindow
|
||||||
test eax,eax
|
test eax,eax
|
||||||
jz bp_ui_fail
|
jz bp_ui_fail
|
||||||
|
call ToggleFullscreen3D
|
||||||
invoke SetWindowLongA,h3DWnd,-4,OFFSET WindowEvents3D
|
invoke SetWindowLongA,h3DWnd,-4,OFFSET WindowEvents3D
|
||||||
call InitBowling3D
|
call InitBowling3D
|
||||||
call LoadBowling3D
|
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/rooftop.inc")
|
||||||
code += "\n" + expand("src_graphics/bowling.inc")
|
code += "\n" + expand("src_graphics/bowling.inc")
|
||||||
code += "\n" + read("src_graphics/character_cast.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/scene_animation.inc"),"LoadAnimPack3D")
|
||||||
code += "\n" + proc(read("src_graphics/unavailable.inc"),"BeginUnavailable3D")
|
code += "\n" + proc(read("src_graphics/unavailable.inc"),"BeginUnavailable3D")
|
||||||
code += "\n" + read("src_graphics/observer.inc")
|
code += "\n" + read("src_graphics/observer.inc")
|
||||||
|
|
@ -75,6 +76,7 @@ def prepare():
|
||||||
darts = read("src_graphics/darts_data.inc").replace(
|
darts = read("src_graphics/darts_data.inc").replace(
|
||||||
"include src_graphics\\darts_art.inc", read("src_graphics/darts_art.inc"))
|
"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" + 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 = 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))
|
own_data.update(re.findall(r"^(\w+) LABEL\b",data,re.M))
|
||||||
coff = Coff(ROOT / "build/graphics/poker.obj")
|
coff = Coff(ROOT / "build/graphics/poker.obj")
|
||||||
|
|
@ -90,7 +92,8 @@ def prepare():
|
||||||
"casinoNpcs3D":"NpcMindEntity","hallSpriteTemp3D":"CityProp3D",
|
"casinoNpcs3D":"NpcMindEntity","hallSpriteTemp3D":"CityProp3D",
|
||||||
"hallObjects3D":"CityProp3D","hallLights3D":"CityProp3D",
|
"hallObjects3D":"CityProp3D","hallLights3D":"CityProp3D",
|
||||||
"hallLoungeDecor3D":"CityProp3D","hallGuests3D":"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
|
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/"casino3d.inc",ROOT/"casino3d_data.inc",*sorted(path for path in
|
||||||
(ROOT/"src_graphics").glob("*.inc") if path.name != "renderer.inc")])
|
(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]):
|
for dep in re.findall(r"\b[A-Za-z_]\w*",constants[name]):
|
||||||
constant(dep)
|
constant(dep)
|
||||||
ordered.append(f"{name} equ {constants[name]}")
|
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)
|
constant(name)
|
||||||
# Win32 prototypes are not declarations in the helper object.
|
# Win32 prototypes are not declarations in the helper object.
|
||||||
for name,args in re.findall(r"^(\w+)\s+PROTO([^\n]*)",all_source,re.M):
|
for name,args in re.findall(r"^(\w+)\s+PROTO([^\n]*)",all_source,re.M):
|
||||||
protos.setdefault(name,args.count(":DWORD"))
|
protos.setdefault(name,args.count(":DWORD"))
|
||||||
protos.update({"ExitProcess":1,"WriteFile":5,"GetTickCount":0,"SetUnhandledExceptionFilter":1,
|
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 = ".386\n.model flat\noption casemap:none\n" + "\n".join(structures+ordered+externs)
|
||||||
header += "\noption language:stdcall\n" + "\n".join(
|
header += "\noption language:stdcall\n" + "\n".join(
|
||||||
name+" PROTO"+(" "+",".join([":DWORD"]*size) if size else "")
|
name+" PROTO"+(" "+",".join([":DWORD"]*size) if size else "")
|
||||||
|
|
@ -223,6 +226,10 @@ def check_bowling_room():
|
||||||
return False
|
return False
|
||||||
if 2 <= x <= 17.3 and y < 22.3:
|
if 2 <= x <= 17.3 and y < 22.3:
|
||||||
return False
|
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"])
|
return not any(a <= x <= b and c <= y <= d for a,b,c,d in layout["collisions"])
|
||||||
start = (68,120)
|
start = (68,120)
|
||||||
reached,pending = {start},[start]
|
reached,pending = {start},[start]
|
||||||
|
|
@ -248,18 +255,118 @@ def check_bowling_room():
|
||||||
assert len(captures) >= 10
|
assert len(captures) >= 10
|
||||||
for a,b,region in (
|
for a,b,region in (
|
||||||
("direction","direction-left",(180,314,462,414)),
|
("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)]
|
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")
|
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")
|
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")
|
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():
|
def main():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("--parity",action="store_true")
|
parser.add_argument("--parity",action="store_true")
|
||||||
parser.add_argument("--bowling-only",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-alpha-regression",action="store_true")
|
||||||
parser.add_argument("--prove-seam-regression",action="store_true")
|
parser.add_argument("--prove-seam-regression",action="store_true")
|
||||||
parser.add_argument("--prove-distance-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",
|
source = source.replace(" call LoadHallAssets3D\n cmp characterCast3D.pixels,0",
|
||||||
" call LoadHallAssets3D\n call BowlingNativeTests\n invoke ExitProcess,0\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")
|
(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:
|
if args.prove_fate_anchor_regression:
|
||||||
stem = "module-fate-anchor-regression"
|
stem = "module-fate-anchor-regression"
|
||||||
source = (OUT/"module.asm").read_text(encoding="cp1251")
|
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",
|
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)
|
"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)
|
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:
|
if args.bowling_only:
|
||||||
assert result.returncode == 0,result.returncode
|
assert result.returncode == 0,result.returncode
|
||||||
check_bowling_room()
|
check_bowling_room()
|
||||||
|
|
@ -373,6 +492,7 @@ def main():
|
||||||
if not args.prove_seam_regression:
|
if not args.prove_seam_regression:
|
||||||
check_rooftop_navigation()
|
check_rooftop_navigation()
|
||||||
check_bowling_room()
|
check_bowling_room()
|
||||||
|
check_npc_visits()
|
||||||
check_character_cast()
|
check_character_cast()
|
||||||
closed = Image.open(OUT/"fortune-closed.bmp").tobytes()
|
closed = Image.open(OUT/"fortune-closed.bmp").tobytes()
|
||||||
opened = Image.open(OUT/"fortune-open.bmp").tobytes()
|
opened = Image.open(OUT/"fortune-open.bmp").tobytes()
|
||||||
|
|
|
||||||
|
|
@ -1000,8 +1000,9 @@ expansion_long_gait:
|
||||||
expansion_gait_bounds:
|
expansion_gait_bounds:
|
||||||
cmp npcWalkDistance3D[edi*4],FP_1*3/4
|
cmp npcWalkDistance3D[edi*4],FP_1*3/4
|
||||||
jae expansion_fail
|
jae expansion_fail
|
||||||
imul ebx,edi,SIZEOF NpcMindEntity
|
invoke NpcEntity3D,edi
|
||||||
invoke CanWalk3D,casinoNpcs3D[ebx].posX,casinoNpcs3D[ebx].posY
|
mov ebx,eax
|
||||||
|
invoke CanWalk3D,[ebx].NpcMindEntity.posX,[ebx].NpcMindEntity.posY
|
||||||
cmp eax,1
|
cmp eax,1
|
||||||
jne expansion_fail
|
jne expansion_fail
|
||||||
inc edi
|
inc edi
|
||||||
|
|
@ -1175,6 +1176,7 @@ expansion_leaf_shut:
|
||||||
call ExpansionDartsTests
|
call ExpansionDartsTests
|
||||||
call RoofNativeTests
|
call RoofNativeTests
|
||||||
call BowlingNativeTests
|
call BowlingNativeTests
|
||||||
|
call NpcVisitsNativeTests
|
||||||
invoke ExitProcess,0
|
invoke ExitProcess,0
|
||||||
expansion_fail:
|
expansion_fail:
|
||||||
invoke ExitProcess,expansionStage
|
invoke ExitProcess,expansionStage
|
||||||
|
|
@ -1187,3 +1189,4 @@ include tools/tests/darts_hall_test.inc
|
||||||
include tools/tests/rooftop_test.inc
|
include tools/tests/rooftop_test.inc
|
||||||
include tools/tests/bowling_test.inc
|
include tools/tests/bowling_test.inc
|
||||||
include tools/tests/character_cast_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
|
call UpdateNpcLife3D
|
||||||
xor esi,esi
|
xor esi,esi
|
||||||
npc_test_person_bounds:
|
npc_test_person_bounds:
|
||||||
imul ebx,esi,SIZEOF NpcMindEntity
|
invoke NpcEntity3D,esi
|
||||||
invoke CanWalk3D,casinoNpcs3D[ebx].posX,casinoNpcs3D[ebx].posY
|
mov ebx,eax
|
||||||
|
invoke CanWalk3D,[ebx].NpcMindEntity.posX,[ebx].NpcMindEntity.posY
|
||||||
cmp eax,1
|
cmp eax,1
|
||||||
jne npc_test_fail
|
jne npc_test_fail
|
||||||
imul edi,esi,SIZEOF NpcLife3D
|
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