| ← D00C | Map | D186 → |
D05B: Orb (ball-capturer) behavior handler
|
Behavior handler for the orb, which captures ball A and spits it back out. On top of the shared spawn and death reactions it runs its own hunt, chew, spit and give-up.
|
|||||||||||
|
|||||||||||
|
A capture of the ball scores 500 points. An orb that catches nothing within 250 frames turns into a capsule.
The orb homes on ball A and captures it. In its default state it chases ball A. When it overlaps ball A, it chews the ball for 110 frames, then spits it back toward the bat.
Hunt, the default: it forces the hunt sprite into the sprite record each frame, then steers. While the bat holds ball A, for a serve or a glue catch, the orb wanders on a random heading. In free flight it homes on the ball.
It avoids walls, advances, and leaves play at the far edge. A counter in its record counts to 250 frames, and at 250 the orb gives up. It then tests for the catch. An overlap enters the chew. Otherwise the sweep destroys it.
Chew: on the first frame it deactivates the ball. It clears ball A's active flag so nothing draws the ball. It runs the chew animation, and loops frames 21–28.
For its first 10 frames, timed by a counter in its record, the orb still homes on the ball and moves. The ball stays where it was caught. After that, a second counter is a hold timer that ticks to 100 frames. The ball's Y is pinned to the orb's Y while it ticks. At animation frame 20 it arms the chew sound. When the hold timer reaches 100 it switches to the spit.
Spit: it plays the continuation of the orb animation, and at animation frame 6 it arms the orb-spit sound. From animation frame 8 on it points ball A's sprite at the spat-out ball. It also re-arms the capture slide, which makes the ball active again and walks it back to the bat side.
QUIRK: the spit code carries a death transition on animation frame 14. It sits on the branch for frames below 8, where the frame can never be 14. The orb therefore never dies here. From frame 8 onward it merely re-arms the ball every frame. The spit has no self-exit.
The slot is reclaimed externally, via the ball-loss path. Each frame it re-arms the capture slide. The slide walks the caught ball to the bat's losing edge at 5 px/frame and, on arrival, loses the ball. With ball B in play, ball B takes over as ball A and the re-armed slide carries it off too. When the last ball goes, the last-ball branch zeroes the type field of every inhabitant record. The dispatcher therefore skips the now-empty orb slot on the next pass.
Give up: it zeroes the anim frame, state and both counters. It then rewrites the type field. The slot becomes a capsule on the next frame.
|
|||||||||||
| update_orb | D05B | CALL inhabitant_react_state | Run the shared reaction machine; while a spawn or death animation plays it returns carry and the orb skips its own update this frame. | ||||||||
| D05E | RET C | ||||||||||
| D05F | LD A,(IY+$0C) | Branch on the reaction state: the chew runs here; the spit, give-up and hunt below. | |||||||||
| D062 | CP $03 | ||||||||||
| D064 | JR NZ,update_orb_5 | ||||||||||
| D066 | LD A,(IY+$0B) | On the first chew frame only, deactivate the captured ball. | |||||||||
| D069 | OR A | ||||||||||
| D06A | JR NZ,update_orb_0 | ||||||||||
| D06C | PUSH IX | Clear ball A's active flag so nothing draws the ball. | |||||||||
| D06E | LD IX,ball_a_object | ||||||||||
| D072 | RES 0,(IX+$08) | ||||||||||
| D076 | POP IX | ||||||||||
| update_orb_0 | D078 | CP $14 | Partway through the chew animation, arm the 49-step chew sound. | ||||||||
| D07A | JR NZ,update_orb_1 | ||||||||||
| D07C | LD A,$01 | ||||||||||
| D07E | LD (chew_counter),A | ||||||||||
| update_orb_1 | D081 | LD HL,anim_orb | Advance the chew animation by one frame. | ||||||||
| D084 | CALL advance_anim | ||||||||||
| D087 | LD A,(IY+$0B) | Loop the chew tail: wrap the animation frame back to 21 at the tail's end, so frames 21–28 cycle. | |||||||||
| D08A | CP $1D | ||||||||||
| D08C | JR C,update_orb_2 | ||||||||||
| D08E | LD (IY+$0B),$15 | ||||||||||
| update_orb_2 | D092 | LD A,(IY+$09) | Early in the chew, close on the ball. Once the chew count reaches its limit, hold the ball in place. | ||||||||
| D095 | CP $0A | ||||||||||
| D097 | JR NZ,update_orb_4 | ||||||||||
| D099 | INC (IY+$0A) | Hold timer: once it runs out, switch to the spit. | |||||||||
| D09C | LD A,(IY+$0A) | ||||||||||
| D09F | CP $64 | ||||||||||
| D0A1 | JR NZ,update_orb_3 | ||||||||||
| D0A3 | LD (IY+$0C),$04 | Begin the spit and reset the animation frame. | |||||||||
| D0A7 | LD (IY+$0B),$00 | ||||||||||
| update_orb_3 | D0AB | LD A,(IX+$01) | Pin the ball's Y to the orb's so it tracks the orb while held. | ||||||||
| D0AE | PUSH IX | ||||||||||
| D0B0 | LD IX,ball_a_object | ||||||||||
| D0B4 | LD (IX+$01),A | ||||||||||
| D0B7 | POP IX | ||||||||||
| D0B9 | RET | ||||||||||
| update_orb_4 | D0BA | INC (IY+$09) | Under 10 frames in: step toward the ball and advance. | ||||||||
| D0BD | LD B,$01 | ||||||||||
| D0BF | CALL head_toward_target | ||||||||||
| D0C2 | CALL move_object | ||||||||||
| D0C5 | RET | ||||||||||
| update_orb_5 | D0C6 | CP $04 | Spit the chewed ball back out. | ||||||||
| D0C8 | JR NZ,update_orb_8 | ||||||||||
| D0CA | LD A,(IY+$0B) | Partway through the spit animation, arm the orb-spit sound. | |||||||||
| D0CD | CP $06 | ||||||||||
| D0CF | JR NZ,update_orb_6 | ||||||||||
| D0D1 | LD A,$05 | ||||||||||
| D0D3 | LD (orb_spit_timer),A | ||||||||||
| update_orb_6 | D0D6 | LD HL,anim_orb+$3A | Advance the spit animation (the continuation of the orb animation). | ||||||||
| D0D9 | CALL advance_anim | ||||||||||
| D0DC | LD A,(IY+$0B) | Past the first frames of the spit, release the ball. | |||||||||
| D0DF | CP $08 | ||||||||||
| D0E1 | JR C,update_orb_7 | ||||||||||
| D0E3 | LD A,$01 | Re-arm the capture slide that walks the ball back to the bat side. | |||||||||
| D0E5 | LD (capture_slide),A | ||||||||||
| D0E8 | PUSH IX | Point ball A's sprite at the spat-out ball. | |||||||||
| D0EA | LD IX,ball_a_object | ||||||||||
| D0EE | LD HL,slot_orb_ball | ||||||||||
| D0F1 | LD (IX+$06),L | ||||||||||
| D0F4 | LD (IX+$07),H | ||||||||||
| D0F7 | POP IX | ||||||||||
| D0F9 | RET | ||||||||||
| update_orb_7 | D0FA | CP $0E | QUIRK dead code: the branch above enters only while the spit animation is in its early frames. This later frame therefore never matches, and the death it would set never fires. | ||||||||
| D0FC | RET NZ | ||||||||||
| D0FD | LD (IY+$0C),$02 | ||||||||||
| D101 | LD (IY+$0B),$00 | ||||||||||
| D105 | RET | ||||||||||
| update_orb_8 | D106 | CP $05 | Give up the hunt. | ||||||||
| D108 | JR NZ,update_orb_9 | ||||||||||
| D10A | XOR A | Reset the animation frame, state and both counters. | |||||||||
| D10B | LD (IY+$0B),A | ||||||||||
| D10E | LD (IY+$0C),A | ||||||||||
| D111 | LD (IY+$09),A | ||||||||||
| D114 | LD (IY+$0A),A | ||||||||||
| D117 | LD (IY+$08),$08 | Morph into a capsule: rewrite the type field so the capsule handler runs this slot next frame. | |||||||||
| D11B | RET | ||||||||||
| update_orb_9 | D11C | INC (IY+$09) | Hunt timer: once it runs out with no catch, give up. | ||||||||
| D11F | LD A,(IY+$09) | ||||||||||
| D122 | CP $FA | ||||||||||
| D124 | JR NZ,update_orb_10 | ||||||||||
| D126 | LD (IY+$0C),$05 | Arm the give-up reset. | |||||||||
| update_orb_10 | D12A | LD HL,slot_orb_hunt | Force the orb's hunt sprite into the sprite record each frame. | ||||||||
| D12D | LD (IX+$06),L | ||||||||||
| D130 | LD (IX+$07),H | ||||||||||
| D133 | LD A,(ball_a_on_bat) | While the bat holds ball A, for a serve or a glue catch, wander. In free flight, home on it. | |||||||||
| D136 | OR A | ||||||||||
| D137 | JR Z,update_orb_11 | ||||||||||
| D139 | XOR A | Ball on the bat: wander on a random heading. | |||||||||
| D13A | CALL pick_wander_heading | ||||||||||
| D13D | JR update_orb_12 | ||||||||||
| update_orb_11 | D13F | LD B,$01 | Free flight: steer toward the ball. | ||||||||
| D141 | CALL head_toward_target | ||||||||||
| update_orb_12 | D144 | CALL object_avoid_walls | Avoid walls, advance, and despawn off the far edge. | ||||||||
| D147 | CALL move_object | ||||||||||
| D14A | CALL inhabitant_offscreen | ||||||||||
| D14D | RET C | ||||||||||
| D14E | LD A,C | Test the orb against ball A for a catch through the first and second overlap operands. | |||||||||
| D14F | LD (overlap_slot_1),A | ||||||||||
| D152 | LD A,$01 | ||||||||||
| D154 | LD (overlap_slot_2),A | ||||||||||
| D157 | CALL overlap_pair | ||||||||||
| D15A | OR A | ||||||||||
| D15B | JR NZ,update_orb_13 | ||||||||||
| D15D | CALL overlap_sweep | No catch: the sweep destroys the orb. | |||||||||
| D160 | OR A | ||||||||||
| D161 | RET Z | ||||||||||
| D162 | LD (IY+$0B),$00 | Die: restart the animation and enter the death reaction. | |||||||||
| D166 | LD (IY+$0C),$02 | ||||||||||
| D16A | RET | ||||||||||
| update_orb_13 | D16B | XOR A | Catch: zero the anim frame and both counters and enter the chew. | ||||||||
| D16C | LD (IY+$0B),A | ||||||||||
| D16F | LD (IY+$09),A | ||||||||||
| D172 | LD (IY+$0A),A | ||||||||||
| D175 | LD (IY+$0C),$03 | ||||||||||
| D179 | INC A | Flag the capture: set the ball-captured flag and request the glue release. | |||||||||
| D17A | LD (capture_active),A | ||||||||||
| D17D | LD (glue_release_req),A | ||||||||||
| D180 | LD A,$32 | Award 500 points for the catch, banked as this frame's pending points. | |||||||||
| D182 | LD (pending_score),A | ||||||||||
| D185 | RET | ||||||||||
| ← D00C | Map | D186 → |
