![]() |
Routines |
| Prev: C892 | Up: Map | Next: CA11 |
|
This handles the various different pursuit modes that vischars can be in (pursuing the hero, a dog moving towards food, etc.) and drives character movement.
Used by the routines at spawn_character and automatics.
|
||||||||
|
Proceed into the character behaviour handling only when this delay field hits zero. This stops characters navigating around obstacles too quickly.
|
||||||||
| character_behaviour | C918 | LD A,(IY+$07) | Fetch vischar.counter_and_flags | |||||
| C91B | LD B,A | Copy it to B | ||||||
|
If the counter field is set then decrement it and return.
|
||||||||
| C91C | AND $0F | Isolate the counter field in the bottom nibble | ||||||
| C91E | JR Z,cb_proceed | Decrement the counter if it's positive | ||||||
| C920 | DEC B | |||||||
| C921 | LD (IY+$07),B | |||||||
| C924 | RET | Return | ||||||
|
We arrive here when the counter is zero.
|
||||||||
| cb_proceed | C925 | PUSH IY | Copy the vischar pointer into HL | |||||
| C927 | POP HL | |||||||
| C928 | INC L | Advance HL to vischar.flags | ||||||
| C929 | LD A,(HL) | Fetch the flags so we can check the mode field | ||||||
| C92A | AND A | Are any flag bits set? | ||||||
| C92B | JP Z,cb_check_halt | Jump if not | ||||||
|
Check for mode 1 ("pursue")
|
||||||||
| C92E | CP $01 | Is the mode vischar_PURSUIT_PURSUE? | ||||||
| C930 | JR NZ,cb_hassle_check | Jump if not | ||||||
|
Mode 1: Hero is chased by hostiles and sent to solitary if caught.
|
||||||||
| cb_pursue_hero | C932 | PUSH HL | Preserve vischar.flags pointer | |||||
| C933 | EXX | Bank | ||||||
| C934 | POP DE | Restore vischar.flags pointer | ||||||
| C935 | INC E | Advance DE to vischar.position | ||||||
| C936 | INC E | |||||||
| C937 | INC E | |||||||
| C938 | LD HL,$81B8 | Point HL at the global map position (the hero's position) | ||||||
| C93B | LDI | Copy hero's (x,y) position to vischar.target | ||||||
| C93D | LDI | |||||||
| C93F | EXX | Unbank | ||||||
| C940 | JP cb_move | Jump to 'move' | ||||||
|
Check for mode 2 ("hassle")
|
||||||||
| cb_hassle_check | C943 | CP $02 | Is the mode vischar_PURSUIT_HASSLE? | |||||
| C945 | JR NZ,cb_dog_food_check | Jump if not | ||||||
|
Mode 2: Hero is chased by hostiles if under player control.
|
||||||||
| C947 | LD A,($A139) | Is the automatic_player_counter non-zero? | ||||||
| C94A | AND A | |||||||
|
The hero is under player control: pursue.
|
||||||||
| C94B | JR NZ,cb_pursue_hero | Jump into mode 1's pursue handler | ||||||
|
Otherwise the hero is under automatic control: hostiles lose interest and resume their original route.
|
||||||||
| C94D | LD (HL),$00 | Clear vischar.flags | ||||||
| C94F | INC L | |||||||
| C950 | JP get_target_assign_pos | Exit via get_target_assign_pos | ||||||
|
Check for mode 3 ("dog food")
|
||||||||
| cb_dog_food_check | C953 | CP $03 | Is the mode vischar_PURSUIT_DOG_FOOD? | |||||
| C955 | JR NZ,cb_saw_bribe_check | Jump if not | ||||||
|
Mode 3: The food item is near a guard dog.
|
||||||||
| C957 | PUSH HL | Preserve vischar.flags pointer | ||||||
| C958 | EX DE,HL | (get it in DE) | ||||||
| C959 | LD HL,$76FA | Point HL at item_structs[item_FOOD].room | ||||||
| C95C | BIT 7,(HL) | Is itemstruct_ROOM_FLAG_NEARBY_7 set? | ||||||
| C95E | JR Z,cb_dog_food_not_nearby | Jump if not | ||||||
|
Set the dog's target to the poisoned food location.
|
||||||||
| C960 | INC HL | Advance HL to item_structs[item_FOOD].pos.x | ||||||
| C961 | LD A,E | Point DE at vischar.target.x | ||||||
| C962 | ADD A,$03 | |||||||
| C964 | LD E,A | |||||||
| C965 | LDI | Copy (x,y) | ||||||
| C967 | LDI | |||||||
| C969 | POP HL | Restore vischar.flags pointer | ||||||
| C96A | JR cb_move | Jump to 'move' | ||||||
|
Nearby flag wasn't set.
|
||||||||
| cb_dog_food_not_nearby | C96C | XOR A | Clear vischar.flags | |||||
| C96D | LD (DE),A | |||||||
| C96E | EX DE,HL | (get vischar.flags pointer in HL) | ||||||
| C96F | INC L | Set vischar.route.index to routeindex_255_WANDER ($FF) | ||||||
| C970 | LD (HL),$FF | |||||||
| C972 | INC L | Set vischar.route.step to zero -- wander from 0..7 | ||||||
| C973 | LD (HL),$00 | |||||||
| C975 | POP HL | Restore vischar.flags pointer | ||||||
| C976 | JP get_target_assign_pos | Exit via get_target_assign_pos | ||||||
|
Check for mode 4 ("saw bribe")
|
||||||||
| cb_saw_bribe_check | C979 | CP $04 | Is the mode vischar_PURSUIT_SAW_BRIBE? | |||||
| C97B | JR NZ,cb_check_halt | Jump if not | ||||||
|
Mode 4: Hostile character witnessed a bribe being given (in accept_bribe).
|
||||||||
| C97D | PUSH HL | Preserve vischar.flags pointer | ||||||
| C97E | LD A,($AF8E) | Get the global bribed character | ||||||
| C981 | CP $FF | Is it character_NONE? ($FF) | ||||||
| C983 | JR Z,cb_bribe_not_found | Jump if so | ||||||
| C985 | LD C,A | Copy the bribed character to C | ||||||
|
Iterate over non-player characters.
|
||||||||
| C986 | LD B,$07 | Set B for seven iterations | ||||||
| C988 | LD HL,$8020 | Point HL at the second visible character | ||||||
|
Start loop
|
||||||||
| cb_bribe_loop | C98B | LD A,C | Copy bribed character to A | |||||
| C98C | CP (HL) | Is this vischar the bribed character? | ||||||
| C98D | JR Z,cb_bribed_visible | Jump if so | ||||||
| C98F | LD A,$20 | Step HL to the next vischar | ||||||
| C991 | ADD A,L | |||||||
| C992 | LD L,A | |||||||
| C993 | DJNZ cb_bribe_loop | ...loop | ||||||
| cb_bribe_not_found | C995 | POP HL | Restore vischar.flags pointer | |||||
|
Bribed character was not visible: hostiles lose interest and resume following their original route.
|
||||||||
| C996 | LD (HL),$00 | Clear vischar.flags | ||||||
| C998 | INC L | |||||||
| C999 | JP get_target_assign_pos | Exit via get_target_assign_pos | ||||||
|
Found the bribed character in vischars: hostiles target him.
|
||||||||
| cb_bribed_visible | C99C | LD A,$0F | Advance HL to vischar.mi.pos | |||||
| C99E | ADD A,L | |||||||
| C99F | LD L,A | |||||||
| C9A0 | POP DE | Get the vischar pointer | ||||||
| C9A1 | PUSH DE | |||||||
| C9A2 | LD A,E | Point DE at vischar.target | ||||||
| C9A3 | ADD A,$03 | |||||||
| C9A5 | LD E,A | |||||||
| C9A6 | LD A,($68A0) | Get the global current room index | ||||||
| C9A9 | AND A | Is it zero? | ||||||
| C9AA | JP NZ,cb_bribed_indoors | Jump if not | ||||||
|
Outdoors
|
||||||||
| C9AD | CALL pos_to_tinypos | Scale down the bribed character's position to this vischar's target field | ||||||
| C9B0 | JR cb_bribed_done | (else) | ||||||
|
Indoors
|
||||||||
| cb_bribed_indoors | C9B2 | LDI | Scale down the bribed character's position to this vischar's target field | |||||
| C9B4 | INC L | |||||||
| C9B5 | LDI | |||||||
| cb_bribed_done | C9B7 | POP HL | Restore the vischar pointer | |||||
| C9B8 | JR cb_move | Jump to 'move' | ||||||
| cb_check_halt | C9BA | INC L | Advance HL to vischar.route.index | |||||
| C9BB | LD A,(HL) | Fetch it | ||||||
| C9BC | DEC L | Step back | ||||||
| C9BD | AND A | Is it routeindex_0_HALT? ($00) | ||||||
| C9BE | JR Z,cb_set_input | Jump if so (set input) | ||||||
| cb_move | C9C0 | LD A,(HL) | Get vischar.flags | |||||
| C9C1 | EXX | Bank | ||||||
| C9C2 | LD C,A | C = flags | ||||||
|
Select a scaling routine.
|
||||||||
| C9C3 | LD A,($68A0) | Get the global current room index | ||||||
| C9C6 | AND A | Is it outdoors? (zero) | ||||||
| C9C7 | JR Z,cb_scaling_door | Jump if so | ||||||
| cb_scaling_indoors | C9C9 | LD HL,$CB75 | Point HL at multiply_by_1 | |||||
| C9CC | JR cb_self_modify | (else) | ||||||
| cb_scaling_door | C9CE | BIT 6,C | Is vischar.flags vischar_FLAGS_TARGET_IS_DOOR set? | |||||
| C9D0 | JR Z,cb_scaling_outdoors | Jump if not | ||||||
| C9D2 | LD HL,$B295 | Point HL at multiply_by_4 | ||||||
| C9D5 | JR cb_self_modify | (else) | ||||||
| cb_scaling_outdoors | C9D7 | LD HL,$B1C7 | Point HL at multiply_by_8 | |||||
|
Self modify vischar_move_x/y routines.
|
||||||||
| cb_self_modify | C9DA | LD ($CA13),HL | Self-modify vischar_move_x | |||||
| C9DD | LD ($CA4B),HL | Self-modify vischar_move_y | ||||||
| C9E0 | EXX | Unbank | ||||||
|
If the vischar_BYTE7_Y_DOMINANT flag is set then cb_move_y_dominant is used instead of the code below, which is x dominant. i.e. It means "try moving y then x, rather than x then y". This is the code which makes characters alternate left/right when navigating.
|
||||||||
| C9E1 | BIT 5,(IY+$07) | Does the vischar's counter_and_flags field have flag vischar_BYTE7_Y_DOMINANT set? ($20) | ||||||
| C9E5 | JR NZ,cb_move_y_dominant | Jump if so | ||||||
| cb_move_x_dominant | C9E7 | INC L | Advance HL to vischar.position.x | |||||
| C9E8 | INC L | |||||||
| C9E9 | INC L | |||||||
| C9EA | CALL vischar_move_x | Call vischar_move_x | ||||||
| C9ED | JR NZ,cb_set_input | If it couldn't move call vischar_move_y | ||||||
| C9EF | CALL vischar_move_y | |||||||
| C9F2 | JP Z,target_reached | If it still couldn't move exit via target_reached | ||||||
|
This entry point is used by the routine at target_reached.
|
||||||||
| cb_set_input | C9F5 | CP (IY+$0D) | Is our new input different from the vischar's existing input? | |||||
| C9F8 | RET Z | Return if not | ||||||
| C9F9 | OR $80 | Otherwise set the input_KICK flag | ||||||
| C9FB | LD (IY+$0D),A | |||||||
| C9FE | RET | Return | ||||||
| cb_move_y_dominant | C9FF | LD A,$04 | Advance HL to vischar.position.y | |||||
| CA01 | ADD A,L | |||||||
| CA02 | LD L,A | |||||||
| CA03 | CALL vischar_move_y | Call vischar_move_y | ||||||
| CA06 | JR NZ,cb_set_input | If it couldn't move call vischar_move_x | ||||||
| CA08 | CALL vischar_move_x | |||||||
| CA0B | JR NZ,cb_set_input | If it could move, jump to cb_set_input | ||||||
| CA0D | DEC L | Rewind HL to vischar.position.x | ||||||
| CA0E | JP target_reached | Exit via target_reached | ||||||
| Prev: C892 | Up: Map | Next: CA11 |