GSCats/projectile.s
2023-08-04 19:37:09 -07:00

995 lines
19 KiB
ArmAsm

;
; projectile
; Code and data structures related to the projectiles
;
; Created by Quinn Dunki on 8/13/17
;
projectileData:
; Gameobject data (we're a subclass, effectively)
.word -1 ; Pos X in pixels (from left terrain edge)
.word 0 ; Pos Y in pixels (from bottom terrain edge)
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; Saved background
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.word 0 ; Pos X (12.4 fixed point)
.word 0 ; Pos Y (12.4 fixed point)
.word 0 ; Velocity X (8.8 fixed point)
.word 0 ; Velocity Y (8.8 fixed point)
.word 0 ; Type
.word 1 ; New?
.word 0 ; Static?
.word 0 ; Owner (player index)
.word 0 ; Facing (0,1) = (+X,-X)
.word 0 ; Scratch space for subclasses
.word 0 ; Age (in turns)
.word 0 ; Deployment delay needed?
.repeat 100
.byte 0 ; Padding to 256-byte boundary
.endrepeat
; Gameobject data (we're a subclass, effectively)
.word -1 ; Pos X in pixels (from left terrain edge)
.word 0 ; Pos Y in pixels (from bottom terrain edge)
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; Saved background
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.word 0 ; Pos X (12.4 fixed point)
.word 0 ; Pos Y (12.4 fixed point)
.word 0 ; Velocity X (8.8 fixed point)
.word 0 ; Velocity Y (8.8 fixed point)
.word 0 ; Type
.word 1 ; New?
.word 0 ; Static?
.word 0 ; Owner (player index)
.word 0 ; Facing (0,1) = (+X,-X)
.word 0 ; Scratch space for subclasses
.word 0 ; Age (in turns)
.repeat 102
.byte 0 ; Padding to 256-byte boundary
.endrepeat
; Gameobject data (we're a subclass, effectively)
.word -1 ; Pos X in pixels (from left terrain edge)
.word 0 ; Pos Y in pixels (from bottom terrain edge)
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; Saved background
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.word 0 ; Pos X (12.4 fixed point)
.word 0 ; Pos Y (12.4 fixed point)
.word 0 ; Velocity X (8.8 fixed point)
.word 0 ; Velocity Y (8.8 fixed point)
.word 0 ; Type
.word 1 ; New?
.word 0 ; Static?
.word 0 ; Owner (player index)
.word 0 ; Facing (0,1) = (+X,-X)
.word 0 ; Scratch space for subclasses
.word 0 ; Age (in turns)
.repeat 102
.byte 0 ; Padding to 256-byte boundary
.endrepeat
; Byte offsets for that-^ data structure can be found in equates.s
GRAVITY = $fffa ; 8.8 fixed point
projectileTypes:
PT_SPIT = 0
PT_BOMB = 1
PT_FAN = 2
; Spit
.word 4 ; Damage
.word 3 ; Crater radius
.word 4 ; Frame 0
.word 6 ; Frame 1
.word 8 ; Frame 2
.addr 0 ; Deploy
.addr 0 ; Update
.addr 0 ; Render
.addr 0 ; Cleanup
.word 1 ; Directional
.word 1 ; Mining
.repeat 10
.byte 0 ; Padding to 32-byte boundary
.endrepeat
; Bomb
.word 50 ; Damage
.word 10 ; Crater radius
.word 3 ; Frame 0
.word 3 ; Frame 1
.word 3 ; Frame 2
.addr 0 ; Deploy
.addr 0 ; Update
.addr 0 ; Render
.addr 0 ; Cleanup
.word 0 ; Directional
.word 0 ; Mining
.repeat 10
.byte 0 ; Padding to 32-byte boundary
.endrepeat
; Fan
.word 0 ; Damage
.word 3 ; Crater radius
.word 12 ; Frame 0
.word 12 ; Frame 1
.word 12 ; Frame 2
.addr deployFan ; Deploy
.addr updateFan ; Update
.addr renderFan ; Render
.addr deleteFan ; Cleanup
.word 1 ; Directional
.word 0 ; Mining
.repeat 10
.byte 0 ; Padding to 32-byte boundary
.endrepeat
PT_DAMAGE = 0 ; Byte offsets into projectile type data structure
PT_RADIUS = 2
PT_FRAME0 = 4
PT_FRAME1 = 6
PT_FRAME2 = 8
PT_DEPLOY = 10
PT_UPDATE = 12
PT_RENDER = 14
PT_CLEANUP = 16
PT_DIRECTIONAL = 18
PT_MINING = 20
.macro PROJECTILEPTR_Y
tya ; Pointer to projectile structure from index
asl
asl
asl
asl
asl
asl
asl
asl
tay
.endmacro
.macro PROJECTILETYPEPTR_Y
tya ; Pointer to projectile type structure from index
asl
asl
asl
asl
asl
tay
.endmacro
.macro PROJECTILETYPEPTR_X
txa ; Pointer to projectile type structure from index
asl
asl
asl
asl
asl
tax
.endmacro
projectileParams:
.word 0 ; Starting pos X
.word 0 ; Starting pos Y
.word 0 ; Initial angle
.word 0 ; Initial power
.word 0 ; Type
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; allocProjectile
;
; Returns offset of projectile structure in Y, or -1 if none available
;
allocProjectile:
SAVE_AX
ldx #0
allocProjectileLoop:
txy
PROJECTILEPTR_Y
lda projectileData+GO_POSX,y
bmi allocProjectileDone
inx
cpx #MAXPROJECTILES
bne allocProjectileLoop
ldy #-1
allocProjectileDone:
RESTORE_AX
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; fireProjectile
;
;
fireProjectile:
SAVE_AXY
; Allocate a projectile
jsr allocProjectile
cpy #-1
beq fireProjectileDone
; Set up projectile structure
lda projectileParams ; X pos
sta projectileData+GO_POSX,y
lda projectileParams+2 ; Y pos
sta projectileData+GO_POSY,y
lda #0
sta projectileData+JD_STATIC,y
sta projectileData+JD_AGE,y
sty projectileActive
lda currentPlayer
sta projectileData+JD_OWNER,y
; Set facing. For now assume player orientations are constant
beq fireProjectilePosX
lda #1
sta projectileData+JD_FACING,y
bra fireProjectileSetup
fireProjectilePosX:
lda #0
sta projectileData+JD_FACING,y
fireProjectileSetup:
lda projectileParams ; Fixed point version of X pos
asl
asl
asl
asl
sta projectileData+JD_PRECISEX,y
lda projectileParams+2 ; Fixed point version of Y pos
asl
asl
asl
asl
sta projectileData+JD_PRECISEY,y
lda projectileParams+8 ; Type
sta projectileData+JD_TYPE,y
; Check for special deployment code
phy
tay ; Find projectile type data
PROJECTILETYPEPTR_Y
lda projectileTypes+PT_DEPLOY,y
beq fireProjectileStandardDeploy
ply
JSRA
bra fireProjectileFinish
fireProjectileStandardDeploy:
ply
; Standard physics setup
jsr prepareProjectilePhysics
fireProjectileFinish:
lda #1
sta projectileData+JD_NEW,y
fireProjectileDone:
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; prepareProjectilePhysics
;
; Y: Index to projectile structure
;
prepareProjectilePhysics:
SAVE_AXY
lda projectileParams+6 ; Convert power to 8.8
asl
asl
asl
asl
asl
asl
asl
asl
sta projectileParams+6
lda projectileParams+4 ; Convert angle to vector
asl
tax
lda angleToVectorX,x ; Velocity X (unit vector)
sta PARAML1
lda projectileParams+6 ; Scale by power
sta PARAML0
jsr mult88
sta projectileData+JD_VX,y
lda projectileParams+4 ; Convert angle to vector
asl
tax
lda angleToVectorY,x ; Velocity Y (unit vector)
sta PARAML1
lda projectileParams+6 ; Scale by power
sta PARAML0
jsr mult88
sta projectileData+JD_VY,y
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; updateProjectilesPhysics
;
;
updateProjectilesPhysics:
SAVE_AXY
ldx #0
updateProjectilesPhysicsLoop:
txy
PROJECTILEPTR_Y
jsr updateProjectilePhysics
updateProjectilesPhysicsSkip:
inx
cpx #MAXPROJECTILES
bne updateProjectilesPhysicsLoop
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; updateProjectilePhysics
;
; Y = Offset to projectile structure
;
updateProjectilePhysics:
SAVE_AXY
lda projectileData+GO_POSX,y
bmi updateProjectilePhysicsDone ; Not allocated
lda projectileData+JD_STATIC,y
bne updateProjectilePhysicsSpecial ; Static
updateProjectilePhysicsActive:
; Integrate gravity over velocity
lda projectileData+JD_VY,y
clc
adc #GRAVITY
sta projectileData+JD_VY,y
; Integrate X velocity over position
lda projectileData+JD_VX,y
; Convert 8.8 to 12.4
cmp #$8000
ror
cmp #$8000
ror
cmp #$8000
ror
cmp #$8000
ror
clc
adc projectileData+JD_PRECISEX,y
adc globalWind ; Add wind
sta projectileData+JD_PRECISEX,y
; Convert to integer for rendering
lsr
lsr
lsr
lsr
sta projectileData+GO_POSX,y
bmi updateProjectilePhysicsDelete
cmp #TERRAINWIDTH-GAMEOBJECTWIDTH-1
bpl updateProjectilePhysicsDelete
updateProjectilePhysicsContinue:
; Integrate Y velocity over position
lda projectileData+JD_VY,y
; Convert 8.8 to 12.4
cmp #$8000
ror
cmp #$8000
ror
cmp #$8000
ror
cmp #$8000
ror
clc
adc projectileData+JD_PRECISEY,y
sta projectileData+JD_PRECISEY,y
; Convert to integer for rendering
lsr
lsr
lsr
lsr
sta projectileData+GO_POSY,y
cmp #GAMEOBJECTHEIGHT
bmi updateProjectilePhysicsDelete
updateProjectilePhysicsSpecial:
; Check for special update code
phy
lda projectileData+JD_TYPE,y
tay
PROJECTILETYPEPTR_Y
lda projectileTypes+PT_UPDATE,y
beq updateProjectilePhysicsNormalUpdate
ply
JSRA
updateProjectilePhysicsDone:
RESTORE_AXY
rts
updateProjectilePhysicsDelete:
jsr endDeleteCurrProjectile
bra updateProjectilePhysicsDone
updateProjectilePhysicsNormalUpdate:
ply
bra updateProjectilePhysicsDone
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; updateProjectilesCollisions
;
;
updateProjectilesCollisions:
SAVE_AXY
ldx #0
updateProjectilesCollisionsLoop:
txy
PROJECTILEPTR_Y
jsr updateProjectileCollisions
updateProjectilesCollisionsSkip:
inx
cpx #MAXPROJECTILES
bne updateProjectilesCollisionsLoop
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; updateProjectileCollisions
;
; Y = Offset to projectile structure
;
updateProjectileCollisions:
SAVE_AXY
; Check for player collisions
lda projectileData+JD_STATIC,y
bne updateProjectileCollisionsDone ; Static
lda projectileData+GO_POSX,y
bmi updateProjectileCollisionsDone ; Not allocated
sta rectParams
lda projectileData+GO_POSY,y
sta rectParams+2
lda #GAMEOBJECTWIDTH
sta rectParams+4
lda #GAMEOBJECTHEIGHT
sta rectParams+6
ldx #0
updateProjectileCollisionsPlayerLoop:
cpx currentPlayer
beq updateProjectileCollisionsPlayerNext
jsr playerIntersectRect
cmp #0
bne updateProjectileCollisionsPlayerHit
updateProjectileCollisionsPlayerNext:
inx
cpx #NUMPLAYERS
bne updateProjectileCollisionsPlayerLoop
; Check for terrain collisions
lda projectileData+GO_POSX,y
inc
inc
sta rectParams
lda projectileData+GO_POSY,y
clc
inc
inc
sta rectParams+2
lda #GAMEOBJECTWIDTH-4
sta rectParams+4
lda #GAMEOBJECTHEIGHT-4
sta rectParams+6
jsr intersectRectTerrain
cmp #0
bne updateProjectileCollisionsTerrainHit
updateProjectileCollisionsDone:
RESTORE_AXY
rts
updateProjectileCollisionsPlayerHit:
jsr processPlayerImpact
jsr endDeleteCurrProjectile
bra updateProjectileCollisionsDone
updateProjectileCollisionsTerrainHit:
jsr processTerrainImpact
jsr endDeleteCurrProjectile
bra updateProjectileCollisionsDone
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; processTurnForProjectiles
;
;
processTurnForProjectiles:
SAVE_AXY
ldx #0
processTurnForProjectilesLoop:
txy
PROJECTILEPTR_Y
lda projectileData+JD_AGE,y
inc
sta projectileData+JD_AGE,y
processTurnForProjectilesSkip:
inx
cpx #MAXPROJECTILES
bne processTurnForProjectilesLoop
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; endDeleteCurrProjectile
;
; Trashes A and Y
;
endDeleteCurrProjectile:
lda #projectileData
clc
adc projectileActive
sta PARAML0
jsr unrenderGameObject
ldy projectileActive
jsr deleteProjectile
bra endProjectile
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; deleteVisibleProjectile
;
; Y = Projectile offset
; Trashes A
;
deleteVisibleProjectile:
lda #projectileData
sta PARAML0
tya
clc
adc PARAML0
sta PARAML0
jsr unrenderGameObject
bra deleteProjectile
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; endProjectile
;
; Trashes A
;
endProjectile:
lda #1
sta turnRequested
lda #-1
sta projectileActive
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; deleteProjectile
;
; Y = Projectile offset
; Trashes A
;
deleteProjectile:
lda #-1
sta projectileData+GO_POSX,y
; Check for special cleanup code
lda projectileData+JD_TYPE,y
tax ; Find projectile type data
PROJECTILETYPEPTR_X
lda projectileTypes+PT_CLEANUP,x
beq deleteProjectileDone
JSRA
deleteProjectileDone:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; protectProjectiles
;
;
protectProjectiles:
SAVE_AXY
ldx #0
protectProjectilesLoop:
txy
PROJECTILEPTR_Y
lda projectileData+GO_POSX,y
bpl protectProjectilesGotOne
protectProjectilesContinue:
inx
cpx #MAXPROJECTILES
beq protectProjectilesDone
bra protectProjectilesLoop
protectProjectilesGotOne:
lda #projectileData+GO_POSX
sta PARAML0
clc
tya
adc PARAML0
sta PARAML0
phx
jsr vramPtr
cpx #$ffff
beq protectProjectilesOffscreen
lda #projectileData+GO_BACKGROUND
sta PARAML0
clc
tya
adc PARAML0
sta PARAML0
jsr protectGameObject
plx
bra protectProjectilesContinue
protectProjectilesDone:
RESTORE_AXY
rts
protectProjectilesOffscreen:
plx
bra protectProjectilesContinue
UPANGLE = $00af
DNANGLE = $ffaf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; renderProjectiles
;
;
renderProjectiles:
SAVE_AXY
ldx #0
renderProjectilesLoop:
txy
PROJECTILEPTR_Y
jsr renderProjectile
renderProjectilesSkip:
inx
cpx #MAXPROJECTILES
bne renderProjectilesLoop
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; renderProjectile
;
; Y = Offset to projectile structure
; Trashes SCRATCHL
;
renderProjectile:
SAVE_AXY
lda projectileData+GO_POSX,y
bpl renderProjectileDoIt
jmp renderProjectileDone
renderProjectileDoIt:
lda projectileData+JD_TYPE,y
tax
PROJECTILETYPEPTR_X
lda #projectileData ; Calculate pointer for game object render
sta PARAML0
clc
tya
adc PARAML0
sta PARAML0
; Determine which sprite to use
lda projectileData+JD_VY,y
bmi renderProjectileNegYPosX
cmp #UPANGLE
bmi renderProjectileFlat
renderProjectileUpAngle:
lda projectileTypes+PT_FRAME0,x ; Up angle
bra renderProjectileGoSprite
renderProjectileNegYPosX:
cmp #DNANGLE
bpl renderProjectileFlat
renderProjectileDownAngle:
lda projectileTypes+PT_FRAME2,x ; Down angle
bra renderProjectileGoSprite
renderProjectileFlat:
lda projectileTypes+PT_FRAME1,x ; Flat
renderProjectileGoSprite:
sta SCRATCHL
lda projectileTypes+PT_DIRECTIONAL,x
beq renderProjectileGoSpriteNormal
lda projectileData+JD_FACING,y ; Projectile is directional, so flip sprite if needed
beq renderProjectileGoSpriteNormal
lda SCRATCHL
inc ; Flip it!
bra renderProjectileGoSpriteFlipped
renderProjectileGoSpriteNormal:
lda SCRATCHL
renderProjectileGoSpriteFlipped:
jsr renderGameObject
; Check for special deployment code
lda projectileTypes+PT_RENDER,x
beq renderProjectileDone
JSRA
renderProjectileDone:
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; unrenderProjectiles
;
;
unrenderProjectiles:
SAVE_AXY
ldx #0
unrenderProjectilesLoop:
txy
PROJECTILEPTR_Y
jsr unrenderProjectile
unrenderProjectilesSkip:
inx
cpx #MAXPROJECTILES
bne unrenderProjectilesLoop
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; unrenderProjectile
;
; Y = Offset to projectile structure
;
unrenderProjectile:
pha
lda projectileData+GO_POSX,y
bpl unrenderProjectileActive
jmp unrenderProjectileDone
unrenderProjectileActive:
lda projectileData+JD_NEW,y
beq unrenderProjectileDoIt
lda #0
sta projectileData+JD_NEW,y
jmp unrenderProjectileDone
unrenderProjectileDoIt:
lda #projectileData
sta PARAML0
clc
tya
adc PARAML0
sta PARAML0
jsr unrenderGameObject
unrenderProjectileDone:
pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; processPlayerImpact
;
; X = Index of player that was hit
; Y = Offset to projectile structure
;
processPlayerImpact:
phy
; Do hit animation
txy
jsr renderHitAnimation
PLAYERPTR_X
; Find projectile data structure
ply
lda projectileData+JD_TYPE,y
tay
PROJECTILETYPEPTR_Y
; Apply damage
lda playerData+PD_ANGER,x
sec
sbc projectileTypes+PT_DAMAGE,y
; Check for death
beq processPlayerImpactDeath
bmi processPlayerImpactDeath
sta playerData+PD_ANGER,x
rts
processPlayerImpactDeath:
lda currentPlayer
sta gameOver
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; processTerrainImpact
;
; Trashes A,Y, SCRATCHL, PARAML0, PARAML1
;
processTerrainImpact:
ldy projectileActive
; Shift impact point to forward bottom corner according to V
lda projectileData+JD_VX,y
bmi processTerrainImpactNegative
lda projectileData+GO_POSX,y
clc
adc #GAMEOBJECTWIDTH/2+1 ; A fudge that makes crater location look better in this direction, and tunneling work better
bra processTerrainImpactStoreContinue
processTerrainImpactNegative:
lda projectileData+GO_POSX,y
clc
adc #GAMEOBJECTWIDTH/4-1 ; A fudge that makes crater location look better in this direction, and tunneling work better
processTerrainImpactStoreContinue:
sta PARAML0
pha ; Dirt explosion will need this
sta compileTerrainRowStart ; Terrain chunk compiler will need this
sta compileTerrainRowEnd
lda projectileData+GO_POSY,y
sec
sbc #GAMEOBJECTHEIGHT ; This fudge makes tunneling work better
sta PARAML1
pha ; Dirt explosion will need this
lda projectileData+JD_TYPE,y
tay
PROJECTILETYPEPTR_Y
sec ; Quick sidebar to calculate crater compiling extents while we have the pointers
lda #TERRAINWIDTH
sbc compileTerrainRowStart
sbc projectileTypes+PT_RADIUS,y
sbc projectileTypes+PT_RADIUS,y
sta compileTerrainRowStart
sec
lda #TERRAINWIDTH
sbc compileTerrainRowEnd
clc
adc projectileTypes+PT_RADIUS,y
adc #GAMEOBJECTWIDTH
sta compileTerrainRowEnd
lda projectileTypes+PT_RADIUS,y
tay
phy ; We'll need the radius in a moment
jsr craterTerrain
jsr unclipTerrain
; Recompile the rows affected by the crater
clc
lda PARAML1 ; Impact point is top row to recompile
adc #GAMEOBJECTHEIGHT ; Expand recompile area upwards because of tunneling fudge
tax
clc
pla
adc #GAMEOBJECTHEIGHT ; Expand "vertical" radius area because of tunneling fudge
sta SCRATCHL ; Need radius in a memory location for this math
txa
sec
sbc SCRATCHL ; Need to subtract diameter to ensure enough terrain is recompiled. Not 100% sure why?
sbc SCRATCHL
tay
jsr compileTerrainChunk
jsr clipTerrain
pla
sta PARAML1
pla
sta PARAML0
jsr createDirtExplosion
; Cash in the dirt if needed
ldy projectileActive
lda projectileData+JD_TYPE,y
tay
PROJECTILETYPEPTR_Y
lda projectileTypes+PT_MINING,y
beq processTerrainImpactDone
lda craterTerrainAccumulator
lsr ; Dirt to treats conversion rate
lsr
lsr
inc ; Ensure minimum one treat
sta PARAML0
jsr awardTreats
processTerrainImpactDone:
rts