        display "movefire=",$
movefire
movefire_direction_dx=$+1
        add a,8;4
        ld (hl),a
        jp p,movefire_nodestroy ;$+3+2 ;ret p
         xor a
         ld (hl),a ;destroy fire
        ld (firecollision_firexmin),a
        ld (firecollision_firexmax),a
        ret
movefire_nodestroy
        ;ld hl,(fireyx)
        ;ld a,(hl);h;(fireyx_x)
        add a,-1 -FIREXRADIUS ;3 ;для пули шириной 16 пикс
        ;ld (firecollision_firex),a
        ld (firecollision_firexmin),a
        add a,FIREXRADIUS*2+1
        ld (firecollision_firexmax),a
        ret

setidnone_procnone
        ld (ix+OBJ_Y),0 ;для монстров, убитых по падению, чтобы они не затирали панель
        ld (ix+OBJ_X),0 ;чтобы не попало на экран
setidnone_procnone_nosety
        ld (ix+OBJ_GFX),ID_NONE
        ld (ix+OBJ_PROC_ADDR),moveobj_none&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_none/256
        ret

removemonster
;выключить монстра в killedmonsterslist
;a=GFX монстра, по нему определяем ID, а по нему сколько очков дать
         sub ID_CALMAR
         srl a
         srl a ;a=тип монстра
         push bc
         ld hl,tmonsterscores
         ld c,a
         ld b,0
         add hl,bc
         ld c,(hl)
         ld hl,(score)
         add hl,bc
         ld (score),hl
         call prscore
        ld hl,monsterskilledhere
        inc (hl)
         pop bc
        call getmaproom ;a=current room
        ld hl,killedmonsterslist
        add a,l
        ld l,a
        adc a,h
        sub l
        ld h,a
;бит=номер текущего монстра, его можно узнать только из ix/iy
        ld a,(hl)
        ;or (ix+OBJ_NUMBERMASK)/iy для bomb
        ;ld (hl),a ;это в вызывающей процедуре
        ret

;быстро ветвить по OBJ_GFX на нужную ветку анимации и физики

moveobj_deadbody
	ld c,(ix+OBJ_X)
	ld b,(ix+OBJ_Y)

	ld a,(timer3flag)
	;and 3
        add a,(ix+OBJ_DY)
	;jr nz,moveobj_nogravity
        ;inc a
        ld (ix+OBJ_DY),a
        ;inc (ix+OBJ_DY)
;moveobj_nogravity
        ;or a
	;ld h,(ix+OBJ_Y)
        jp p,moveobj_ypositive
;движется вверх
        add a,b;h
        jp p,moveobj_deadbody_moveyq
;ударился головой об потолок
        ld (ix+OBJ_DY),0
        ld b,0 ;(ix+OBJ_Y),0
        jp moveobj_deadbody_moveyq
moveobj_ypositive
;движется вниз
        add a,b;h
        cp 64-9
        jr c,moveobj_deadbody_moveyq;moveobj_noyhole
        
        if 1==1

        call setidnone_procnone
        ;ld (ix+OBJ_GFX),ID_NONE
        ;ld (ix+OBJ_PROC_ADDR),moveobj_none&0xff
        ;ld (ix+OBJ_PROC_ADDR+1),moveobj_none/256

        else
        
        push de
        call rnd
        and 63
        pop de
        add a,10
        ld c,a ;(ix+OBJ_X),a
        ld b,48 ;(ix+OBJ_Y),50
        ld (ix+OBJ_DX),0
        ld (ix+OBJ_DY),0
        ld (ix+OBJ_GFX),ID_CALMAR
        ld (ix+OBJ_PROC_ADDR),moveobj_calmar&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_calmar/256
        
        endif
        
;moveobj_deadbody_noyhole
moveobj_deadbody_moveyq
	;ld a,b ;y
	;or a
	;jr z,$+4
	;cp 64-1;-9
        ;jp moveobj_deadbody_moveyq
	ld a,(ix+OBJ_DY)
	;jr nz,moveobj_deadbody_nochangedy
	 ;neg
	 ;ld (ix+OBJ_DY),a
;moveobj_deadbody_nochangedy
	add a,b ;y
	ld (ix+OBJ_Y),a
	ld a,c
	cp 8+1
        ccf
	jr nc,$+4
	cp 120-9
	ld a,(ix+OBJ_DX)
	jr c,moveobj_deadbody_nochangedx
	 neg
	 ld (ix+OBJ_DX),a
moveobj_deadbody_nochangedx
	add a,c ;y
	;ld (ix+OBJ_Y),b
	ld (ix+OBJ_X),a
        ret

;1. медленно колеблется вверх-вниз, через время переходит в режим стрельбы
;DX=задержка до следующего режима
;DY=скорость по Y
moveobj_bossbody
        ld a,(timer3flag)
        or a
        jr z,moveobj_bossbody_nomove
         ld a,(ix+OBJ_GFX)
         xor 1
         ld (ix+OBJ_GFX),a
         ld a,(ix+OBJSIZE+OBJ_GFX)
         xor 1
         ld (ix+OBJSIZE+OBJ_GFX),a ;глаза
moveobj_bossbody_nomove
        ld a,(ix+OBJ_Y)
        add a,(ix+OBJ_DY)
        ld (ix+OBJ_Y),a
         sub 5;9
         ld (ix+OBJSIZE+OBJ_Y),a
        cp 48-5-1
        jr nc,moveobj_bossbody_movereturn
        cp 20-5
        jp nc,moveobj_bossbody_nomoveq
moveobj_bossbody_movereturn
        xor a
        sub (ix+OBJ_DY)
        ld (ix+OBJ_DY),a
moveobj_bossbody_nomoveq
        dec (ix+OBJ_DX)
	ld a,(ix+OBJ_X)
        jp nz,firecollision0_no ;проверка столкновения с героем (там есть и напрыг)
        ld (ix+OBJ_DX),3
        ld (ix+OBJ_DY),1
        ld (ix+OBJ_PROC_ADDR),moveobj_bossbody2&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_bossbody2/256
boss_closeeyes
        ld (ix+OBJ_GFX),ID_BOSS+2
        ld (ix+OBJSIZE+OBJ_GFX),ID_BOSSEYE+2
        ret

;2. периодически стреляет другим монстром в позиции после следующей (т.е. после глаз)
;DX=счётчик монстров, которыми стреляем
;DY=задержка до очередного выстрела
moveobj_bossbody2
        dec (ix+OBJ_DY)
	ld a,(ix+OBJ_X)
        jp nz,firecollision0_no ;проверка столкновения с героем (там есть и напрыг)
;пора стрелять
        ld (ix+OBJ_DY),40
        ld a,(ix+OBJ_X)
        ld (ix+(3*OBJSIZE)+OBJ_X),a
        ld (ix+(4*OBJSIZE)+OBJ_X),a
        sub 4
        ld (ix+(2*OBJSIZE)+OBJ_X),a
        ld a,(ix+OBJ_Y)
        ld (ix+(2*OBJSIZE)+OBJ_Y),a
        ld (ix+(3*OBJSIZE)+OBJ_Y),a
        ld (ix+(4*OBJSIZE)+OBJ_Y),a
        ld (ix+(2*OBJSIZE)+OBJ_DY),0
        ld (ix+(3*OBJSIZE)+OBJ_DY),-1
        ld (ix+(4*OBJSIZE)+OBJ_DY),+1
        ld a,2
        ld (ix+(2*OBJSIZE)+OBJ_DX),a
        ld (ix+(3*OBJSIZE)+OBJ_DX),a
        ld (ix+(4*OBJSIZE)+OBJ_DX),a
        ld a,ID_BOSSPROJECTILE
        ld (ix+(2*OBJSIZE)+OBJ_GFX),a
        ld (ix+(3*OBJSIZE)+OBJ_GFX),a
        ld (ix+(4*OBJSIZE)+OBJ_GFX),a
        ld hl,moveobj_bossprojectile
        ld (ix+(2*OBJSIZE)+OBJ_PROC_ADDR),l
        ld (ix+(3*OBJSIZE)+OBJ_PROC_ADDR),l
        ld (ix+(4*OBJSIZE)+OBJ_PROC_ADDR),l
        ld (ix+(2*OBJSIZE)+OBJ_PROC_ADDR+1),h
        ld (ix+(3*OBJSIZE)+OBJ_PROC_ADDR+1),h
        ld (ix+(4*OBJSIZE)+OBJ_PROC_ADDR+1),h

        dec (ix+OBJ_DX)
	ld a,(ix+OBJ_X)
        jp nz,firecollision0_no ;проверка столкновения с героем (там есть и напрыг)
;выстрелы кончились
        ld (ix+OBJ_DX),50
        ld (ix+OBJ_DY),1
        ld (ix+OBJ_GFX),ID_BOSS+3
        ld (ix+OBJSIZE+OBJ_GFX),ID_BOSSEYE+3

        ld (ix+OBJ_PROC_ADDR),moveobj_bossbody3&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_bossbody3/256
        ret

;3. медленно колеблется вверх-вниз, через время переходит в режим полёта
moveobj_bossbody3
        ld a,(timer)
        and 7
        jr z,moveobj_bossbody3_nomove
        ld a,(ix+OBJ_Y)
        add a,(ix+OBJ_DY)
        ld (ix+OBJ_Y),a
         sub 5;9
         ld (ix+OBJSIZE+OBJ_Y),a
        cp 48-5-1
        jr nc,moveobj_bossbody3_movereturn
        cp 20-5
        jp nc,moveobj_bossbody3_nomove
moveobj_bossbody3_movereturn
        xor a
        sub (ix+OBJ_DY)
        ld (ix+OBJ_DY),a
moveobj_bossbody3_nomove
        dec (ix+OBJ_DX)
	ld a,(ix+OBJ_X)
        jp nz,firecollision0_no ;проверка столкновения с героем (там есть и напрыг)
        ld (ix+OBJ_DX),50
        ld (ix+OBJ_GFX),ID_BOSS
        ld (ix+OBJSIZE+OBJ_GFX),ID_BOSSEYE

        ld (ix+OBJ_PROC_ADDR),moveobj_bossbody4&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_bossbody4/256
        ret

;4. меняет позицию (взлетает и делает круг по экрану против часовой?)
;DX=указатель в таблице траектории?
moveobj_bossbody4
;TODO

        dec (ix+OBJ_DX)
	ld a,(ix+OBJ_X)
        jp nz,firecollision0_no ;проверка столкновения с героем (там есть и напрыг)
        ld (ix+OBJ_DX),50
        ld (ix+OBJ_DY),1
        ld (ix+OBJ_GFX),ID_BOSS
        ld (ix+OBJSIZE+OBJ_GFX),ID_BOSSEYE

        ld (ix+OBJ_PROC_ADDR),moveobj_bossbody&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_bossbody/256
        ret

moveobj_bossdying
;DX=время до очередного взрыва
;DY=число взрывов
        dec (ix+OBJ_DX)
        ret nz
        call bomb
        
        call rnd
        and 15
        inc a
        ld (ix+OBJ_DX),a;3;6
        dec (ix+OBJ_DY)
        ret nz
        ;ld (ix+OBJ_GFX),ID_NONE
        call setidnone_procnone
        ld (ix+OBJSIZE+OBJ_GFX),ID_NONE ;уничтожить глаза тоже
        ld (ix+OBJ_PROC_ADDR),moveobj_bossdead&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_bossdead/256
         ld a,4
         jp SFXPLAY ;не идём на herocollision0_no, т.к. там портится GFX (могут получиться невозможные значения)

moveobj_bossdead
        call addtimebonus
;сообщение "ты убил не того монстра!"
        ld hl,resprq
        ld (resprscript),hl
        halt
        ld hl,emptyprsprscriptwithmc
        ld (prsprscriptaddr),hl
         call waitkey_prepareseconds
        call promg
         call pausekeeptimer
;переход на следующий уровень без дополнительных сообщений
        jp newlevelpp ;там нет addtimebonus

moveobj_bossprojectile
;двигаем влево до края экрана и стираем
        ld a,(ix+OBJ_Y)
        add a,(ix+OBJ_DY)
        ld (ix+OBJ_Y),a
        cp 56
        jr nc,moveobj_bossprojectile_delete
        ld a,(ix+OBJ_X)
        sub (ix+OBJ_DX)
        ld (ix+OBJ_X),a
	;ld a,(ix+OBJ_X)
        jp nc,firecollision0_no ;проверка столкновения с героем (там есть и напрыг)
moveobj_bossprojectile_delete
        jp setidnone_procnone
        ;ld (ix+OBJ_GFX),ID_NONE
        ;ld (ix+OBJ_PROC_ADDR),moveobj_none&0xff
        ;ld (ix+OBJ_PROC_ADDR+1),moveobj_none/256
        ;ret

moveobj_sosulka
;проверить, что рядом идёт игрок
        ld a,(objects+(7*OBJSIZE)+OBJ_X)
        sub (ix+OBJ_X)
        add a,SOSULKA_MOTIONDETECT_RADIUS
        cp SOSULKA_MOTIONDETECT_RADIUS*2
        ret nc
        ld (ix+OBJ_PROC_ADDR),moveobj_sosulka_falling&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_sosulka_falling/256
        ret

moveobj_sosulka_falling
	ld a,(ix+OBJ_Y)
	add a,(ix+OBJ_DY)
	ld (ix+OBJ_Y),a
	 cp 64-8-4;(ix+OBJ_MAXX);120-9
         ;jr nc,moveobj_sosulka_remove
         ;jr nc,moveobj_sosulka_remove
	ld a,(ix+OBJ_X)
        jp c,firecollision0_no ;moveobj_firecollision
moveobj_sosulka_remove
        ;ld (ix+OBJ_GFX),ID_NONE
        ;ld (ix+OBJ_PROC_ADDR),moveobj_none&0xff
        ;ld (ix+OBJ_PROC_ADDR+1),moveobj_none/256
        call setidnone_procnone_nosety
        ; ld a,(ix+OBJ_GFX)
        ;call removemonster ;выключить монстра в killedmonsterslist
        ;or (ix+OBJ_NUMBERMASK)
        ;ld (hl),a ;это в вызывающей процедуре
        ;ld (ix+OBJ_GFX),ID_NONE
        jp bomb ;в зависимости от типа монстра ;после изменения GFX, иначе засчитают убийство два раза

herocollision_killmonster_byjump
        display "herocollision_killmonster_byjump=",$
         ld a,(ix+OBJ_GFX)
         cp ID_BOSSPROJECTILE
         jp z,herocollision_nokillmonster
         cp ID_SOSULKA
         jp z,herocollision_nokillmonster
          and 0xfc
         cp ID_BOSS
         jr nz,herocollision_killmonster_ok
         ld a,-20
         ld (objects+(7*OBJSIZE)+OBJ_DX),a
         ld hl,objects+(7*OBJSIZE)+OBJ_FLAGS
         res 0,(hl) ;not on ground
        xor a
        ld (timer),a ;костыль!!!
        if SLOWJUMP
        ld (timer3flag),a ;костыль!!!
        ld a,-3
        else
        ld a,-5
        endif
        ld (objects+(7*OBJSIZE)+OBJ_DY),a
         ;ld a,(ix+OBJ_HEALTH)
         ;sub 100
         ;ld (ix+OBJ_HEALTH),a
         dec (ix+OBJ_HEALTH)
         jr nz,herocollision_killmonster_jumpfrom ;nc
;переход в режим умирания босса
        ld (ix+OBJ_DX),1 ;время до очередного взрыва
        ld (ix+OBJ_DY),8 ;число взрывов
        ld (ix+OBJ_PROC_ADDR),moveobj_bossdying&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_bossdying/256
        ;ld (ix+OBJ_GFX),ID_BOSS+2 ;зажмурить
        ;ld (ix+OBJSIZE+OBJ_GFX),ID_BOSSEYE+2 ;зажмурить
        call boss_closeeyes
        if 1==0
;уничтожим выстрелы босса
         ld hl,moveobj_none
         ld (ix+(OBJSIZE*2)+OBJ_PROC_ADDR),l
         ld (ix+(OBJSIZE*3)+OBJ_PROC_ADDR),l
         ld (ix+(OBJSIZE*4)+OBJ_PROC_ADDR),l
         ld (ix+(OBJSIZE*2)+OBJ_PROC_ADDR+1),h
         ld (ix+(OBJSIZE*3)+OBJ_PROC_ADDR+1),h
         ld (ix+(OBJSIZE*4)+OBJ_PROC_ADDR+1),h
         ld a,ID_NONE
         ld (ix+(OBJSIZE*2)+OBJ_GFX),a
         ld (ix+(OBJSIZE*3)+OBJ_GFX),a
         ld (ix+(OBJSIZE*4)+OBJ_GFX),a
        endif
        ret
         
herocollision_killmonster_ok
        call killmonster ;там может быть bomb
        
herocollision_killmonster_jumpfrom
        xor a
        ld (timer),a ;костыль!!!
        if SLOWJUMP
        ld (timer3flag),a ;костыль!!!
        ld a,-3
        else
        ld a,-5
        endif
        ld (objects+(7*OBJSIZE)+OBJ_DY),a
         ld a,3 ;3 перезвяк, 5 диньк, 7 тормоз, 9 миниприз, 10 приз, 11 бум
         jp SFXPLAY ;не идём на herocollision0_no, т.к. там портится GFX (могут получиться невозможные значения)

;враги
moveobjects_changedy
          xor a
	  sub (ix+OBJ_DY)
	 ld (ix+OBJ_DY),a
	ld a,(ix+OBJ_X)
        jp moveobj_firecollision

moveobj_white
        ld a,(timer3flag)
	xor (ix+OBJ_GFX)
	ld (ix+OBJ_GFX),a
	ld a,(ix+OBJ_Y)
	add a,(ix+OBJ_DY)
	ld (ix+OBJ_Y),a
	;cp 8;(ix+OBJ_MINX);8+1
	cp (ix+OBJ_MINX);8+1
         jr c,moveobjects_changedy
	 ;cp 64-8-8;(ix+OBJ_MAXX);120-9
	 cp (ix+OBJ_MAXX);120-9
         jr nc,moveobjects_changedy
	ld a,(ix+OBJ_X)
        jp moveobj_firecollision

moveobj_pink_wait
        ld a,(ix+OBJ_DY)
        add a,8
        ld (ix+OBJ_DY),a ;будет как таймер
	ld a,(ix+OBJ_X)
        jr nc,moveobj_firecollision
        ld (ix+OBJ_PROC_ADDR),moveobj_pink&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_pink/256
        jp moveobj_firecollision

moveobj_pink
        ld a,(timer3flag)
	xor (ix+OBJ_GFX)
	ld (ix+OBJ_GFX),a
	ld a,(ix+OBJ_X)
	 add a,(ix+OBJ_DX)
	ld (ix+OBJ_X),a
        jp moveobj_minmax_firecollision

moveobjects_changedx
           ld c,a
          xor a
	  sub (ix+OBJ_DX)
	 ld (ix+OBJ_DX),a
	 ;add a,c ;y
	 ;ld (ix+OBJ_X),a
         ld a,(ix+OBJ_GFX)
         xor SPRTURN
         ld (ix+OBJ_GFX),a
         and 0xfc
         cp ID_PINK
          ld a,c
         jp nz,moveobj_firecollision ;ret nz
        ld (ix+OBJ_PROC_ADDR),moveobj_pink_wait&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_pink_wait/256
        jp moveobj_firecollision

moveobj
moveobj_calmar
moveobj_red
timer3flag=$+1
	ld a,0
	xor (ix+OBJ_GFX)
	ld (ix+OBJ_GFX),a

	;ld b,(ix+OBJ_Y)
	;ld a,(ix+OBJ_DY)
	;add a,b ;y
	;ld (ix+OBJ_Y),a
;попал, если y <= fireyx_y < y+14/2, а также x <= fireyx_x < x+16/2
	ld a,(ix+OBJ_X)
	 add a,(ix+OBJ_DX)
          bit 0,(ix+OBJ_GFX)
          jr z,$+2+3
	ld (ix+OBJ_X),a
moveobj_minmax_firecollision
;a=x
	cp (ix+OBJ_MINX);8+1
         jr c,moveobjects_changedx
	 cp (ix+OBJ_MAXX);120-9
         jr nc,moveobjects_changedx ;TODO для скорости сделать две ветки спрайта - влево и вправо?
        
moveobj_firecollision
firecollision_firexmin=$+1
        cp 0-FIREXRADIUS
        jp m,firecollision0_no
firecollision_firexmax=$+1
        cp 0+FIREXRADIUS+1
        jr c,firecollision0
firecollision0_no
herocollision_heroxmin=$+1
        cp 0-HEROXRADIUS
        ret m ;jp m,herocollision0_no
herocollision_heroxmax=$+1
        cp 0+HEROXRADIUS+1
        ret nc

herocollision0
        ld a,(ix+OBJ_Y);b
herocollision_heroymin=$+1
        sub 0-HEROYRADIUS
        cp HEROYRADIUS*2+1
        ret nc ;jp nc,herocollision0q
;если герой сверху, то убиваем монстра
        display "herocollision=",$
        ;cp HEROYRADIUS+2
        ;jr nc,herocollision_nokillmonster
        ld a,(objects+(7*OBJSIZE)+OBJ_DY)
        if SLOWJUMP
        cp 1
        else
        cp 2
        endif
        jp p,herocollision_killmonster_byjump
herocollision_nokillmonster
         ld a,(objects+(7*OBJSIZE)+OBJ_FLAGS)
         and 4 ;blink
         ret nz ;jr nz,herocollision0q
        display "collision=",$
;столкновение с врагом!
         ld a,1 ;malus
         call SFXPLAY
        ld a,(ix+OBJ_GFX)
        cp ID_SOSULKA
        push af
         call z,moveobj_sosulka_remove ;bomb
        pop af
        ld hl,energy_malus
         ;jp z,instantkill
        ld (hl),2;3
        ret nz ;jr nz,$+4
        ld (hl),20 ;гарантированная смерть
;herocollision0q
	 ;ld a,(ix+OBJ_X)
        ret ;jp herocollision0_no

firecollision0
	ld a,(ix+OBJ_Y);b
firecollision_firey=$+1
	sub 0
        cp -(FIREYRADIUS*2-1) ;24/2 ;16/2
	 ld a,(ix+OBJ_X)
        jp c,firecollision0_no
;попал! убиваем врага (сначала уменьшаем его энергию)
        xor a
        ld (firecollision_firexmin),a
        ld (firecollision_firexmax),a ;destroy fire, чтобы в этом фрейме больше не было взрывов
        ld (fireyx_x),a
         ld a,2 ;3 перезвяк, 5 диньк, 7 тормоз, 9 миниприз, 10 приз, 11 бум
         call SFXPLAY
        ld a,(ix+OBJ_HEALTH)
        sub 20
        ld (ix+OBJ_HEALTH),a
	 ld a,(ix+OBJ_X)
        jp nc,firecollision0_no ;энергия не кончилась
         ld a,(ix+OBJ_GFX)
         and 0xfc
         cp ID_RED
         ld a,5 ;3 перезвяк, 5 диньк, 7 тормоз, 9 миниприз, 10 приз, 11 бум
         call nz,SFXPLAY
         ;jp killmonster ;не идём на firecollision0_no, т.к. там портится GFX (могут получиться невозможные значения)

killmonster
        ld (ix+OBJ_PROC_ADDR),moveobj_deadbody&0xff
        ld (ix+OBJ_PROC_ADDR+1),moveobj_deadbody/256
        ld (ix+OBJ_DY),-4
        ld (ix+OBJ_DX),-1
         ld a,(ix+OBJ_GFX)
        call removemonster ;выключить монстра в killedmonsterslist, добавить score
        or (ix+OBJ_NUMBERMASK)
        ld (hl),a ;это в вызывающей процедуре
         ;ld a,(ix+OBJ_GFX)
         ;and 0xfc
         ;cp ID_RED
         ;call z,bomb ;в зависимости от типа монстра
        ld a,(ix+OBJ_GFX)
        srl a
        srl a
        add a,ID_CALMARDEAD - (ID_CALMAR/4)
       ;ld a,ID_CALMARDEAD ;ID_WHITEDEAD может повиснуть, если к нему прибавить SPRTURN
        ld (ix+OBJ_GFX),a
        cp ID_REDDEAD
        ret nz
         ;call setidnone_procnone ;плохо смотрится превращение помидора во взрыв, пусть лучше улетает вместе со взрывом
         jp bomb ;в зависимости от типа монстра ;после изменения GFX, иначе засчитают убийство два раза

movemainobj_up_thorns
        inc (IX+OBJSIZE+OBJ_DY) ;чтобы не залипало
         bit 2,(IX+OBJSIZE+OBJ_FLAGS) ;blink
         ret nz
        ld a,2;3
        ld (energy_malus),a
         ld a,1 ;malus
         jp SFXPLAY

;герой
movemainobj        
       if 1==1
        ld hl,(objects+(7*OBJSIZE)+OBJ_DX-1) ;h=dx (-128..127) (реально -MAXSPEED..+MAXSPEED)
        xor a
        sra h
        rra
        sra h
        rra
        sra h
        rra
         ;sra h
         ;rra
        ;ld l,a ;60+12 ;hl = (+-7.8) -8..+7
        ;ld c,(ix+OBJSIZE+OBJ_XLOW)
	;ld b,(ix+OBJSIZE+OBJ_X)
        ;add hl,bc
        add a,(ix+OBJSIZE+OBJ_XLOW)
        ld (objects+(7*OBJSIZE)+OBJ_XLOW),a
        ld a,(objects+(7*OBJSIZE)+OBJ_X)
        adc a,h
        ld h,a
       else
	ld a,(objects+(7*OBJSIZE)+OBJ_DX)
        ld l,a
        rla
        sbc a,a
        ld h,a
        add hl,hl
        add hl,hl
        add hl,hl
        add hl,hl ;73
         add hl,hl
        ld c,(ix+OBJSIZE+OBJ_XLOW)
	ld b,(ix+OBJSIZE+OBJ_X)
        add hl,bc
        ld a,h
       endif
        cp 8
        jr c,movemainobj_leftedge
        cp 120-9 +1
        jr nc,movemainobj_rightedge
movemainobj_norightedge
        ;ld (ix+OBJSIZE+OBJ_X),h
        ;ld (ix+OBJSIZE+OBJ_XLOW),l
        ld (objects+(7*OBJSIZE)+OBJ_X),a
         sub HEROXRADIUS
         ld (herocollision_heroxmin),a
         add a,HEROXRADIUS*2+1
         ld (herocollision_heroxmax),a
         ld a,h
        rra
        rra
         inc a ;на одно знакоместо правее, чем левая граница персонажа
        and 31
        LD E,A ;будем проверять боковую стенку с помощью этого

         ld a,(objects+(7*OBJSIZE)+OBJ_Y)
         ld h,a ;ld h,(ix+OBJSIZE+OBJ_Y)
         ;sub HEROYRADIUS
         ;ld (herocollision_heroymin),a
        if SLOWJUMP
        ld a,(timer3flag)
        else
	ld a,(timer)
	and 1
        endif
        add a,(ix+OBJSIZE+OBJ_DY);(objects+(7*OBJSIZE)+OBJ_DY)
        jp p,movemainobj_ypositive
        ld (objects+(7*OBJSIZE)+OBJ_DY),a
;движемся вверх
        add a,h
        jp m,movemainobj_roof
;проверить, что голова ty = Y/8 внутри потолка
        ld b,a ;y
         add a,2 ;якобы персонаж высотой 14, а не 18 (тогда он может впрыгнуть в дыру высотой 1 тайл)
        and 0x38
        ;ld c,a
        add a,a
        add a,a
        ADD A,E
        ld l,a
        ld h,tilemap/256 ;32*8 tiles
       ld a,(hl)
       cp 0x78;0xc0 ;шипы тоже отталкивают голову
       jr c,movemainobj_ab_moveyq
       add a,a ;cp 0x80 ;jr c
       jr nc,movemainobj_up_thorns
       add a,a ;cp 0xc0 ;jr c
       jp nc,movemainobj_ab_moveyq
;если потолок, то выравниваемся на 16: Y = ty*8 + 8 ???
        xor a
        ld (objects+(7*OBJSIZE)+OBJ_DY),a
        ret

movemainobj_rightedge
        ld hl,mapx
        inc (hl)
        call filltilemap
        ld h,8
        ld a,h
        jp movemainobj_norightedge ;там исправляется баундинг бокс героя
movemainobj_leftedge
        ld hl,mapx
        dec (hl)
        call filltilemap
        ld h,120-9
        ld a,h
        jp movemainobj_norightedge ;там исправляется баундинг бокс героя
movemainobj_roof
;скроллить выше... лучше бы не в этой процедуре (т.к. она вызывается в цикле логики, который может быть 2 раза за кадр)
        ld (ix+OBJSIZE+OBJ_Y),64-9
        ld hl,mapy
        dec (hl)
        jp filltilemap ;там исправляется баундинг бокс героя

movemainobj_ab_moveyq
         ;res 0,(ix+OBJSIZE+OBJ_FLAGS) ;not on ground ;Sand просил раскомментировать, получается прыжок в падении
        ld a,b
movemainobj_moveyq
         res 4,(ix+OBJSIZE+OBJ_FLAGS) ;no drop ;когда мы уже не внутри платформы/бетона
movemainobj_moveyqq
        ld (objects+(7*OBJSIZE)+OBJ_Y),a
         sub HEROYRADIUS
         ld (herocollision_heroymin),a
;a=Y=y/2
;e=x/8+1
;h=tilemap/256
        add a,4+9 +HEROYRADIUS ;если 4+9, то на высоту 3 прыгаем не каждый раз (из-за фазы таймера, решено костылём)
        and 0x38
        ;ld c,a
        add a,a
        add a,a
        ADD A,E

        sub 32 ;a = индекс стены, которая в середине персонажа
        ld l,a
        ld a,(hl)
        add a,a
        cp 0x70*2 ;дверь/ключ/шипы ;так иногда бьёт бетоном как шипами (фикс ниже)
        ;ld hl,objects+(7*OBJSIZE)+OBJ_DX
        jr nc,maybethorns
nothorns       
;hl = адрес стены, которая в середине персонажа
         ld a,(objects+(7*OBJSIZE)+OBJ_DX)
         or a
         call z,movemainobj_testleft
        ;bit 7,(ix+OBJSIZE+OBJ_DX) ;DX
        ;jr nz,movemainobj_testleft ;в зависимости от направления движения
        jp m,movemainobj_testleft ;в зависимости от направления движения
;movemainobj_testright
        inc l ;индекс стены, которая правее персонажа
        ld a,(hl)
         ;dec l
        ;cp 0xc0 ;>=0xc0 совсем непроходимо
        ;ret c
       cp 0x78;0xc0 ;шипы тоже отталкивают
       ret c
       add a,a
       jr nc,testright_thorns
       add a,a
       ret nc
;>=0xc0 совсем непроходимо
        ld (ix+OBJSIZE+OBJ_DX),0 ;DX
         ld (ix+OBJSIZE+OBJ_XLOW),0 ;предсказуемость
	;ld hl,objects+(7*OBJSIZE)+OBJ_X ;TODO reg
        ld a,(objects+(7*OBJSIZE)+OBJ_X)
        sub 4
        or 3
        ld (objects+(7*OBJSIZE)+OBJ_X),a
        ret
movemainobj_testleft
        dec l ;ld e,a ;индекс стены, которая левее персонажа
        ld a,(hl)
         inc l
        ;cp 0xc0 ;>=0xc0 совсем непроходимо
        ;ret c
       cp 0x78;0xc0 ;шипы тоже отталкивают
       ret c
       add a,a
       jr nc,testleft_thorns
       add a,a
       ret nc
;>=0xc0 совсем непроходимо
        ld (ix+OBJSIZE+OBJ_DX),0
         ld (ix+OBJSIZE+OBJ_XLOW),0 ;предсказуемость
	;ld hl,objects+(7*OBJSIZE)+OBJ_X ;TODO reg
        ld a,(objects+(7*OBJSIZE)+OBJ_X)
        add a,4
        and 0xfc
        ld (objects+(7*OBJSIZE)+OBJ_X),a
        ret
testleft_thorns
testright_thorns
        xor a
        sub (ix+OBJSIZE+OBJ_DX)
        ld (ix+OBJSIZE+OBJ_DX),a
         bit 2,(IX+OBJSIZE+OBJ_FLAGS) ;blink
         ret nz
        ld a,2;3
        ld (energy_malus),a
         push hl
         ld a,1 ;malus
         call SFXPLAY
         pop hl
         ret
        
maybethorns
        ld a,(hl)
        cp 0x74 ;ключ ;проверяем точно, а то был редкий глюк, когда взяли 0xf4
        jr nz,nokeycard
        display "takenkeycardslist_addr=",takenkeycardslist_addr
        display "takekeycard=",$
        ld (hl),0 ;кладём пустой тайл (а теперь надо скорректировать resprscript!!!)
         ;push de
         push hl
        ld hl,emptyprsprscript ;выход без мультиколора и восстановления спрайтов
        ld (prsprscriptaddr),hl
       ld a,0x3f;0x41;7
       call clearattr;remove_sprscript
       halt
        
        ld hl,keycards
        inc (hl)
        ;ld bc,(mapx) ;h=mapy
        ;ld a,b
        ;add a,a
        ;add a,a
        ;add a,a
        ;add a,c
        call getmaproom ;a=current room
;запоминаем в keycardslist
takenkeycardslist_addr=$+1
        ld hl,takenkeycardslist
        ld (hl),a ;mapyx
        inc hl
         pop de
         push de
        ld (hl),e ;yx
        inc hl
        ld (takenkeycardslist_addr),hl
;рисуем тайл
        ;ld a,(objects+(7*OBJSIZE)+OBJ_Y)
        ; add a,4+9-8
         ld a,e
         rra
         rra
        and 0x38
        ld l,a
        ;ld a,(objects+(7*OBJSIZE)+OBJ_X)
        ;rra
        ;rra
        ; inc a ;на одно знакоместо правее, чем левая граница персонажа
         ld a,e
        and 31
        add a,0x40
;a=x/8 + 0x40
;l=y/2
        ld h,tytoscr/256
        add a,(hl)
        inc h
        ld h,(hl)
        ld l,a ;hl=scr
        ld ly,1
;ly=number of columns
;de=tilemap
;hl=screen
        call prtilemap_columns
         
         ld a,9 ;3 перезвяк, 5 диньк, 7 тормоз, 9 миниприз, 10 приз, 11 бум
         call SFXPLAY
         
       call empty_restore_sprscript
         
         pop hl
         ;pop de
        jp nothorns ;keep hl!
nokeycard
        jr nc,nodoor
        ld bc,keycards
        ld a,(bc)
        dec a
        jp m,nothorns ;keep hl!
        ld (bc),a
        jp newlevel
nodoor
;шипы 0x78/7c или бетон 0xf8/fc
        rla
        jp c,nothorns ;keep hl!
       xor a
       ld (timer),a ;костыль!!!
       if SLOWJUMP
        ld (timer3flag),a ;костыль!!!
        ld (ix+OBJSIZE+OBJ_DY),-2 ;не сбрасываем флаг on ground, так что можно будет прыгнуть в полёте?
       else
       ld a,-1 ;можно -2, будет высоко отскакивать
       sub (ix+OBJSIZE+OBJ_DY)
        jp m,$+3+2
        ld a,-2 ;на всякий случай (бетон над шипами?)
       ;ld a,(ix+OBJSIZE+OBJ_DY)
       ;cpl
       ld (ix+OBJSIZE+OBJ_DY),a
       endif
       ;ld a,(ix+OBJSIZE+OBJ_Y)
       ;sub 3
       ;ld (ix+OBJSIZE+OBJ_Y),a
        bit 0,(ix+OBJSIZE+OBJ_FLAGS)
        res 0,(ix+OBJSIZE+OBJ_FLAGS) ;всё-таки сбрасываем, а то сразу погасится dx
        jr z,thornsdomalus ;летели
        xor a
        sub (ix+OBJSIZE+OBJ_DX)
        ld (ix+OBJSIZE+OBJ_DX),a ;если шли пешком, то dx в противоположную сторону, а если летели, то в ту же
thornsdomalus
         bit 2,(IX+OBJSIZE+OBJ_FLAGS) ;blink
         jp nz,nothorns
        ld a,2;3
        ld (energy_malus),a
         push hl
         ld a,1 ;malus
         call SFXPLAY
         pop hl
         jp nothorns ;keep hl!

movemainobj_ypositive
;движемся вниз
        cp 4;6;7 пролетает сквозь шипы сверху, даже 6 изредка - почему?
        jr nc,movemainobj_nogravity
        ld (objects+(7*OBJSIZE)+OBJ_DY),a
movemainobj_nogravity
        add a,h
        cp 64-9
        jr nc,movemainobj_yhole
;movemainobj_noyhole
;проверить, что ноги ty = (Y+9)/8 внутри пола
        ld b,a ;Y=y/2
        add a,9
        and 0x38
        ld c,a
        add a,a
        add a,a
        ADD A,E
        ld l,a ;на одно знакоместо правее, чем левая граница персонажа
        ld h,tilemap/256 ;32*8 tiles
        bit 7,(hl) ;тайлы >=0x80 непроходимы по вертикали
        jp z,movemainobj_ab_moveyq ;воздух => выключаем drop
         ;dec l
         ;ld a,(hl)
         ;inc l
         ;or (hl)
         ;jp p,movemainobj_ab_moveyq ;воздух => выключаем drop
        bit 4,(ix+OBJSIZE+OBJ_FLAGS) ;drop?
        jr z,movemainobj_movedown_beton ;no drop
        bit 6,(hl) ;нельзя дропнуться через бетон
        jr z,movemainobj_movedown_drop ;дропаемся
         res 4,(ix+OBJSIZE+OBJ_FLAGS) ;no drop ;спрыгнул на бетон без воздуха
movemainobj_movedown_beton ;если drop&небетон
;если пол, то выравниваемся на 16: Y = ty*8 - 9
        xor a
        ld (objects+(7*OBJSIZE)+OBJ_DY),a
         set 0,(ix+OBJSIZE+OBJ_FLAGS) ;on ground
        ;ld a,b
        ;add a,9
        ;and 0x3c;38
        ld a,c ;выровненный y
        sub 9
         ;ld a,56-9
        jp nc,movemainobj_moveyqq
        inc a
        jp movemainobj_moveyqq
movemainobj_movedown_drop
         res 0,(ix+OBJSIZE+OBJ_FLAGS) ;not on ground
         push bc
         push hl
         ld a,7 ;3 перезвяк, 5 диньк, 7 тормоз, 9 миниприз, 10 приз, 11 бум
         call SFXPLAY
         pop hl
         pop bc
         ld a,b ;y/2
         jp movemainobj_moveyqq

movemainobj_yhole
;провалиться
        ld (ix+OBJSIZE+OBJ_Y),0
        ld hl,mapy
        inc (hl)
        jp filltilemap ;там исправляется баундинг бокс героя
