Prev: C47E Up: Map Next: C5D3
C4E0: Spawn character
This adds a character to the visible character (vischar) list.
Used by the routine at spawn_characters.
Input
HL Pointer to character to spawn.
spawn_character C4E0 BIT 6,(HL) Is the character already on-screen? (test flag characterstruct_FLAG_ON_SCREEN)
C4E2 RET NZ Return if so
C4E3 PUSH HL Preserve the character pointer
Find an empty slot in the visible character list.
Iterate over non-player characters.
C4E4 LD HL,$8020 Point HL at the second visible character
C4E7 LD DE,$0020 Prepare the vischar stride
C4EA LD A,$FF Prepare vischar_CHARACTER_EMPTY_SLOT
C4EC LD B,$07 Set B for seven iterations (seven non-player vischars)
Start loop
spawn_find_slot C4EE CP (HL) Empty slot?
C4EF JR Z,spawn_found_empty_slot Jump if so
C4F1 ADD HL,DE Advance to the next vischar
C4F2 DJNZ spawn_find_slot ...loop
spawn_no_spare_slot C4F4 POP HL Restore the character pointer
C4F5 RET Return (Z set)
Found an empty slot.
spawn_found_empty_slot C4F6 POP DE Restore the character pointer to DE
C4F7 PUSH HL Point IY at the empty vischar slot
C4F8 POP IY
C4FA PUSH HL Preserve the empty vischar slot pointer
C4FB PUSH DE Preserve the character pointer
C4FC INC DE Advance DE to point at charstr.room
Scale coords dependent on which room the character is in.
C4FD LD HL,$81A4 Point HL at saved_pos_x
C500 LD A,(DE) Fetch charstr.room
C501 INC DE Advance DE to charstr.pos
C502 AND A Is it outside?
C503 JR NZ,spawn_indoors Jump if not
Outdoors
C505 LD A,$03 Set A for three iterations (x,y,height)
Start loop
spawn_outdoor_pos_loop C507 EX AF,AF' Bank
C508 LD A,(DE) Read an (8-bit) coord
C509 CALL multiply_by_8 Multiply it by 8 returning the result in BC
C50C LD (HL),C Store the result widened to 16-bit
C50D INC HL
C50E LD (HL),B
C50F INC HL
C510 INC DE Advance to the next coord
C511 EX AF,AF' Unbank
C512 DEC A ...loop
C513 JP NZ,spawn_outdoor_pos_loop
C516 JR spawn_check_collide (else)
spawn_indoors C518 LD B,$03 Set B for three iterations
Start loop
spawn_indoor_pos_loop C51A LD A,(DE) Read an (8-bit) coord
C51B LD (HL),A Store the coord widened to 16-bit
C51C INC DE
C51D INC HL
C51E LD (HL),$00
C520 INC HL
C521 DJNZ spawn_indoor_pos_loop ...loop
spawn_check_collide C523 CALL collision Call collision
C526 CALL Z,bounds_check If no collision, call bounds_check
C529 POP DE Restore the character pointer
C52A POP HL Restore the empty vischar slot pointer
C52B RET NZ Return if collision or bounds_check returned non-zero
Transfer character struct to vischar.
C52C LD A,(DE) Set characterstruct_FLAG_ON_SCREEN in charstr.character_and_flags
C52D OR $40
C52F LD (DE),A
C530 AND $1F Mask A against characterstruct_CHARACTER_MASK ($1F) and store that as vischar.character
C532 LD (HL),A
C533 INC L
C534 LD (HL),$00 Clear the vischar.flags
C536 PUSH DE Preserve the charstr.character_and_flags pointer
C537 LD DE,$CD9A Point DE at the character_meta_data for the commandant
C53A AND A Is it character_0_COMMANDANT?
C53B JR Z,spawn_metadata_set Jump if so
C53D LD DE,$CD9E Point DE at the character_meta_data for a guard
C540 CP $10 Is it character_1_GUARD_1 to character_15_GUARD_15?
C542 JR C,spawn_metadata_set Jump if so
C544 LD DE,$CDA2 Point DE at the character_meta_data for a dog
C547 CP $14 Is it character_16_GUARD_DOG_1 to character_19_GUARD_DOG_4?
C549 JR C,spawn_metadata_set Jump if so
C54B LD DE,$CDA6 Point DE at the character_meta_data for a prisoner
spawn_metadata_set C54E EX DE,HL Swap vischar into DE, metadata into HL
C54F LD A,$07 Point DE at vischar.animbase
C551 ADD A,E
C552 LD E,A
C553 LDI Copy metadata.animbase to vischar.animbase
C555 LDI
C557 LD A,$0B Point DE at vischar.mi.sprite
C559 ADD A,E
C55A LD E,A
C55B LDI Copy metadata.sprite to vischar.mi.sprite
C55D LDI
C55F LD A,E Rewind DE to vischar.mi.pos
C560 SUB $08
C562 LD E,A
C563 LD HL,$81A4 Copy saved_pos to vischar.mi.pos
C566 LD BC,$0006
C569 LDIR
C56B POP HL Restore the HL charstr.character_and_flags pointer
C56C INC HL Advance HL to charstr.route
C56D INC HL
C56E INC HL
C56F INC HL
C570 INC HL
C571 LD A,$07 Point DE at vischar.room
C573 ADD A,E
C574 LD E,A
C575 LD A,($68A0) Set vischar.room to the global current room index
C578 LD (DE),A
C579 AND A Are we outside?
C57A JR Z,spawn_entered Jump if so
spawn_indoors_sound C57C LD BC,$2040 Play the "character enters" sound effects
C57F CALL play_speaker
C582 LD BC,$2030
C585 CALL play_speaker
spawn_entered C588 LD A,E Rewind DE to vischar.route
C589 SUB $1A
C58B LD E,A
C58C LDI vischar.route = charstr.route
C58E LDI
C590 DEC HL Rewind HL to charstr.route
C591 DEC HL
This can get entered twice via C5B4. On the first entry HL points at charstr.route.index. On the second entry HL points at vischar.route.index.
spawn_again C592 LD A,(HL) Load route.index
C593 AND A Is this character stood still? (routeindex_0_HALT)
C594 JR NZ,spawn_moving Jump if not
C596 LD A,$03 Advance DE to vischar.counter_and_flags
C598 ADD A,E
C599 LD E,A
C59A JR spawn_end (else)
spawn_moving C59C XOR A Clear the entered_move_a_character flag
C59D LD ($A13E),A
C5A0 PUSH DE Preserve the vischar.target pointer
C5A1 CALL get_target Get our next target: a location, a door or 'route ends'. The result is returned in A, target pointer returned in HL
C5A4 CP $FF Did get_target return get_target_ROUTE_ENDS? ($FF)
C5A6 JR NZ,spawn_route_door_test Jump if not
spawn_route_ends C5A8 POP HL Restore the vischar.target pointer
C5A9 DEC L Rewind HL to vischar.route
C5AA DEC L
C5AB PUSH HL Preserve the vischar.route pointer
C5AC CALL route_ended Route ended
C5AF POP HL Restore the vischar.route pointer
C5B0 LD D,H Point DE at vischar.target
C5B1 LD E,L
C5B2 INC E
C5B3 INC E
C5B4 JR spawn_again Jump back and try again...
spawn_route_door_test C5B6 CP $80 Did get_target return get_target_DOOR? ($80)
C5B8 JR NZ,spawn_got_target Jump if not (it must be get_target_LOCATION)
spawn_route_door C5BA SET 6,(IY+$01) Set the vischar_FLAGS_TARGET_IS_DOOR flag
spawn_got_target C5BE POP DE Restore the vischar.target pointer
C5BF LD BC,$0003 Copy the next target to vichar.target
C5C2 LDIR
spawn_end C5C4 XOR A Clear vischar.counter_and_flags
C5C5 LD (DE),A
C5C6 LD A,E Rewind DE back to vischar.character (first byte)
C5C7 SUB $07
C5C9 LD E,A
C5CA EX DE,HL Swap vischar pointer into HL
C5CB PUSH HL Preserve vischar pointer
C5CC CALL calc_vischar_iso_pos_from_vischar Calculate screen position for the specified vischar
C5CF POP HL Restore vischar pointer
C5D0 JP character_behaviour Exit via character_behaviour
Prev: C47E Up: Map Next: C5D3