dos33fsprogs/games/tfv/tfv_battle_enemy.s
2021-01-20 16:36:26 -05:00

426 lines
6.7 KiB
ArmAsm

; Environment: grass, beach, forest, ice
; Enemies: HP ATTACK WEAKNESS RESIST
; Killer Crab RND-32 PINCH MALAISE FIRE
; Plain Fish BUBBLE FIRE ICE
; Evil Tree RND-16 LEAVE FIRE ICE
; Wood Elf SING MALAISE BOLT
; Giant Bee RND-64 BUZZSAW ICE NONE
; Procrastinon RND-32 PUTOFF NONE MALAISE
; Ice Fish RND-32 AUGER FIRE ICE
; EvilPenguin WADDLE FIRE ICE
; Battle.
; Forest? Grassland? Artic? Ocean?
; ATTACK REST
; MAGIC LIMIT
; SUMMON RUN
;
; SUMMONS -> METROCAT VORTEXCN
; MAGIC -> HEAL FIRE
; ICE MALAISE
; BOLT
; LIMIT -> SLICE ZAP
; DROP
;
; 1 2 3
;0123456789012345678901234567890123456789|
;----------------------------------------|
; | HP LIMIT | -> FIGHT/LIMIT 21
;KILLER CRAB | DEATER 128/255 128 | ZAP 22
; | | REST 23
; | | RUN AWAY 24
;
; struct enemy_type {
; char *name;
; int hp_base,hp_mask;
; char *attack_name;
; int weakness,resist;
; unsigned char *sprite;
;};
;=============================
; Init Enemy
;=============================
init_enemy:
; select type
; random, with weight toward proper terrain
; 50% completely random, 50% terrain based?
; enemy_type=random_8()%0x7;
; enemy_hp=enemies[enemy_type].hp_base+
; (rand()&enemies[enemy_type].hp_mask);
lda #0 ; hardcode crab for now
sta ENEMY_TYPE
sta ENEMY_X
sta ENEMY_DEAD
; FIXME: lower
lda #$00 ; BCD
sta ENEMY_HP_LO
lda #$03 ; BCD
sta ENEMY_HP_HI
lda #$3 ; max HP is 100
sta ENEMY_LEVEL
lda #30
sta ENEMY_COUNT
lda #<killer_crab_sprite
sta draw_enemy_smc1+1
lda #>killer_crab_sprite
sta draw_enemy_smc2+1
rts
;static struct enemy_type enemies[9]={
; [0]= {
; .name="Killer Crab",
; .hp_base=50,
; .hp_mask=0x1f,
; .attack_name="Pinch",
; .weakness=MAGIC_MALAISE,
; .resist=MAGIC_FIRE,
; .sprite=killer_crab,
; },
; [1]= {
; .name="Plain Fish",
; .hp_base=10,
; .hp_mask=0x1f,
; .attack_name="Bubble",
; .weakness=MAGIC_FIRE,
; .resist=MAGIC_ICE,
; .sprite=plain_fish,
; },
; [2]= {
; .name="Evil Tree",
; .hp_base=10,
; .hp_mask=0x1f,
; .attack_name="Leaves",
; .weakness=MAGIC_FIRE,
; .resist=MAGIC_ICE,
; .sprite=evil_tree,
; },
; [3]= {
; .name="Wood Elf",
; .hp_base=10,
; .hp_mask=0x1f,
; .attack_name="Song",
; .weakness=MAGIC_MALAISE,
; .resist=MAGIC_BOLT|MAGIC_HEAL,
; .sprite=wood_elf,
; },
; [4]= {
; .name="Giant Bee",
; .hp_base=10,
; .hp_mask=0x1f,
; .attack_name="Buzzsaw",
; .weakness=MAGIC_ICE,
; .resist=MAGIC_NONE,
; .sprite=giant_bee,
; },
; [5]= {
; .name="Procrastinon",
; .hp_base=10,
; .hp_mask=0x1f,
; .attack_name="Putoff",
; .weakness=MAGIC_NONE,
; .resist=MAGIC_MALAISE,
; .sprite=procrastinon,
; },
; [6]= {
; .name="Ice Fish",
; .hp_base=10,
; .hp_mask=0x1f,
; .attack_name="Auger",
; .weakness=MAGIC_FIRE,
; .resist=MAGIC_ICE,
; .sprite=ice_fish,
; },
; [7]= {
; .name="Evil Penguin",
; .hp_base=10,
; .hp_mask=0x1f,
; .attack_name="Waddle",
; .weakness=MAGIC_FIRE,
; .resist=MAGIC_ICE,
; .sprite=evil_penguin,
; },
; [8]= {
; .name="Act.Principl",
; .hp_base=10,
; .hp_mask=0x1f,
; .attack_name="BIRDIE",
; .weakness=MAGIC_NONE,
; .resist=MAGIC_ICE|MAGIC_FIRE,
; .sprite=roboknee1,
; },
;};
;=========================
; damage enemy
;=========================
; amount to damage in DAMAGE_VAL_LO/HI (BCD)
damage_enemy:
; see if damage < enemy_hp, if so fine to subtract
; if not, set enemy_hp to zero
; 16 bit unsigned compare
lda DAMAGE_VAL_HI ; compare high bytes
cmp ENEMY_HP_HI
bcc damage_enemy_subtract ; if damage_hi<hp_hi then less
bne damage_enemy_too_much ; if damage_hi<>hp_hi then bigger
lda DAMAGE_VAL_LO ; compare low bytes
cmp ENEMY_HP_LO
bcc damage_enemy_subtract ; then damage_hi<hp_hi
damage_enemy_too_much:
lda #0
sta ENEMY_HP_HI
sta ENEMY_HP_LO
jmp damage_enemy_done
damage_enemy_subtract:
sed
sec
lda ENEMY_HP_LO
sbc DAMAGE_VAL_LO
sta ENEMY_HP_LO
lda ENEMY_HP_HI
sbc DAMAGE_VAL_HI
sta ENEMY_HP_HI
cld
damage_enemy_done:
rts
;===============================
; enemy attack
;===============================
enemy_attack:
lda #$10
sta DAMAGE_VAL_LO
lda #$00
sta DAMAGE_VAL_HI
lda #1
sta ENEMY_ATTACKING
enemy_attack_loop:
; put attack name onh
; occasionally attack with that enemy's power?
; occasionally heal self?
;======================
; copy over background
jsr gr_copy_to_current
; draw hero first so behind enemy
jsr draw_hero_and_sword
; draw enemy
lda ENEMY_X
sta XPOS
lda #20
sta YPOS
jsr draw_enemy
; let you finish menu commands?
lda MENU_STATE
cmp #MENU_NONE
beq enemy_no_menu
jsr get_keypress
sta LAST_KEY
jsr battle_menu_keypress
enemy_no_menu:
;============
; draw bottom
jsr draw_battle_bottom
;============
; page flip
jsr page_flip
;============
; delay a bit
lda #50
jsr WAIT
inc ENEMY_X
lda ENEMY_X
cmp #30
bcc enemy_attack_loop
enemy_done_charging:
; damage the hero
jsr damage_hero
; update limit count
; max out at 5
lda HERO_LIMIT
cmp #5
beq battle_no_inc_limit
inc HERO_LIMIT
battle_no_inc_limit:
;============================
;============================
;============================
lda #50
sta ANIMATE_LOOP
enemy_end_loop:
;======================
; copy over background
jsr gr_copy_to_current
; draw hero first so behind enemy
jsr draw_hero_and_sword
; if == 10 back to left
lda ANIMATE_LOOP
cmp #10
bne not_enemy_back
lda #0
sta ENEMY_X
lda #0
sta ENEMY_ATTACKING
not_enemy_back:
; draw enemy
lda ENEMY_X
sta XPOS
lda #20
sta YPOS
jsr draw_enemy
; let you finish menu commands?
lda MENU_STATE
cmp #MENU_NONE
beq enemy_no_menu2
jsr get_keypress
sta LAST_KEY
jsr battle_menu_keypress
enemy_no_menu2:
;============
; draw bottom
jsr draw_battle_bottom
lda ANIMATE_LOOP
cmp #10
bcc no_enemy_print_damage
; print damage
lda #25
sta XPOS
lda #10
sta YPOS
jsr gr_put_num
no_enemy_print_damage:
; flip page
jsr page_flip
dec ANIMATE_LOOP
bne enemy_end_loop
done_enemy_attack:
; done attacking
; reset enemy time. FIXME: variable?
lda #100
sta ENEMY_COUNT
rts
;================================
; draw enemy
; relies on self-modifying code
; position in XPOS,YPOS
draw_enemy:
draw_enemy_smc1:
lda #$a5
sta INL
draw_enemy_smc2:
lda #$a5
sta INH
lda ENEMY_DEAD
beq draw_enemy_alive
lda #$99
sta COLOR
jmp put_sprite_mask
draw_enemy_alive:
jmp put_sprite_crop ; tail call