- Billiards: add native Russian Pyramid & American Eight-Ball pool with physics prediction, controls, and regression tests - Scratch Tickets: add dedicated counter, mat presentation, elliptical coin scraping, 4 ticket types, and payout effects - First-Person Dice: add native dice scene, hand anchor frames, throwing animation, and table perspective - City Wake & Weather: add arrival cutscene, alley geometry, weather/rain effects, and lighter/rocker animation - World Dressing: add hall paintings, furniture packs, hall lighting, and scene regression tests - Build & Tooling: update build.bat for modern MSVC toolchain, update launcher hash, and refresh shipping binaries
181 lines
4.3 KiB
PHP
181 lines
4.3 KiB
PHP
; Deterministic avenue traffic; stationary cars stay near the curb.
|
|
AnimateCityCars3D PROC uses ebx esi edi
|
|
local trafficClock:DWORD
|
|
mov eax, cityClock3D
|
|
; Keep the crossing's safe stopped positions when the wake-up gets longer.
|
|
sub eax,CITY_TRAFFIC_OFFSET_MS
|
|
jns @F
|
|
xor eax,eax
|
|
@@:
|
|
; A red-light interval lets the protagonist cross from the alley.
|
|
; Resume from the stopped position instead of jumping forward in world space.
|
|
cmp eax,7000
|
|
jb city_traffic_clock_ready
|
|
cmp eax,8400
|
|
jae city_traffic_wait
|
|
sub eax,7000
|
|
mov ebx,eax
|
|
imul eax,eax
|
|
xor edx,edx
|
|
mov ecx,2800
|
|
div ecx
|
|
sub ebx,eax
|
|
lea eax,[ebx+7000]
|
|
jmp city_traffic_clock_ready
|
|
city_traffic_wait:
|
|
cmp eax,14300
|
|
jae city_traffic_resume
|
|
mov eax,7700
|
|
jmp city_traffic_clock_ready
|
|
city_traffic_resume:
|
|
cmp eax,15700
|
|
jae city_traffic_cruise
|
|
sub eax,14300
|
|
imul eax,eax
|
|
xor edx,edx
|
|
mov ecx,2800
|
|
div ecx
|
|
add eax,7700
|
|
jmp city_traffic_clock_ready
|
|
city_traffic_cruise:
|
|
sub eax,7300
|
|
city_traffic_clock_ready:
|
|
mov trafficClock,eax
|
|
mov ecx, FP_1/2500
|
|
mul ecx
|
|
mov ecx, 26*FP_1
|
|
div ecx
|
|
add edx, 3*FP_1
|
|
mov cityObjects3D[CITY_TRAFFIC_EAST*SIZEOF CityProp3D].posX, edx
|
|
mov eax, trafficClock
|
|
mov ecx, FP_1/2900
|
|
mul ecx
|
|
mov ecx, 26*FP_1
|
|
div ecx
|
|
mov eax, 29*FP_1
|
|
sub eax, edx
|
|
mov cityObjects3D[CITY_TRAFFIC_WEST*SIZEOF CityProp3D].posX, eax
|
|
mov esi, CITY_FIRST_CAR
|
|
city_car_view:
|
|
cmp esi, 12
|
|
je city_car_next
|
|
cmp esi, 13
|
|
je city_car_next
|
|
imul edi, esi, SIZEOF CityProp3D
|
|
mov eax, playerX
|
|
sub eax, cityObjects3D[edi].posX
|
|
mov edx, playerY
|
|
sub edx, cityObjects3D[edi].posY
|
|
cmp esi, CITY_TRAFFIC_WEST
|
|
jne @F
|
|
neg eax
|
|
neg edx
|
|
@@:
|
|
push eax
|
|
push edx
|
|
test eax, eax
|
|
jns @F
|
|
neg eax
|
|
@@:
|
|
test edx, edx
|
|
jns @F
|
|
neg edx
|
|
@@:
|
|
lea ebx, [edx*2]
|
|
cmp eax, ebx
|
|
ja city_car_longitudinal
|
|
lea ebx, [eax*2]
|
|
cmp edx, ebx
|
|
ja city_car_lateral
|
|
pop edx
|
|
pop eax
|
|
mov ebx, 1
|
|
test eax, eax
|
|
jle @F
|
|
mov ebx, 3
|
|
@@:
|
|
test edx, edx
|
|
jns city_car_set
|
|
mov ebx, 7
|
|
test eax, eax
|
|
jle city_car_set
|
|
mov ebx, 5
|
|
jmp city_car_set
|
|
city_car_longitudinal:
|
|
pop edx
|
|
pop eax
|
|
xor ebx, ebx
|
|
test eax, eax
|
|
jle city_car_set
|
|
mov ebx, 4
|
|
jmp city_car_set
|
|
city_car_lateral:
|
|
pop edx
|
|
pop eax
|
|
mov ebx, 2
|
|
test edx, edx
|
|
jns city_car_set
|
|
mov ebx, 6
|
|
city_car_set:
|
|
mov eax, cityObjects3D[edi].frame
|
|
and eax, 8
|
|
add eax, ebx
|
|
mov cityObjects3D[edi].frame, eax
|
|
city_car_next:
|
|
inc esi
|
|
cmp esi, CITY_TRAFFIC_WEST+1
|
|
jb city_car_view
|
|
ret
|
|
AnimateCityCars3D ENDP
|
|
|
|
; Pedestrians follow continuous curb routes, independently of rendering FPS.
|
|
AnimateCityPedestrians3D PROC uses ebx esi edi
|
|
local walkingFrame:DWORD
|
|
xor esi, esi
|
|
city_ped_route:
|
|
imul ebx, esi, SIZEOF CityWalkRoute3D
|
|
add ebx, OFFSET cityWalkRoutes3D
|
|
mov eax, cityClock3D
|
|
add eax, [ebx].CityWalkRoute3D.phaseOffset
|
|
xor edx, edx
|
|
mov ecx, [ebx].CityWalkRoute3D.halfPeriod
|
|
shl ecx, 1
|
|
div ecx
|
|
mov eax, edx
|
|
mov edx, [ebx].CityWalkRoute3D.firstFrame
|
|
mov walkingFrame, edx
|
|
cmp eax, [ebx].CityWalkRoute3D.halfPeriod
|
|
jb city_ped_forward
|
|
sub eax, [ebx].CityWalkRoute3D.halfPeriod
|
|
add walkingFrame, 8
|
|
mov ecx, [ebx].CityWalkRoute3D.maxX
|
|
sub ecx, [ebx].CityWalkRoute3D.minX
|
|
mul ecx
|
|
div [ebx].CityWalkRoute3D.halfPeriod
|
|
neg eax
|
|
add eax, [ebx].CityWalkRoute3D.maxX
|
|
jmp city_ped_position
|
|
city_ped_forward:
|
|
mov ecx, [ebx].CityWalkRoute3D.maxX
|
|
sub ecx, [ebx].CityWalkRoute3D.minX
|
|
; Keep the high product: route distance * milliseconds exceeds 32 bits.
|
|
mul ecx
|
|
div [ebx].CityWalkRoute3D.halfPeriod
|
|
add eax, [ebx].CityWalkRoute3D.minX
|
|
city_ped_position:
|
|
imul edi, [ebx].CityWalkRoute3D.objectIndex, SIZEOF CityProp3D
|
|
mov cityObjects3D[edi].posX, eax
|
|
mov eax, [ebx].CityWalkRoute3D.curbY
|
|
mov cityObjects3D[edi].posY, eax
|
|
mov eax, cityClock3D
|
|
add eax, [ebx].CityWalkRoute3D.phaseOffset
|
|
xor edx, edx
|
|
div [ebx].CityWalkRoute3D.poseMs
|
|
and eax, 7
|
|
add eax, walkingFrame
|
|
mov cityObjects3D[edi].frame, eax
|
|
inc esi
|
|
cmp esi, CITY_PEDESTRIAN_COUNT
|
|
jb city_ped_route
|
|
ret
|
|
AnimateCityPedestrians3D ENDP
|