tkeyangle=$-5
;LRDU
;DB -1 ;0000
;DB 128;0001
;DB 0 ;0010
;DB -1 ;0011
;DB 64 ;0100
DB 96 ;0101
DB 32 ;0110
DB 64 ;0111
DB 192;1000
DB 160;1001
DB 224;1010
DB 192;1011
DB -1 ;1100
DB 128;1101
DB 0 ;1110
DB -1 ;1111
tkeyangleend
;в 0x4000 включена pgmap
CONTROL
LD HL,(IMcurXx+1)
LD a,(IMcurYy+1)
ld h,a
;корректировать адрес стены в зависимости от направления
ld a,(IMavision+1)
sub 32
cp 64
jr nc,$+3
inc h
bit 6,a
jr z,$+4
SET mapdifbit,L
cp -64
jr c,$+3
inc l
ld (touchedwalladdr),hl
ld a,0xf7
in a,(0xfe)
and 0x1f
oldeditkeys=$+1
ld c,0
ld (oldeditkeys),a
cp c
jr z,noedit
ld c,a
bit 0,c
jr nz,noedit1
ld a,(hl)
or a
ld (hl),0xc0
jr z,edit1q
set 6,a
add a,2
cp 0xc0+(2*12)
jr c,$+4
ld a,0xc0
xor (hl)
and 0x3f
xor (hl)
ld (hl),a
edit1q
noedit1
bit 1,c
jr nz,noedit2
ld a,(hl)
or a
ld (hl),0xc0
jr z,edit2q
set 6,a
sub 2
cp 0xc0
jr nc,$+4
ld a,0xc0+(2*11)
xor (hl)
and 0x3f
xor (hl)
ld (hl),a
edit2q
noedit2
bit 2,c
jr nz,noedit3
ld a,(hl)
xor 1 ;mirror
ld (hl),a
noedit3
bit 3,c
jr nz,noedit4
ld (hl),0
noedit4
bit 4,c
jr nz,noedit5
ld a,(hl)
or a
jr z,noedit5
xor 64 ;page
ld (hl),a
noedit5
noedit
;режимы двери:
;0: дверь закрыта
;1: дверь открывается, doortimer увеличивается
;2: дверь открыта, dooropentimer уменьшается
;3: дверь закрывается, doortimer уменьшается
doortimer=$+1
ld a,0
doortimermode=$+1
ld b,0
djnz control_door_noopening
add a,2
ld (doortimer),a
jr nz,control_doorq
dec a ;-1
ld (doortimer),a ;stay opened
ld a,50 ;a=door open time
ld (dooropentimer),a
ld a,2
ld (doortimermode),a
jr control_doorq
control_door_noopening
djnz control_door_noopened
dooropentimer=$+1
ld a,0
dec a
ld (dooropentimer),a
jr nz,control_doorq
;call closecurrentdoor ;keeps hl
ld a,-2
ld (doortimer),a ;stay opened
ld a,3
ld (doortimermode),a
jr control_doorq
control_door_noopened
djnz control_door_noclosing
;если игрок стоит в дверях, то не закрываем, а открываем
LD HL,(IMcurXx+1)
LD a,(IMcurYy+1)
ld h,a
ld a,ID_DOOR
cp (hl)
jr z,control_door_setopened
inc h
cp (hl)
jr z,control_door_setopened
dec h
set mapdifbit,l
cp (hl)
jr z,control_door_setopened
inc l
cp (hl)
jr z,control_door_setopened
ld a,(doortimer)
sub 2
ld (doortimer),a
jr nz,control_doorq
;xor a
ld (doortimermode),a
call closecurrentdoor ;keeps hl
jr control_doorq
control_door_setopened
ld a,1
ld (doortimermode),a
control_door_noclosing
control_doorq
IF kempston
LD C,#FF
IN A,(#1F)
LD B,A
AND #E0
jr NZ,nKEMPSTON
LD A,B
RRA
jr NC,$+4
RES 1,C
RRA
jr NC,$+4
RES 0,C
RRA
jr NC,$+4
RES 3,C
RRA
jr NC,$+4
RES 2,C
RRA
jr NC,$+4
RES 6,C
nKEMPSTON
;C=%1f11durl
ENDIF
IF autostrafe
BIT 3,C ;down
jr NZ,nAUTOSTRAFE
LD A,C
BIT 1,A
jr NZ,$+6
AND %01101111 ;strafe + rotate flag
OR %00001011 ;block down & rotate
BIT 0,A
jr NZ,$+6
AND %01011111 ;strafe + rotate flag
OR %00001011 ;block down & rotate
LD C,A
nAUTOSTRAFE
ENDIF
LD B,#FF
ld a,#fe
in a,(#fe)
rra
rl b ;cs (open)
LD A,#7F
IN A,(#FE)
RRA
RL B ;space (fire)
LD A,#FD
IN A,(#FE)
RRA
RL B ;A
RRA
RRA
RL B ;D
RLA
RL B ;S (down)
LD A,#FB
IN A,(#FE)
RRA
RRA
RL B ;W (up)
LD A,#DF
IN A,(#FE)
RRA
RL B ;P (right)
RRA
LD A,B
RLA ;O (left)
IF kempston
AND C
ENDIF
;A=%ofADdurl
IF demoplay
demoplayoff=$
OR A
jr C,demoplayQ
BIT 4,A ;"D"
jr NZ,demoplaynOFF
LD A,#37 ;scf
LD (demoplayoff),A
LD A,#91 ;sub c
LD (mouseon),A
LD A,#FF
demoplaynOFF
democursor=$+1
LD HL,demobegin
demokey=$+1
LD A,%00111111
demokeytime=$+1
LD C,1
DEC C
jr NZ,CnNEWKEY
LD A,(HL)
LD (demokey),A
INC HL
LD C,(HL)
INC HL
LD (democursor),HL
CnNEWKEY
LD HL,demokeytime
LD (HL),C
demoplayQ
ELSE
IF demorec
democursor=$+1
LD HL,demobegin
demokeytime=$+1
LD C,0
INC C
jr Z,CNEWKEY
CP (HL)
jr Z,CnNEWKEY
CNEWKEY
INC HL
LD (HL),C
LD C,0
INC HL
CnNEWKEY
LD (HL),A
LD (democursor),HL
LD HL,demokeytime
LD (HL),C
ENDIF
ENDIF
;a=%ofADdurl
PUSH AF
bit 7,a
jr nz,noopendoor
;call closecurrentdoor ;keeps hl
;LD HL,(IMcurXx+1)
;LD a,(IMcurYy+1)
;ld h,a
touchedwalladdr=$+1
ld hl,0
ld c,ID_DOOR*2
ld a,(hl)
add a,a
cp c
jr nz,noopendoor
bit mapdifbit,l
jr z,opendoor_h
opendoor_l
push hl
res 7,(hl)
inc l
ld a,(hl)
add a,a
cp c
jr z,opendoorok
dec l
dec l
;ld a,(hl)
;add a,a
;cp c
jr opendoorok
opendoor_h
push hl
res 7,(hl)
inc h
ld a,(hl)
add a,a
cp c
jr z,opendoorok
dec h
dec h
;ld a,(hl)
;add a,a
;cp c
opendoorok
res 7,(hl)
;ничего не делать, если hl==(oldopendooraddr2)
ld de,(oldopendooraddr2)
or a
sbc hl,de
add hl,de
pop de
jr z,noopendoor
call closecurrentdoor ;keeps hl,de
ld (oldopendooraddr2),hl
ld (oldopendooraddr),de
xor a
ld (doortimer),a
inc a
ld (doortimermode),a
ld a,5 ;open sfx
call sfxplay
noopendoor
;сколько фреймов прошло с прошлого fire? считать независимо от fire!
ld a,(firedelaycounter)
dec a
;jp m,fire_timeok
;ld (firedelaycounter),a
jp p,firedelaycounter_popnofire
;fire_timeok
pop af
;a=%ofADdurl
bit 6,a
jp nz,nofire
push af
ld a,(bullets)
or a
jp z,popnofire
dec a
ld (bullets),a
push hl
ld a,1 ;shot sfx
call sfxplay
pop hl
if sprites
call RAYPREPXY
LD A,SCRWIDPIX/2;0x40;TODO связано с scrwid/2
ld l,a
LD (cura),A
CALL RAYCAST
;C=dist(scale#)
;B=texx
ld a,c
ld (fire_walldist),a
if 1==0
call getuser_scr_high_cur
SETPG8000
ld a,(fire_walldist)
ld hl,0x8000
ld bc,40
dup 8
ld (hl),7
rla
rr (hl)
add hl,bc
edup
endif
call SCANMONS
;в cursprites лежат данные о видимых спрайтах (от задних к передним)
;ID 8 (0=end)
;dist 16
;xscr 8
;monster index
ld hl,cursprites
fire_scan0
ld a,(hl)
or a
jp z,fire_scan0q
inc l
ld c,(hl)
inc l
ld b,(hl) ;bc=dist
ld d,b
ld e,c
inc l
dup 3;4
srl d
rr e
edup
ld a,d
or a
jr z,$+4
ld e,255
or e
jr nz,$+3
inc e
ld d,t1x/256
ld a,(de) ;width*k (for typical sprite width)
ld e,a
ld a,(hl) ;xscr (центр = 0x40)
sub e
jr nc,$+3
xor a ;a=sprite left margin
cp SCRWIDPIX/2;0x40;TODO связано с scrwid/2
jr nc,fire_miss
ld a,(hl) ;xscr
add a,e
jr nc,$+3
sbc a,a ;a=sprite right margin
cp SCRWIDPIX/2;0x40;TODO связано с scrwid/2
jr c,fire_miss
push hl
;не убивать, если стена впереди закрывает монстра (т.е. стена ближе)
;bc=dist
;приводим к 128..255
LD DE,#000
INC B
DEC B
LD A,C
jr Z,fire_MOTOLOGRLQ
DUP 5;6
INC D
SRL B
RRA
jr Z,fire_MOTOLOGRLE
EDUP
fire_MOTOLOGRLQ ;
fire_MOTOLOGRLE ;
LD C,A ;128..255 ;D=0..5
LD B,tlogd/256
LD A,(BC) ;log(dist) = 128..255 for arg>=128
if atm==0
SUB 16;64 ;0..127 for arg=64..127 ;???
endif
LD C,A ;0 for arg<64
LD B,tlogd2sca/256
SRA D
RR E ;DE=+0,+#80,..+#300
ex de,hl
ADD HL,BC
LD a,(HL) ;scale#
pop hl
fire_walldist=$+1
cp 0
jr c,fire_miss
push hl
;найти этого монстра в таблице монстров
inc l
ld l,(hl) ;monster index
ld h,0
add hl,hl
add hl,hl
add hl,hl ;*8
ld bc,MONSTRS+5 ;Xx,Yy,TYPEphase_dir,TIMEenergy
add hl,bc ;TYPEphase
ld a,(hl)
cp 4*8
jr nc,fire_skip ;not a monster
and 7
cp 6
jr z,fire_skip ;dead monster
dec l
ld (hl),0 ;dir = no move
inc l
ld (hl),3*8+4 ;wounded, go
inc l
ld a,(hl) ;energy
sub 20
ld (hl),a ;energy
jr c,fire_kill
inc l
ld (hl),TIME_WOUNDED ;time
ld a,2 ;wound sfx
jr fire_killq
fire_kill
dec l
ld (hl),3*8+6 ;dead
;ld a,l
;and 0xf8
;ld l,a
;inc l ;X
;ld (hl),0xc0 ;impossible X
ld a,0 ;kill sfx
fire_killq
call sfxplay
fire_skip
pop hl
fire_miss
if CURSPRITES_RECSZ == 5
inc l
endif
inc l
jp fire_scan0
fire_scan0q
endif
ld a,10
firedelaycounter_popnofire
ld (firedelaycounter),a
popnofire
pop af
nofire
push af
IMavision=$+1
LD HL,32*256
IMdavision=$+1
LD DE,100
AND %10110011
CP 0
LD ($-1),A
jr Z,$+4
LD E,50 ;key just pressed/released
IF kempston&autostrafe
BIT 7,A
jr NZ,nAUTOROTATE
BIT 4,A
jr NZ,$+3
ADD HL,DE
BIT 5,A
jr NZ,$+4
SBC HL,DE
nAUTOROTATE
ENDIF
IF doublerotate
RRA
jr C,$+4
ADD HL,DE
ADD HL,DE
RRA
jr C,$+6
SBC HL,DE
SBC HL,DE
ELSE
RRA
jr C,$+3
ADD HL,DE
RRA
jr C,$+4
SBC HL,DE
ENDIF
LD A,E
ADD A,12;10
jr C,$+3
LD E,A ;key held: increase rotspd
LD (IMdavision),DE
IF mouse
LD BC,#FBDF
IN A,(C)
mouseoldx=$+1
LD C,0
LD ($-1),A
mouseon=$
IF demoplay
XOR A
ELSE
SUB C
ENDIF
NEG
LD E,A
RLA
SBC A,A
LD D,A
ex de,hl
DUP 6
ADD HL,HL
EDUP
ADD HL,DE
ENDIF
LD (IMavision),HL
;делим вектор на коэфф замедления
IMcurDX=$+1
LD HL,0
LD B,H
ld A,L
SRA B
RRA
IF doublespeed
SRA B
RRA
ENDIF
LD C,A
CP B
jr NZ,$+3
LD C,L
SBC HL,BC
LD B,H
ld C,L
CSLOWXQ
IMcurDY=$+1
LD HL,0
LD D,H
ld A,L
SRA D
RRA
IF doublespeed
SRA D
RRA
ENDIF
LD E,A
CP D
jr NZ,$+3
LD E,L
SBC HL,DE
LD D,H
ld E,L
CSLOWYQ
POP AF ;%00ADSWPO
RRCA
RRCA
AND 15
LD HL,tkeyangle
ADD A,L
LD L,A
IF (tkeyangle^tkeyangleend)&256
ADC A,H
SUB L
LD H,A
ENDIF
LD A,(HL)
;прибавляем вектор направления
;sin и cos (IMavision+32*N), где N=0..7 в зав. от клавиш
;0=forth
;64=left
CP -1
JP Z,CTRLnspeed
LD HL,IMavision+1
ADD A,(HL)
LD L,A
LD H,tcos/256 ;-pi/4..+pi/4
LD A,(HL)
ADD A,C
LD C,A
BIT 7,(HL)
jr NZ,$+3
INC B
jr C,$+3
DEC B
LD A,64
SUB L
LD L,A
LD A,(HL)
ADD A,E
LD E,A
BIT 7,(HL)
jr NZ,$+3
INC D
jr C,$+3
DEC D
CTRLnspeed
LD (IMcurDX),BC
LD (IMcurDY),DE
DUP 2
SRA D
RR E
SRA B
RR C
EDUP
ld b,e
LD HL,(IMcurXx)
LD de,(IMcurYy)
;hl=x
;de=y
;c=dx/4
;b=dy/4
call moveandcollideX
ex de,hl
call moveandcollideY
;hl=y
;de=x
LD (IMcurYy),HL
LD (IMcurXx),de
call collideobjects
call movemonsters
ret
collideobjects
;collide with objects
;все объекты - в центре своей клетки
LD HL,MONSTRS+1 ;1+начало табл.монстров/предметов
ld hx,-1 ;monster index
jp logCOLLIDE0 ;цикл скан-я видимых монстров/предметов
logCOLLIDENx
LD A,L
ADD A,8
LD L,A
JR C,logCOLLIDExIH
logCOLLIDE0
inc hx ;monster index
LD A,(HL) ;X
INC A
RET Z
ld a,(IMcurXx+1)
cp (hl)
jr nz,logCOLLIDENx
inc l
inc l
ld a,(IMcurYy+1)
cp (hl)
jr z,logCOLLIDEY
LD A,L
ADD A,6
LD L,A
JP NC,logCOLLIDE0
logCOLLIDExIH
INC H
JP logCOLLIDE0
logCOLLIDEY
inc l
;ld a,(hl) ;dir
inc l
ld a,(hl) ;TYPE*8+phase
cp 4*8
jr c,logCOLLIDEnobj
push hl
;ld a,l
;and 0xf8
;ld l,a
;inc l ;X
res 1,l
res 2,l
ld (hl),0xc0 ;impossible X
cp 4*8
jr nz,logCOLLIDEnammo
ld hl,bullets
ld bc,40*256+50 ;ADDmax
call addmax
logCOLLIDEnammo
cp 5*8
jr nz,logCOLLIDEnhealth
ld hl,health
ld bc,40*256+100 ;ADDmax
call addmax
logCOLLIDEnhealth
ld a,3 ;get obj
call sfxplay
pop hl
logCOLLIDEnobj
inc l
;ld a,(hl) ;energy
inc l
;ld a,(hl) ;time
inc hl
INC L ;skip x
jp logCOLLIDE0
movemonsters
;move monsters
LD A,(IMcurXx+1);d;(curX)
SUB viewrange
LD (logscmonX),A
LD A,(IMcurYy+1);h;(curY)
SUB viewrange
LD (logscmonY),A
LD HL,MONSTRS+1 ;1+начало табл.монстров/предметов
ld hx,-1 ;monster index
jp logSCMONS0 ;цикл скан-я видимых монстров/предметов
logSCMONNx
LD A,L
ADD A,8
LD L,A
JR C,logSCMxIH
logSCMONS0
inc hx ;monster index
LD A,(HL) ;X
INC A
RET Z
logscmonX=$+1
SUB 0
CP viewrange*2+1
JP NC,logSCMONNx
INC L
inc L
LD A,(HL)
logscmonY=$+1
SUB 0
CP viewrange*2+1
JR C,logSCMONY
LD A,L
ADD A,6
LD L,A
JP NC,logSCMONS0
logSCMxIH
INC H
JP logSCMONS0
logSCMONY
DEC L
dec L
dec L
push hl
LD C,(HL)
INC L
LD B,(HL) ;Xx
INC L
LD E,(HL)
INC L
LD D,(HL) ;Yy
INC L
ld a,(hl) ;dir
or a
jr z,logSCMONS_nomove
push af ;dir
push bc ;x
ld l,a
LD H,tcos/256 ;-pi/4..+pi/4
LD c,(HL)
LD A,64
SUB L
LD L,A
LD b,(HL)
pop hl ;x
dup 3
sra b
sra c
edup
;hl=x
;de=y
;c=dx/4
;b=dy/4
call moveandcollideX
ex de,hl
call nc,moveandcollideY
;hl=y
;de=x
pop bc ;b=dir
ld a,b
jr nc,movemons_nochagedir
ld a,r
add a,a
inc a
movemons_nochagedir
ld b,d
ld c,e ;x
ex de,hl ;y
logSCMONS_nomove
pop hl
ld (hl),c
inc l
ld (hl),b ;Xx
inc l
ld (hl),e
inc l
ld (hl),d ;Yy
inc l
ld (hl),a ;dir
inc l ;skip dir
if 1
ld a,0xfe
in a,(0xfe)
rra
jr c,logSCMONS_noattack
;если (1..3)*8+(0..1) и близко, то wantattack:
ld a,(hl) ;TYPE*8+phase
and (30*8)+6
cp 0*8+0 ;стоит спиной
ld e,MONSTERBACKviewrange
jr z,logSCMONS_startattack
cp 2*8+0 ;стоит лицом или идёт
ld e,MONSTERviewrange
jr nz,logSCMONS_noattack
logSCMONS_startattack
ld a,(IMcurYy+1)
sub d ;Y
jr nc,$+4
neg
cp e;MONSTERviewrange
jr nc,logSCMONS_noattack
ld a,(IMcurXx+1)
sub b ;X
jr nc,$+4
neg
cp e;MONSTERviewrange
jr nc,logSCMONS_noattack
ld (hl),3*8+2 ;wantattack
inc l
inc l
ld (hl),TIME_WANTATTACK
dec l
dec l
logSCMONS_noattack
endif
ld c,(hl) ;TYPE*8+phase
INC L ;skip TYPE*8+phase
inc L ;skip energy
dec (hl) ;time
jr nz,logSCMONS_notime
ld (hl),TIME_STEP ;time
dec l
dec l ;hl points to TYPE*8+phase
ld a,c
and 7
jr z,logSCMONS_step
dec a
jr z,logSCMONS_step
dec a
jr z,logSCMONS_wantattack
dec a ;attack
jr z,logSCMONS_attack
dec a
jr z,logSCMONS_wounded
jr logSCMONS_nosetphase
logSCMONS_wantattack
inc l
inc l
ld (hl),TIME_ATTACK
dec l
dec l
dec l
ld (hl),0 ;dir (no move)
inc l
ld a,3*8+3 ;moving attack
jr logSCMONS_setphase
logSCMONS_attack
;todo shot
;дальше продолжаем движение
logSCMONS_wounded
ld a,r
add a,a ;dir
dec l
ld (hl),a ;dir
inc l
ld a,3*8+0 ;moving
jr logSCMONS_setphase
logSCMONS_step
ld a,c
xor 1
logSCMONS_setphase
ld (hl),a
logSCMONS_nosetphase
inc l
inc l
logSCMONS_notime
inc hl ;skip TIME
INC L ;skip x
jp logSCMONS0
moveandcollideX
;hl=x
;de=y
;c=dx/4
;b=dy/4
;ADD HL,BC
PUSH HL
;|..............|
;.....<---*--->..
;or a:sbc hl,bc;LD HL,(IMcurXx)
ld a,l
sub mindist ;dx<0
;dec h
BIT 7,c;B
jr nz,$+6
ld a,l
add a,mindist ;dx>0
inc h
jr nc,CTRLXpass ;проходимо (CY=0)
;LD A,H
;LD HL,(IMcurYy)
;LD L,A
ld l,h
ld h,d ;Y
SET mapdifbit,L
LD A,(HL)
RLA ;проходимо?
CTRLXpass
POP HL
jr nc,CTRLnXq ;проходимо (CY=0)
CTRLnX
;непроходимо
;LD HL,(IMcurXx)
BIT 7,c;B
LD l,256-mindist ;dx>0
ret z ;C
LD l,mindist ;dx<0
ret ;C
CTRLnXq
;add hl,bc
ld a,c
add a,l
ld l,a
adc a,h
sub l
ld h,a
or a ;NC
bit 7,c
ret z ;NC
dec h
ret ;NC
moveandcollideY
;hl=y
;b=dy/4
;ADD HL,DE
PUSH HL
;or a:sbc hl,de;LD HL,(IMcurYy)
ld a,l
sub mindist ;dx<0
;dec h
BIT 7,b;D
jr nz,$+6
ld a,l
add a,mindist ;dx>0
inc h
jr nc,CTRLYpass ;проходимо (CY=0)
;LD A,H
;LD HL,(IMcurXx)
;LD L,H
;LD H,A
ld l,d ;X
LD A,(HL)
RLA ;проходимо?
CTRLYpass
POP HL
jr nc,CTRLnYq ;проходимо (CY=0)
;непроходимо
;LD HL,(IMcurYy)
BIT 7,b;d
LD l,256-mindist ;dy>0
ret z ;C
LD l,mindist ;dy<0
ret ;C
CTRLnYq
;add hl,de
ld a,b
add a,l
ld l,a
adc a,h
sub l
ld h,a
or a ;NC
bit 7,b
ret z ;NC
dec h
RET ;NC
closecurrentdoor
;keeps hl,de
ld a,128+ID_DOOR;(hl)
oldopendooraddr=$+1
ld (killablebyte),a
oldopendooraddr2=$+1
ld (killablebyte),a
ld bc,killablebyte
ld (oldopendooraddr),bc
ld (oldopendooraddr2),bc
ret
killablebyte
db 0
addmax
ld a,(hl)
cp c;100
ret nc
add a,40
ld (hl),a
cp c;100
ret c
ld (hl),c;100
ret