-
Notifications
You must be signed in to change notification settings - Fork 10
/
bullet.s
416 lines (377 loc) · 13.1 KB
/
bullet.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
GRENADE_DMG_RADIUS = 24
GRENADE_MAX_YSPEED = 6*8
GRENADE_ACCEL = 4
GRENADE_BRAKE = 8
EXTINGUISH_ADD = 5
EXTINGUISH_THRESHOLD = 45
; Extinguisher powder update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MovePowder: lda #3
ldy #1
jsr OneShotAnimation
bcs MMH_Remove
ldy #ACTI_FIRSTNPC-1
MP_GetNextTarget:
iny
cpy #ACTI_LASTNPC+1
bcs MP_Done
lda actT,y ;Check collision only against fires
cmp #ACT_FIRE
bne MP_GetNextTarget
jsr CheckActorCollision
bcc MP_GetNextTarget
lda #COLOR_FLICKER
sta actFlash,y
lda actTime,y ;Reduce fire "oxygen level"
adc #EXTINGUISH_ADD-1
sta actTime,y
jmp RemoveActor
MP_Done: jmp MoveBullet_NoCollision
; Smoketrail update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveSmokeTrail: ldy #1
SKIP2
; Small water splash update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveSmallSplash:ldy #2
SKIP2
; Explosion / large water splash update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveExplosion: ldy #4
lda #1
OneShotAnimateAndRemove:
jsr OneShotAnimation
bcs MMH_Remove
MExpl_NoAnimation:
MRckt_Done:
MExpl_NoRemove: rts
; Melee hit update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveMeleeHit: jsr CheckBulletCollisionsApplyDamage
MoveSpeechBubble:
MMH_Remove: jmp RemoveActor
; Flame update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveFlame: lda #3
ldy #3
jsr OneShotAnimation
jmp MoveBullet
; Bullet update routine with muzzle flash as first frame
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveBulletMuzzleFlash:
lda actF1,x
cmp #$0a
bcs MoveBullet
adc #$0a
MBltMF_Common: sta actF1,x
jsr MoveBullet
jmp NoInterpolation ;Prevent muzzle flash from interpolating
; Shotgun bullet update routine. Expands collision and reduces damage as the
; bullet moves
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveShotgunBullet:
lda actF1,x
cmp #$0a
bcs MSBlt_Cloud
inc actFd,x
lda #$0a
bne MBltMF_Common
MBlt_Remove: jmp RemoveActor
MSBlt_Cloud: lda #2
jsr AnimationDelay
bcc MSBlt_NoAnim
lda actSizeH,x ;C=1, increase size by 2
adc #$01
sta actSizeH,x
sta actSizeU,x
sta actSizeD,x
lda actHp,x
sbc #$01 ;C=0, decrease damage by 2
sta actHp,x
inc actF1,x
MSBlt_NoAnim:
; Bullet update routine. Check collisions, then move
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveBullet: jsr CheckBulletCollisionsApplyDamage
MoveBullet_NoCollision:
dec actTime,x
bmi MBlt_Remove
; Move actor in a straight line. If hit water, transform into a splash
; If hit an obstacle, remove
; Note: do not JSR into this, but jump at the end of bullet move routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y,temp vars
MoveProjectile: lda actSX,x
jsr MoveActorX
lda actSY,x
jsr MoveActorY
jsr GetCharInfo
tay
and #CI_WATER|CI_OBSTACLE
bne MProj_ObstacleOrWater
rts
MProj_ObstacleOrWater:
and #CI_WATER
bne MProj_HitWater
tya ;If went outside zone, always remove
bmi MProj_Outside
MProj_Remove: lda actT,x
cmp #ACT_ROCKET
beq MRckt_Explode
MProj_Outside: jmp RemoveActor
MProj_HitWater: lda actT,x
cmp #ACT_LASER
bcs MProj_LargeSplash
lda #ACT_SMALLSPLASH
bne MProj_SplashOK
MProj_LargeSplash:
lda #SFX_SPLASH
jsr PlaySfx
lda #ACT_WATERSPLASH
MProj_SplashOK: jsr TransformBullet
FixSplashPosition:
lda lvlWaterSplashColor ;Color override
sta actFlash,x
lda actYL,x ;Align to char
and #$c0
sta actYL,x
FSP_Loop: jsr GetCharInfo1Above ;Steer higher until found the edge of water
and #CI_WATER
beq FSP_PosOK
lda #-8*8
jsr MoveActorY
jmp FSP_Loop
FSP_PosOK: jmp NoInterpolation
; Rocket update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveRocket: lda actTime,x
lsr
bcc MRckt_NoSmoke
lda #ACTI_FIRSTEFFECT
ldy #ACTI_LASTEFFECT
jsr GetFreeActor
bcc MRckt_NoSmoke
lda #ACT_SMOKETRAIL
jsr SpawnActor
lda #COLOR_FLICKER
sta actFlash,y
MRckt_NoSmoke: sec
jsr CheckBulletCollisions
bcc MoveBullet_NoCollision
MRckt_Explode: bcs ExplodeGrenade
; Grenade launcher grenade update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveLauncherGrenade:
lda #2
ldy #2
jsr LoopingAnimation
jsr FallingMotionCommon
bmi MGrn_HitWater
and #MB_HITWALL|MB_HITCEILING|MB_LANDED
bne ExplodeGrenade
MGrn_Common: lda actT,x ;Thrown grenade will not collide after becoming
cmp #ACT_GRENADE ;stationary
bne MGrn_CheckCollision
lda actSX,x
ora actSY,x
beq MGrn_NoCollision
MGrn_CheckCollision:
sec
jsr CheckBulletCollisions
bcs ExplodeGrenade
MGrn_NoCollision:
dec actTime,x
bpl MGrn_NoExplosion
; Explode grenade and do radius damage
;
; Parameters: X actor index
; Returns: -
; Modifies: A
ExplodeGrenade: lda #3 ;If there's ground (obstacle) below the grenade,
jsr GetCharInfoOffset ;reduce blast radius in down direction, otherwise
lsr ;it is equal size
lsr
lda #GRENADE_DMG_RADIUS
bcc EGrn_FullDamageBelow
lsr
lsr
EGrn_FullDamageBelow:
sta actSizeD,x
lda #GRENADE_DMG_RADIUS ;Expand grenade collision size for radius damage
sta actSizeH,x
sta actSizeU,x
lda #$00 ;Clear the X-speed so that possible death impulse
sta actSX,x ;only depends on enemy's relative location to the
jsr RadiusDamage ;grenade
; Turn an actor into an explosion
;
; Parameters: X actor index
; Returns: A=0
; Modifies: A
ExplodeActor: lda #SFX_EXPLOSION
jsr PlaySfx
lda #ACT_EXPLOSION
TransformBullet:sta actT,x
lda #$00
sta actF1,x
sta actFd,x
MGrn_NoExplosion:
rts
; Grenade update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MGrn_HitWater: jmp RemoveActor ;MoveWithGravity already created splash, just remove
MoveGrenade: lda #$00 ;Grenade never stays grounded
sta actMB,x
lda actSY,x ;Store original Y-speed for bounce
sta temp1
jsr FallingMotionCommon
lsr
bcc MGrn_NoBounce
lda temp1 ;Bounce: negate and halve velocity
jsr Negate8Asr8
sta actSY,x
lda #GRENADE_BRAKE ;Brake X-speed with each bounce
jsr BrakeActorX
MGrn_NoBounce: lda actMB,x
bmi MGrn_HitWater
and #MB_HITWALL|MB_HITCEILING
cmp #MB_HITWALL
bne MGrn_NoHitWall
lda actSX,x
jsr Negate8Asr8
jmp MGrn_StoreNewXSpeed
MGrn_NoHitWall: and #MB_HITCEILING ;Halve X-speed when hit ceiling
beq MGrn_NoCeiling
lda actSX,x
jsr Asr8
MGrn_StoreNewXSpeed:
sta actSX,x
MGrn_NoCeiling: jmp MGrn_Common
; Mine update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveMine: lda #7
ldy #1
jsr LoopingAnimation
lda actF1,x
ora actFd,x
bne MoveGrenade
lda #SFX_PICKUP
jsr PlaySfx
jmp MoveGrenade
; EMP blast update routine
;
; Parameters: X actor index
; Returns: -
; Modifies: A,Y
MoveEMP: lda actTime,x ;TODO: should possibly not manipulate
cmp #$01 ;background colors directly
bcc MEMP_ColorDone
beq MEMP_Restore
lda #$01
sta Irq1_Bg3+1
sta actTime,x
bne MEMP_ColorDone
MEMP_Restore: jsr SetZoneColors
MEMP_ColorDone: jsr RadiusDamage
lda #DRAIN_EMP ;EMP also damages player battery charge
jsr DrainBattery
lda actSX,x
jsr MoveActorX
lda #1
ldy #3
jsr OneShotAnimation
bcc MEMP_NoAnim
jmp RemoveActor
; Check bullet collisions and optionally apply damage
;
; Parameters: X bullet actor index, C=0 apply damage and remove bullet
; (will not return if collided), C=1 only report collision
; Returns: C=1 if collided, Y target actor
; Modifies: A,Y,tgtActIndex,temp variables
CheckBulletCollisionsApplyDamage:
clc
CheckBulletCollisions:
ror temp7
lda #<targetList
sta CBC_GetNextTarget+1
CBC_GetNextTarget:
ldy targetList
bmi CBC_Done
inc CBC_GetNextTarget+1
lda actFlags,x
eor actFlags,y
and #AF_GROUPBITS
beq CBC_GetNextTarget ;Must not be in the same group
jsr CheckActorCollision
bcc CBC_GetNextTarget
CBC_HasCollision:
lda temp7
bmi CBC_ReportOnly
sty tgtActIndex
jsr ApplyTargetDamage
ldx actIndex
pla
pla
jmp RemoveActor
CBC_Done: clc
CBC_ReportOnly:
MEMP_NoAnim: rts
; Give radius damage to all NPC actors. Prior to calling, expand the
; collision size of the source actor as necessary
;
; Parameters: X source actor index (must also be in actIndex)
; Returns: -
; Modifies: A,Y,tgtActIndex,possibly other temp registers
RadiusDamage: ldy #ACTI_LASTNPC
RD_Loop: lda actHp,y ;Skip if bystander or already dead
beq RD_Next
jsr CheckActorCollision
bcc RD_Next
sty tgtActIndex
jsr ApplyTargetDamage
ldx actIndex
ldy tgtActIndex
RD_Next: dey
bpl RD_Loop
rts