#ifdef SetBreakpointWithY push af ld a,0 SetBreakpointWithYVar = $-1 or a jr z,SetBreakpointWithYNotSet SetBreakpointWithYLoop: jr SetBreakpointWithYLoop SetBreakpointWithYNotSet: pop af #endif ;Typ, ;Blickwinkel ;ypos fein ;ypos grob ;xpos fein ;xpos grob ;KI var ;Health ;position before ;################################### ; EnemyKI - Routine Definitionen: ;################################### : ; EnemyMoveKI ; Returns: a = 0 wenn gar nicht bewegt ; ; PlayerEnemyBW --- Winkel, in dem der Player den Gegner sieht. ; PlayerEnemyBlickWinkel / ; Returns: 0 =< a =< 128 a = 0 bedeutet, Gegner steht direkt vor ihm. ; ; PlayerEnemyAusrichten --- Gibt Winkel, in dem der Player stehen müsste, um den Gegner Direkt zu sehn ; EnemyDist ---- Distanz von Enemy zu Player ; EnemyPlayerDist // ; PlayerEnemyDis / ; Returns hl = distanz ; ; EnemyPlayerAusrichten - Berechnet Winkel, den Gegner haben muss um Player Direkt zu sehn, und speichert diesen. ; Returns a = Winkel ; ; EnemyPlayerWinkelCalc - Berechnet Winkel, den Gegner haben muss um Player Direkt zu sehn. Wird NICHT gespeichert ; ; GetEnemyRandomDirection - Sucht einen Zufälligen Winkel und speichert den in Enemy Blickwinkel ; ; EnemyRayCast - Castet Ray auf richtung, in der Player stehen müsste, um Enemy zu sehen . ; Returns a!=0 --> enemy sichtbar , d=0, e=3 ; ; ; EnemyKI - Jump Tos ; ; KillEnemy --- Löscht enemy aus dem Buffer und Map ; Hat sofortigen Abbruch, der Aktuellen EnemyKI zur folge ; ; DeleteEnemy --- Löscht enemy aus dem Buffer ; Hat sofortigen Abbruch, der Aktuellen EnemyKI zur folge ; ; SetEnemyFlight --- Setzt Enemy auf "Fliehen" ; Hat sofortigen Abbruch, der Aktuellen EnemyKI zur folge ; ; SetEnemyAttack --- Enemy Attackiert ; Hat sofortigen Abbruch, der Aktuellen EnemyKI zur folge #ifdef EnableKI ld ix,EnemyBuffer KI_Loop: #ifdef DisableEnemyMove jp KI_End #endif ld a,(ix) ;typ or a jp z,KI_End ld (RayMoveSprite),a ;########################################### ;### Check, allgemeine Verhaltensmuster ex af,af' ; NÖTIG!!! wenn nicht standart KI, wirds für spezielle bestimmung gebraucht ld a,(ix+6) ;KI_var cp KI_StandstillStart jp c,NotSpecialKI_var jr z,EnemyStehtStill inc (ix+6) ; KI-var + 1 cp KI_AttackStart jr c,EnemyFlieht cp KI_DieStart jp c,EnemyAttackiert ; cp 255 ; jr c,EnemyStirbt EnemyStirbt: cp KI_DieEnd-1 jp nz,KI_Next KillEnemy: ld a,(ix+0) cp SpriteGrenzeEnemys+48 ; +11 jr c,KillEnemyNoBoss ld a,32 ;key2 jr KillEnemyOnSprite KillEnemyNoBoss: ld a,(ix+8) or a jr nz,KillEnemyOnSprite ld a,StandartEnemyItem KillEnemyOnSprite: ld (RayMoveSprite),a call EnemyMoveKI DeleteEnemy: push ix push ix pop hl ld de,EnemyBufferBytes add hl,de ; enemy nach dem zu überschreibenden pop de ; enemy zum überschreiben EnemyStirbtNextToCopy: ld bc,EnemyBufferBytes ldir ld a,(de) or a jr nz,EnemyStirbtNextToCopy jr KI_Loop EnemyStehtStill: call EnemyRayCast jr z,DeleteEnemy call EnemyPlayerWinkelCalc sub (ix+1) cp 128 jr c,EnemyStehtStillSichtbarOK neg EnemyStehtStillSichtbarOK: cp EnemyBlickfeld / 2 jp nc,KI_Next ld a,129 ld (ix+6),a EnemyFlieht: cp 170 jr z,EnemyFliehtEnd cp 129 call z,GetEnemyRandomDirection call PlayerEnemyDist push hl call EnemyMoveKI call PlayerEnemyDist pop de sbc hl,de call c,GetEnemyRandomDirection ; distanz wurde verkürzt. neue direction. jr KI_Next EnemyFliehtEnd: ld (ix+6),0 call EnemyPlayerAusrichten jr KI_Next EnemyAttackiert: cp KI_AttackStart+AttackErstesBildDauer+AttackZweitesBildDauer jr z,EnemyFliehtEnd ; --> zuende cp KI_AttackStart+AttackErstesBildDauer jr c,KI_Next jr nz,EnemyAttakiertNoShoot call EnemyRayCast jr z,EnemyFliehtEnd ; --> attacke zuende call EnemyDist ex de,hl ; de = distanz call MultDEx255 ; call div_ratio sra a ;/2 inc a ; dass ja nicht = 0 wird. ld (EnemyShootAbweichungsRate),a call EnemyPlayerWinkelCalc; a = soll winkel sub (ix+1) ; soll - ist jr nc,EnemyShootok neg EnemyShootok: cp 0 EnemyShootAbweichungsRate = $-1 jr nc,EnemyAttakiertNoShoot ld b,3 call _IonRandom sub 2 ex af,af' ld a,(RayMoveSprite) ;### SLOW rout but good enough. ld b,6 cp SpriteGrenzeEnemys+12 ;hund jr c,EnemyToPlayerDamadgeSet ld b,4 cp SpriteGrenzeEnemys+24 ;soldat jr c,EnemyToPlayerDamadgeSet ld b,7 cp SpriteGrenzeEnemys+36 ;SS jr c,EnemyToPlayerDamadgeSet ld b,10 cp SpriteGrenzeEnemys+48 ;priester jr c,EnemyToPlayerDamadgeSet ld b,17 BossDamadgeVar = $-1 ; sub SpriteGrenzeEnemys+60 ;Boss ; jr c,EnemyToPlayerDamadgeSet EnemyToPlayerDamadgeSet: ex af,af' add a,b ld b,a call HealthSub EnemyAttakiertNoShoot: jr KI_Next NotSpecialKI_var: ex af,af' ;### AllgemeinerVerhaltensmuster check beendet ;############################################# cp SpriteGrenzeEnemys + 12 ; Hund jr c,HundKI ld b,250 call _IonRandom cp ChanceForAttack jr c,SetEnemyAttack ; cp SpriteGrenzeEnemys + 12 + 12 ;Soldat ; jr c,SoldatKI jr StandartZickZackEnemy KI_Next: ld de,EnemyBufferBytes add ix,de jp KI_Loop ;Typ, <- ix ;Blickwinkel <- hl ;ypos fein ;ypos grob ;xpos fein ;xpos grob ;KI var ;Health SetEnemyFlight: ld (ix+6),KI_FlightStart jr KI_Next SetEnemyAttack: #ifndef DisableEnemyAttack ld (ix+6),KI_AttackStart #endif jr KI_Next HundKI: ; funktioniert nicht, erst prüfen ob call EnemyPlayerDist ld de,Hund_MinDistToAttack sbc hl,de jr c,SetEnemyAttack ; distanz - minimale Distanz = StandartZickZackEnemy: call EnemyPlayerAusrichten ld (HundKI_OldBW),a call PlayerEnemyBlickWinkel cp KI_TurnValue/2 jr nc,HundausserhalbPlayerBW cp KI_TurnValue/2-TurnArea jr c,HundKINoTurn ld a,b or a jr nz,HundKI_NoTurn ld a,2*KI_ZickZackWinkel + 1 HundKI_NoTurn: dec a ld (ix+6),a HundKINoTurn: ld a,(ix+1) sub KI_ZickZackWinkel add a,(ix+6) ; KI_var ld (ix+1),a HundausserhalbPlayerBW: call EnemyMoveKI ld (ix+1),0 HundKI_OldBW = $-1 jp z,SetEnemyFlight jr KI_Next ;########################## ; Enemy KI Routinen ;########################## EnemyMoveKI: ;Returns a=0 if move was blocked and hl = ki_var push ix pop hl inc hl push hl ld de,BlickwinkelMove ld bc,5 ldir call MoveEnemy ld a,(ColWorldMove) cp (ix+2) jr n z,EnemyHatSichBewegt ld a,(RowWorldMove) cp (ix+4) jr nz,EnemyHatSichBewegt ld a,-1 EnemyHatSichBewegt: inc a ; /= 0 pop de ; = Blickwinkel inc de ; yfein ld hl,ColWorldMove;BlickwinkelMove ld bc,4 ;5 ldir ret ;########################## PlayerEnemyBW: PlayerEnemyBlickWinkel: PEW_RowDistCalc1: ld d,(ix+5) ld e,(ix+4) xor a ld c,128 ld hl,(RowWorld) sbc hl,de jr nc,PEW_RowPos1 ld hl,(RowWorld) ex de,hl sbc hl,de inc a ld c,%01000000 PEW_RowPos1: push hl ;row dist PEW_ColDistCalc1: ld d,(ix+3) ld e,(ix+2) ld hl,(ColWorld) sbc hl,de jr nc,PEW_HL ld hl,(ColWorld) ex de,hl sbc hl,de add a,2 ex af,af' ld a,c xor %01000000 ld c,a ex af,af' PEW_HL: pop de ;de = RowDist push hl ;hl = ColDist sbc hl,de pop hl jr c,PEW_HLok ;Optimize jr z,PEW_HLok ex de,hl add a,4 PEW_HLok: sla l rl h sla l rl h sla l rl h ;*8 sla l rl h ;*16 sla l rl h ;*32 ex af,af' push bc call div_hl_by_de ;returns a = winkel pop bc ex af,af' ld hl,Blickwinkel or a ;0 jr z,PEWCalcWay2 ;OK sub 3 jr c,PEWCalcWay1 jr z,PEWCalcWay2 ;OK dec a ;4 jr z,PEWCalcWay1 ;OK sub 3 jr c,PEWCalcWay3 ;7 ;OK WAy1 PEWCalcWay1: ex af,af' add a,c sub (hl) jr PEWCalcWayBoth PEWCalcWay3: ex af,af' sub c jr PEWCalcWayBoth1 PEWCalcWay2: ex af,af' add a,c PEWCalcWayBoth1: add a,(hl) sub 64 PEWCalcWayBoth: ld b,0 cp 128 jr c,PEW_WinkelOK neg inc b PEW_WinkelOK: ret ;########################## PlayerEnemyAusrichten: call EnemyPlayerWinkelCalc add a,128 ; Winkel umdrehen ret ;########################## EnemyDist: EnemyPlayerDist: PlayerEnemyDist: call EnemyPlayerWinkelCalc ld hl,0 PlayerEnemyDistCol = $-2 ld de,0 PlayerEnemyDistRow = $-2 ld a,0 PlayerEnemyDistWinkel = $-1 or a jr nz,PED_NotHorzOrVert push hl sbc hl,de pop hl jr nc,PED_OnHorzOrVertCol ex de,hl PED_OnHorzOrVertCol: jr PED_Fertig PED_NotHorzOrVert: ex af,af' ld a,b cp 4 jr nc,PEDChangeDontDE_HL ex de,hl PEDChangeDontDE_HL: ex af,af' call CosInv call mul PED_Fertig: ret ;########################## EnemyPlayerAusrichten: ;Input: hl = Blickwinkel ix = typ call EnemyPlayerWinkelCalc ld (ix+1),a ret ;########################## EnemyPlayerWinkelCalc: ld d,(ix+5) ;x grob ld e,(ix+4) ;x fein xor a ld c,a EPA_RowDistCalc1: ld hl,(RowWorld) sbc hl,de jr nc,EPA_RowPos1 ld hl,(RowWorld) ex de,hl sbc hl,de inc a ld c,%11000000 EPA_RowPos1: push hl ;row dist EPA_ColDistCalc1: ld hl,(ColWorld) ld d,(ix+3) ;y grob ld e,(ix+2) ;y fein sbc hl,de jr nc,EPA_HL ld hl,(ColWorld) ex de,hl sbc hl,de ex af,af' ld a,c xor %01000000 ld c,a ex af,af' add a,2 EPA_HL: pop de ;de = RowDist push hl ;hl = ColDist ld (PlayerEnemyDistRow),de ld (PlayerEnemyDistCol),hl sbc hl,de pop hl jr c,EPA_HLok ;Optimize jr z,EPA_HLok ex de,hl add a,4 EPA_HLok: ld b,a sla l rl h sla l rl h sla l rl h sla l rl h sla l rl h ;*32 push bc call div_hl_by_de ;returns a = winkel pop bc ld (PlayerEnemyDistWinkel),a ex af,af' ld a,b or a ;0 jr z,EPACalcWay2 sub 3 jr c,EPACalcWay1 jr z,EPACalcWay2 dec a ;4 jr z,EPACalcWay1 sub 3 jr c,EPACalcWay2 ; jr z,EPACalcWay2 ;OK ;7 EPACalcWay1: ex af,af' jr EPACalcWayBoth EPACalcWay2: ex af,af' cpl add a,64 EPACalcWayBoth: add a,c ret ;########################## #ifdef EnableSprite EnemyRayCast: call PlayerEnemyAusrichten ld hl,SpriteArray push hl ld (SpriteArrayPointer),hl call RayCast pop hl push hl ld de,3 EnemyRayCastReplaceEnemys ld a,(hl) or a jr z,EnemyRayCastReturnEnemysEnd inc hl ld b,(hl) inc hl ld c,(hl) ld (bc),a add hl,de jr EnemyRayCastReplaceEnemys EnemyRayCastReturnEnemysEnd: pop hl ld e,5 EnemyRayCastSeeLoop: ld a,(hl) or a ret z add hl,de cp (ix) jr nz,EnemyRayCastSeeLoop dec hl ;x ld a,(hl) cp (ix+5) jr nz,EnemyRayCastSeeWarFalschePos1 dec hl ;y ld a,(hl) cp (ix+3) jr z,EnemyRayCastSeeSichtbar inc hl EnemyRayCastSeeWarFalschePos1: inc hl ;next type jr EnemyRayCastSeeLoop EnemyRayCastSeeSichtbar: inc a ; --> != Zero ret #else EnemyRayCast: ret #endif GetEnemyRandomDirection: ld b,255 call _IonRandom ld (ix+1),a ret KI_End: #endif