diff --git a/src/actor.asm b/src/actor.asm index b774f2d3..3fcc49b6 100644 --- a/src/actor.asm +++ b/src/actor.asm @@ -21,6 +21,7 @@ .INCLUDE "actors/breakball.inc" .INCLUDE "actors/grub.inc" .INCLUDE "actors/orc.inc" +.INCLUDE "actors/solifuge.inc" .INCLUDE "avatar.inc" .INCLUDE "macros.inc" .INCLUDE "ppu.inc" @@ -62,6 +63,7 @@ .IMPORT FuncA_Actor_TickProjBreakbomb .IMPORT FuncA_Actor_TickProjBreakfire .IMPORT FuncA_Actor_TickProjBullet +.IMPORT FuncA_Actor_TickProjEgg .IMPORT FuncA_Actor_TickProjEmber .IMPORT FuncA_Actor_TickProjFireball .IMPORT FuncA_Actor_TickProjFireblast @@ -123,6 +125,7 @@ .IMPORT FuncA_Objects_DrawActorProjBreakbomb .IMPORT FuncA_Objects_DrawActorProjBreakfire .IMPORT FuncA_Objects_DrawActorProjBullet +.IMPORT FuncA_Objects_DrawActorProjEgg .IMPORT FuncA_Objects_DrawActorProjEmber .IMPORT FuncA_Objects_DrawActorProjFireball .IMPORT FuncA_Objects_DrawActorProjFireblast @@ -148,13 +151,13 @@ .IMPORT FuncA_Room_InitActorBadFlydrop .IMPORT FuncA_Room_InitActorBadGooRed .IMPORT FuncA_Room_InitActorBadLavaball -.IMPORT FuncA_Room_InitActorBadSolifuge .IMPORT FuncA_Room_InitActorBadToad .IMPORT FuncA_Room_InitActorBadWasp .IMPORT FuncA_Room_InitActorNpcChild .IMPORT FuncA_Room_InitActorNpcToddler .IMPORT FuncA_Room_InitActorProjBreakball .IMPORT FuncA_Room_InitActorProjBreakbomb +.IMPORT FuncA_Room_InitActorProjEgg .IMPORT FuncA_Room_InitActorProjFlamestrike .IMPORT FuncA_Room_InitActorProjSpine .IMPORT FuncA_Room_InitActorSmokeBlood @@ -163,6 +166,7 @@ .IMPORT FuncA_Room_InitActorSmokeWaterfall .IMPORT Func_InitActorBadGronta .IMPORT Func_InitActorBadOrc +.IMPORT Func_InitActorBadSolifuge .IMPORT Func_InitActorNpcOrc .IMPORT Func_InitActorProjAcid .IMPORT Func_InitActorProjAxe @@ -195,6 +199,7 @@ kBadJellyRadius = 5 kProjAxeRadius = 5 kProjBreakbombRadius = 3 kProjBulletRadius = 1 +kProjEggRadius = 3 kProjFireballRadius = 3 kProjFireblastRadius = 3 kProjFoodRadius = 1 @@ -517,7 +522,7 @@ _NoHit: d_byte BadRhino, 4 d_byte BadRodent, 2 d_byte BadSlime, 4 - d_byte BadSolifuge, 2 + d_byte BadSolifuge, kBadSolifugeBoundingBoxDown d_byte BadSpider, 8 d_byte BadToad, 9 d_byte BadVinebug, 7 @@ -536,6 +541,7 @@ _NoHit: d_byte ProjBreakbomb, kProjBreakbombRadius d_byte ProjBreakfire, 12 d_byte ProjBullet, kProjBulletRadius + d_byte ProjEgg, kProjEggRadius d_byte ProjEmber, 1 d_byte ProjFireball, kProjFireballRadius d_byte ProjFireblast, kProjFireblastRadius @@ -584,7 +590,7 @@ _NoHit: d_byte BadRhino, 8 d_byte BadRodent, 2 d_byte BadSlime, 2 - d_byte BadSolifuge, 8 + d_byte BadSolifuge, kBadSolifugeBoundingBoxDown d_byte BadSpider, 2 d_byte BadToad, 0 d_byte BadVinebug, 7 @@ -603,6 +609,7 @@ _NoHit: d_byte ProjBreakbomb, kProjBreakbombRadius d_byte ProjBreakfire, 8 d_byte ProjBullet, kProjBulletRadius + d_byte ProjEgg, kProjEggRadius d_byte ProjEmber, 3 d_byte ProjFireball, kProjFireballRadius d_byte ProjFireblast, kProjFireblastRadius @@ -651,7 +658,7 @@ _NoHit: d_byte BadRhino, 10 d_byte BadRodent, 2 d_byte BadSlime, 6 - d_byte BadSolifuge, 6 + d_byte BadSolifuge, kBadSolifugeBoundingBoxSide d_byte BadSpider, 6 d_byte BadToad, 7 d_byte BadVinebug, 5 @@ -670,6 +677,7 @@ _NoHit: d_byte ProjBreakbomb, kProjBreakbombRadius d_byte ProjBreakfire, 3 d_byte ProjBullet, kProjBulletRadius + d_byte ProjEgg, kProjEggRadius d_byte ProjEmber, 2 d_byte ProjFireball, kProjFireballRadius d_byte ProjFireblast, kProjFireblastRadius @@ -805,6 +813,7 @@ _TypeSpecificTick: d_entry table, ProjBreakbomb, FuncA_Actor_TickProjBreakbomb d_entry table, ProjBreakfire, FuncA_Actor_TickProjBreakfire d_entry table, ProjBullet, FuncA_Actor_TickProjBullet + d_entry table, ProjEgg, FuncA_Actor_TickProjEgg d_entry table, ProjEmber, FuncA_Actor_TickProjEmber d_entry table, ProjFireball, FuncA_Actor_TickProjFireball d_entry table, ProjFireblast, FuncA_Actor_TickProjFireblast @@ -958,7 +967,7 @@ _Finish: d_entry table, BadRhino, Func_InitActorWithFlags d_entry table, BadRodent, Func_InitActorDefault d_entry table, BadSlime, Func_InitActorWithFlags - d_entry table, BadSolifuge, FuncA_Room_InitActorBadSolifuge + d_entry table, BadSolifuge, Func_InitActorBadSolifuge d_entry table, BadSpider, Func_InitActorDefault d_entry table, BadToad, FuncA_Room_InitActorBadToad d_entry table, BadVinebug, Func_InitActorDefault @@ -977,6 +986,7 @@ _Finish: d_entry table, ProjBreakbomb, FuncA_Room_InitActorProjBreakbomb d_entry table, ProjBreakfire, Func_InitActorProjBreakfire d_entry table, ProjBullet, Func_InitActorProjBullet + d_entry table, ProjEgg, FuncA_Room_InitActorProjEgg d_entry table, ProjEmber, Func_InitActorProjEmber d_entry table, ProjFireball, Func_InitActorProjFireball d_entry table, ProjFireblast, Func_InitActorProjFireblast @@ -1073,6 +1083,7 @@ _Finish: d_entry table, ProjBreakbomb, FuncA_Objects_DrawActorProjBreakbomb d_entry table, ProjBreakfire, FuncA_Objects_DrawActorProjBreakfire d_entry table, ProjBullet, FuncA_Objects_DrawActorProjBullet + d_entry table, ProjEgg, FuncA_Objects_DrawActorProjEgg d_entry table, ProjEmber, FuncA_Objects_DrawActorProjEmber d_entry table, ProjFireball, FuncA_Objects_DrawActorProjFireball d_entry table, ProjFireblast, FuncA_Objects_DrawActorProjFireblast diff --git a/src/actor.inc b/src/actor.inc index b6c0a624..f72d761e 100644 --- a/src/actor.inc +++ b/src/actor.inc @@ -67,6 +67,7 @@ kMaxActors = 16 ProjBreakbomb ; a falling bomb shot by the city boss ProjBreakfire ; sweeps out horizontally from an exploding breakball ProjBullet ; shot by minigun machines + ProjEgg ; dropped by the lava boss; hatches into a BadSolifuge ProjEmber ; fire dropped by a hothead baddie ProjFireball ; shot by various bosses ProjFireblast ; shot by firefly baddies and blaster machines diff --git a/src/actors/dirt.inc b/src/actors/dirt.inc index d1b5d8df..8db8c892 100644 --- a/src/actors/dirt.inc +++ b/src/actors/dirt.inc @@ -26,6 +26,6 @@ ;;; * State4: Unused. ;;; Tile IDs for drawing dirt smoke actors. -kTileIdObjDirtFirst = $a9 +kTileIdObjDirtFirst = $94 ;;;=========================================================================;;; diff --git a/src/actors/egg.asm b/src/actors/egg.asm new file mode 100644 index 00000000..c8184a1a --- /dev/null +++ b/src/actors/egg.asm @@ -0,0 +1,138 @@ +;;;=========================================================================;;; +;;; Copyright 2022 Matthew D. Steele ;;; +;;; ;;; +;;; This file is part of Annalog. ;;; +;;; ;;; +;;; Annalog is free software: you can redistribute it and/or modify it ;;; +;;; under the terms of the GNU General Public License as published by the ;;; +;;; Free Software Foundation, either version 3 of the License, or (at your ;;; +;;; option) any later version. ;;; +;;; ;;; +;;; Annalog is distributed in the hope that it will be useful, but WITHOUT ;;; +;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;; +;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;; +;;; for more details. ;;; +;;; ;;; +;;; You should have received a copy of the GNU General Public License along ;;; +;;; with Annalog. If not, see . ;;; +;;;=========================================================================;;; + +.INCLUDE "../actor.inc" +.INCLUDE "../macros.inc" +.INCLUDE "../platform.inc" +.INCLUDE "../ppu.inc" +.INCLUDE "egg.inc" +.INCLUDE "solifuge.inc" + +.IMPORT FuncA_Actor_ApplyGravityWithTerminalVelocity +.IMPORT FuncA_Actor_HarmAvatarIfCollision +.IMPORT FuncA_Actor_IsInRoomBounds +.IMPORT FuncA_Actor_SetPointAboveOrBelowActor +.IMPORT FuncA_Objects_Draw1x1Actor +.IMPORT Func_FindEmptyActorSlot +.IMPORT Func_InitActorBadSolifuge +.IMPORT Func_InitActorDefault +.IMPORT Func_InitActorSmokeExplosion +.IMPORT Func_IsPointInAnySolidPlatform +.IMPORT Func_PointHitsTerrain +.IMPORT Func_SetActorCenterToPoint +.IMPORT Func_SetPointToActorCenter +.IMPORT Ram_ActorType_eActor_arr +.IMPORT Ram_PlatformType_ePlatform_arr +.IMPORTZP Zp_PointY_i16 + +;;;=========================================================================;;; + +;;; The terminal velocity for a falling egg, in pixels per frame. +kProjEggTerminalVelocity = 4 + +;;; The OBJ palette number used for solifuge egg projectile actors. +kPaletteObjEgg = 1 + +;;;=========================================================================;;; + +.SEGMENT "PRGA_Room" + +;;; Initializes the specified actor as a solifuge egg projectile. +;;; @prereq The actor's pixel position has already been initialized. +;;; @param X The actor index. +;;; @preserve X +.EXPORT FuncA_Room_InitActorProjEgg +.PROC FuncA_Room_InitActorProjEgg + ldy #eActor::ProjEgg ; param: actor type + jmp Func_InitActorDefault ; preserves X +.ENDPROC + +;;;=========================================================================;;; + +.SEGMENT "PRGA_Actor" + +;;; Performs per-frame updates for a solifuge egg projectile actor. +;;; @param X The actor index. +;;; @preserve X +.EXPORT FuncA_Actor_TickProjEgg +.PROC FuncA_Actor_TickProjEgg + jsr FuncA_Actor_HarmAvatarIfCollision ; preserves X + ;; Remove the egg if it somehow falls out of the room without hitting a + ;; solid platform or terrain. + jsr FuncA_Actor_IsInRoomBounds ; preserves X, returns C + bcc _Remove + ;; We want to hatch the egg while its center is still in the empty terrain + ;; block above the solid terrain that it hits, so check far enough below + ;; the center of the egg to ensure that the center of the egg won't be + ;; inside the solid terrain next frame. + lda #kProjEggTerminalVelocity + jsr FuncA_Actor_SetPointAboveOrBelowActor ; preserves X + ;; If the egg lands on a solid platform or terrain, it will hatch or break. + jsr Func_IsPointInAnySolidPlatform ; preserves X, returns C and Y + bcs _HitSolidPlatform + jsr Func_PointHitsTerrain ; preserves X, returns C + bcs _Hatch + ;; Otherwise, keep falling. + lda #kProjEggTerminalVelocity ; param: terminal velocity + jmp FuncA_Actor_ApplyGravityWithTerminalVelocity ; preserves X +_HitSolidPlatform: + ;; If the egg hits a Harm or Kill platform, just destroy the egg. + ;; Otherwise, hatch the egg. + lda Ram_PlatformType_ePlatform_arr, y + cmp #kFirstHarmfulPlatformType + bge _Break +_Hatch: + jsr Func_SetPointToActorCenter ; preserves X + ;; Align the point to kBadSolifugeBoundingBoxDown pixels above this block. + lda Zp_PointY_i16 + 0 + and #$f0 + ora #$10 - kBadSolifugeBoundingBoxDown + sta Zp_PointY_i16 + 0 + ;; Spawn a solifuge baddie actor at the point position. + stx T0 ; egg actor index + jsr Func_FindEmptyActorSlot ; preserves T0+, returns C and X + bcs @noSpawn + jsr Func_SetActorCenterToPoint ; preserves X + jsr Func_InitActorBadSolifuge + @noSpawn: + ldx T0 ; egg actor index +_Break: + ;; TODO: play a sound for the egg breaking/hatching + jmp Func_InitActorSmokeExplosion ; preserves X +_Remove: + lda #eActor::None + sta Ram_ActorType_eActor_arr, x + rts +.ENDPROC + +;;;=========================================================================;;; + +.SEGMENT "PRGA_Objects" + +;;; Draws a solifuge egg projectile actor. +;;; @param X The actor index. +;;; @preserve X +.EXPORT FuncA_Objects_DrawActorProjEgg +.PROC FuncA_Objects_DrawActorProjEgg + lda #kTileIdObjProjEgg ; param: tile ID + ldy #kPaletteObjEgg ; param: palette + jmp FuncA_Objects_Draw1x1Actor ; preserves X +.ENDPROC + +;;;=========================================================================;;; diff --git a/src/actors/egg.inc b/src/actors/egg.inc new file mode 100644 index 00000000..25700ea9 --- /dev/null +++ b/src/actors/egg.inc @@ -0,0 +1,30 @@ +;;;=========================================================================;;; +;;; Copyright 2022 Matthew D. Steele ;;; +;;; ;;; +;;; This file is part of Annalog. ;;; +;;; ;;; +;;; Annalog is free software: you can redistribute it and/or modify it ;;; +;;; under the terms of the GNU General Public License as published by the ;;; +;;; Free Software Foundation, either version 3 of the License, or (at your ;;; +;;; option) any later version. ;;; +;;; ;;; +;;; Annalog is distributed in the hope that it will be useful, but WITHOUT ;;; +;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;; +;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;; +;;; for more details. ;;; +;;; ;;; +;;; You should have received a copy of the GNU General Public License along ;;; +;;; with Annalog. If not, see . ;;; +;;;=========================================================================;;; + +;;; State bytes for solifuge egg projectiles: +;;; * Flags: Unused. +;;; * State1: Unused. +;;; * State2: Unused. +;;; * State3: Unused. +;;; * State4: Unused + +;;; The tile ID for drawing solifuge egg projectile actors. +kTileIdObjProjEgg = $99 + +;;;=========================================================================;;; diff --git a/src/actors/solifuge.asm b/src/actors/solifuge.asm index 6568bab6..28f6735b 100644 --- a/src/actors/solifuge.asm +++ b/src/actors/solifuge.asm @@ -17,6 +17,7 @@ ;;; with Annalog. If not, see . ;;; ;;;=========================================================================;;; +.INCLUDE "../actor.inc" .INCLUDE "../macros.inc" .INCLUDE "../oam.inc" .INCLUDE "../ppu.inc" @@ -26,11 +27,13 @@ .IMPORT FuncA_Actor_AccelerateForward .IMPORT FuncA_Actor_ApplyGravity +.IMPORT FuncA_Actor_CenterHitsTerrainOrSolidPlatform .IMPORT FuncA_Actor_ClampVelX .IMPORT FuncA_Actor_FaceTowardsAvatar .IMPORT FuncA_Actor_GetRoomBlockRow .IMPORT FuncA_Actor_HarmAvatarIfCollision .IMPORT FuncA_Actor_IsAvatarWithinHorzDistance +.IMPORT FuncA_Actor_IsAvatarWithinVertDistances .IMPORT FuncA_Actor_IsPointInRoomBounds .IMPORT FuncA_Actor_LandOnTerrain .IMPORT FuncA_Actor_MovePointTowardVelXDir @@ -39,8 +42,8 @@ .IMPORT Func_GetTerrainColumnPtrForPointX .IMPORT Func_InitActorDefault .IMPORT Func_InitActorSmokeExplosion -.IMPORT Func_PointHitsTerrain .IMPORT Func_SetPointToActorCenter +.IMPORT Ram_ActorFlags_bObj_arr .IMPORT Ram_ActorPosY_i16_0_arr .IMPORT Ram_ActorPosY_i16_1_arr .IMPORT Ram_ActorState1_byte_arr @@ -56,7 +59,7 @@ ;;;=========================================================================;;; ;;; How fast a solifuge baddie can move horizontally, in subpixels per frame. -kSolifugeMaxSpeedX = $1c0 +kSolifugeMaxSpeedX = $180 ;;; How many pixels in front of its center a solifuge baddie actor checks for ;;; solid terrain to see if it needs to stop. @@ -84,13 +87,17 @@ kPaletteObjSolifuge = 0 ;;;=========================================================================;;; -.SEGMENT "PRGA_Room" +.SEGMENT "PRG8" ;;; Initializes a solifuge baddie actor. ;;; @prereq The actor's pixel position has already been initialized. ;;; @param X The actor index. ;;; @preserve X -.EXPORT FuncA_Room_InitActorBadSolifuge := Func_InitActorDefault +.EXPORT Func_InitActorBadSolifuge +.PROC Func_InitActorBadSolifuge + ldy #eActor::BadSolifuge ; param: actor type + jmp Func_InitActorDefault ; preserves X +.ENDPROC ;;;=========================================================================;;; @@ -120,8 +127,7 @@ _AlreadyJumping: _Steamed: jsr FuncA_Actor_ApplyGravity ; preserves X ;; If the solifuge hits the ceiling, kill it. - jsr Func_SetPointToActorCenter ; preserves X - jsr Func_PointHitsTerrain ; preserves X, returns C + jsr FuncA_Actor_CenterHitsTerrainOrSolidPlatform ; preserves X, returns C bcc @noHitCeiling ;; TODO: play a sound jmp Func_InitActorSmokeExplosion ; preserves X @@ -156,7 +162,12 @@ _MaybeJumpAtAvatar: sta Ram_ActorVelY_i16_1_arr, x @done: _ChaseAvatar: + ldy #$3c ; param: distance below avatar + lda #$0c ; param: distance above avatar + jsr FuncA_Actor_IsAvatarWithinVertDistances ; preserves X, returns C + bcc @noChase jsr FuncA_Actor_FaceTowardsAvatar ; preserves X + @noChase: lda #kSolifugeHorzAccel ; param: acceleration jsr FuncA_Actor_AccelerateForward ; preserves X ldya #kSolifugeMaxSpeedX ; param: max speed @@ -168,6 +179,7 @@ _StopIfBlockedHorz: jsr FuncA_Actor_IsPointInRoomBounds ; preserves X, returns C bcc @blocked jsr Func_GetTerrainColumnPtrForPointX ; preserves X + ;; TODO: also check terrain at corners of bounding box (not ground level) ldy Ram_ActorState2_byte_arr, x ; grounded room block row ;; Check the wall in front of the solifuge (at ground level). lda (Zp_TerrainColumn_u8_arr_ptr), y @@ -180,6 +192,10 @@ _StopIfBlockedHorz: bge @done ; floor is solid @blocked: jsr FuncA_Actor_ZeroVelX ; preserves X + ;; TODO: factor this out into a shared actor function + lda Ram_ActorFlags_bObj_arr, x + eor #bObj::FlipH + sta Ram_ActorFlags_bObj_arr, x @done: rts .ENDPROC diff --git a/src/actors/solifuge.inc b/src/actors/solifuge.inc index 4440ded6..d8a7fe3e 100644 --- a/src/actors/solifuge.inc +++ b/src/actors/solifuge.inc @@ -35,4 +35,10 @@ Jumping = %01000000 ; if set, the solifuge is jumping .ENDSCOPE +;;; How far a solifuge baddie actor's bounding box extends in each direction +;;; from the actor's center position. +kBadSolifugeBoundingBoxUp = 2 +kBadSolifugeBoundingBoxDown = 8 +kBadSolifugeBoundingBoxSide = 6 + ;;;=========================================================================;;; diff --git a/src/boss.asm b/src/boss.asm index bbf4e84d..e3d0225a 100644 --- a/src/boss.asm +++ b/src/boss.asm @@ -458,14 +458,22 @@ _Loop: rts _MaybeExpireActor: lda Ram_ActorType_eActor_arr, x + ;; Common boss projectiles: cmp #eActor::ProjFireball beq _ExpireFireball cmp #eActor::ProjBreakfire beq _ExpireBreakfire + ;; Temple boss projectiles: cmp #eActor::ProjBreakball beq _ExpireBreakball + ;; Lava boss projectiles: + cmp #eActor::ProjEgg + beq _ExpireEgg cmp #eActor::ProjFlamestrike beq _ExpireFlamestrike + cmp #eActor::BadSolifuge + beq _ExpireSolifuge + ;; City boss projectiles: cmp #eActor::ProjSpine beq _ExpireSpine cmp #eActor::ProjBreakbomb @@ -480,6 +488,8 @@ _ExpireBreakfire: lda #$c0 ; param: angle ($c0 = up) jmp Func_InitActorSmokeParticle ; preserves X _ExpireBreakball: +_ExpireEgg: +_ExpireSolifuge: jmp Func_InitActorSmokeExplosion ; preserves X _ExpireFlamestrike: lda #eActor::None diff --git a/src/chr.asm b/src/chr.asm index 6d6553ee..91ab71cd 100644 --- a/src/chr.asm +++ b/src/chr.asm @@ -31,6 +31,7 @@ .INCLUDE "actors/crawler.inc" .INCLUDE "actors/dirt.inc" .INCLUDE "actors/duck.inc" +.INCLUDE "actors/egg.inc" .INCLUDE "actors/ember.inc" .INCLUDE "actors/fireball.inc" .INCLUDE "actors/firefly.inc" @@ -1126,7 +1127,8 @@ _chr_begin: chr_inc "ember", kTileIdObjEmber chr_res $01 chr_inc "cannon", kTileIdObjCannonFirst - chr_res $08 + chr_res $06 + chr_inc "dirt", kTileIdObjDirtFirst chr_inc "upgrade_oprest", kTileIdObjUpgradeOpRestFirst chr_res $08 chr_inc "boss_garden_eye_white", kTileIdObjBossGardenEyeWhiteFirst @@ -1135,7 +1137,10 @@ _chr_begin: chr_inc "platform_crypt_bricks", kTileIdObjPlatformCryptBricksFirst chr_inc "boss_crypt_pupil", kTileIdObjBossCryptPupilFirst chr_inc "fireball", kTileIdObjFireballFirst - chr_res $1c + chr_inc "boulder", kTileIdObjBoulderFirst + chr_inc "crane", kTileIdObjCraneFirst + chr_res $08 + chr_inc "boss_mine_eye", kTileIdObjBossMineEyeFirst chr_inc "crusher", kTileIdObjCrusherFirst chr_inc "winch", kTileIdObjWinchFirst chr_inc "grenade", kTileIdObjGrenadeFirst @@ -1159,21 +1164,22 @@ _chr_begin: chr_inc "boiler_flame", kTileIdObjBoilerFlameFirst chr_inc "bullet", kTileIdObjBulletFirst chr_inc "launcher_horz", kTileIdObjLauncherHorzFirst - chr_inc "boulder", kTileIdObjBoulderFirst + chr_inc "dirt", kTileIdObjDirtFirst + chr_res $02 chr_inc "blaster", kTileIdObjBlasterFirst - chr_res $01 + chr_inc "proj_egg", kTileIdObjProjEgg chr_inc "fireblast", kTileIdObjFireblastFirst chr_inc "platform_city_walls", kTileIdObjPlatformCityWalls chr_inc "outbreak_obj", kTileIdObjOutbreakFirst - chr_inc "dirt", kTileIdObjDirtFirst + chr_res $02 chr_inc "breakfire", kTileIdObjBreakfireFirst - chr_inc "crane", kTileIdObjCraneFirst + chr_res $08 chr_inc "proj_spine", kTileIdObjProjSpineFirst chr_inc "valve", kTileIdObjValveFirst chr_inc "fireball", kTileIdObjFireballFirst chr_inc "breakball", kTileIdObjBreakballFirst chr_inc "platform_volcanic", kTileIdObjPlatformVolcanicFirst - chr_inc "boss_mine_eye", kTileIdObjBossMineEyeFirst + chr_inc "bad_spider", kTileIdObjBadSpiderFirst chr_inc "boss_lava_jaws", kTileIdObjBossLavaJawsFirst chr_inc "flamestrike", kTileIdObjFlamestrikeFirst chr_inc "minigun_vert", kTileIdObjMinigunVertFirst @@ -1272,9 +1278,9 @@ _chr_begin: chr_inc "upgrade_opskip", kTileIdObjUpgradeOpSkipFirst chr_res $06 chr_inc "bad_grub", kTileIdObjBadGrubFirst - chr_res $08 + chr_res $20 chr_inc "crane", kTileIdObjCraneFirst - chr_res $28 + chr_res $10 chr_inc "child_stand", kTileIdObjChildStandFirst END_CHR_BANK .ENDPROC @@ -1356,9 +1362,11 @@ _chr_begin: chr_inc "fireblast", kTileIdObjFireblastFirst chr_inc "bad_grub", kTileIdObjBadGrubFirst chr_inc "bad_wasp", kTileIdObjBadWaspFirst - chr_inc "crane", kTileIdObjCraneFirst + chr_res $08 chr_inc "bad_firefly", kTileIdObjBadFireflyFirst - chr_res $14 + chr_res $08 + chr_inc "crane", kTileIdObjCraneFirst + chr_res $04 chr_inc "bad_fish", kTileIdObjBadFishFirst chr_res $20 END_CHR_BANK diff --git a/src/machines/crane.inc b/src/machines/crane.inc index c8aa56f4..dc71723f 100644 --- a/src/machines/crane.inc +++ b/src/machines/crane.inc @@ -34,6 +34,6 @@ kTileIdBgDiagramCraneFirst = $f0 kTileIdBgDiagramTrolleyFirst = $e0 ;;; Various OBJ tile IDs used for drawing crane/trolley machines. -kTileIdObjCraneFirst = $b0 +kTileIdObjCraneFirst = $c8 ;;;=========================================================================;;; diff --git a/src/platform.inc b/src/platform.inc index e0a35250..3a1a1e40 100644 --- a/src/platform.inc +++ b/src/platform.inc @@ -35,6 +35,10 @@ kMaxPlatforms = 16 ;;; Platform types greater than or equal to this are solid. kFirstSolidPlatformType = ePlatform::Solid +;;; Platform types greater than or equal to this will harm or kill the player +;;; avatar on contact. +kFirstHarmfulPlatformType = ePlatform::Harm + ;;;=========================================================================;;; ;;; Describes a platform's initial size and position. diff --git a/src/platforms/crate.inc b/src/platforms/crate.inc index a2ea9366..e80028b7 100644 --- a/src/platforms/crate.inc +++ b/src/platforms/crate.inc @@ -24,7 +24,7 @@ kTileIdObjCrateChainHalf = kTileIdObjAnchorFirst + 1 kTileIdObjCrateAnchor = kTileIdObjAnchorFirst + 2 ;;; OBJ tile IDs for drawing boulder platforms. -kTileIdObjBoulderFirst = $94 +kTileIdObjBoulderFirst = $c4 ;;; OBJ tile IDs for drawing crate platforms. kTileIdObjCrateFirst = $7c diff --git a/src/rooms/boss_lava.asm b/src/rooms/boss_lava.asm index 449b8b08..b031a2b3 100644 --- a/src/rooms/boss_lava.asm +++ b/src/rooms/boss_lava.asm @@ -59,6 +59,7 @@ .IMPORT FuncA_Objects_MoveShapeRightByA .IMPORT FuncA_Objects_MoveShapeUpByA .IMPORT FuncA_Objects_SetShapePosToPlatformTopLeft +.IMPORT FuncA_Room_InitActorProjEgg .IMPORT FuncA_Room_InitActorProjFlamestrike .IMPORT FuncA_Room_InitBoss .IMPORT FuncA_Room_MachineBoilerReset @@ -204,6 +205,9 @@ Ppu_BossBodyAttrs = Ppu_Nametable3_sName + sName::Attrs_u8_arr64 + \ ;;; Modes that the boss in this room can be in. .ENUM eBossMode Dead + EggPrepare ; move into position to drop an egg + EggDrop ; drop an egg + EggWait ; wait for the egg to hatch and the solifuge killed FiresprayPrepare ; move into position to shoot a spray of fireballs FiresprayWindup ; open jaws before shooting a spray of fireballs FiresprayShoot ; shoot a spray of fireballs @@ -508,6 +512,7 @@ _CheckForHitTail: lda #eActor::ProjFireblast ; param: actor type jsr Func_FindActorWithType ; returns C and X bcs @done ; no fireblast found + ;; TODO: Check if the fireblast has hit a solifuge. ;; Check if the fireblast has hit the tail. jsr Func_SetPointToActorCenter ; preserves X ldy #kBossTailPlatformIndex ; param: platform index @@ -547,6 +552,9 @@ _CheckMode: D_TABLE_HI table, _JumpTable_ptr_1_arr D_TABLE .enum, eBossMode d_entry table, Dead, Func_Noop + d_entry table, EggPrepare, _BossEggPrepare + d_entry table, EggDrop, _BossEggDrop + d_entry table, EggWait, _BossEggWait d_entry table, FiresprayPrepare, _BossFiresprayPrepare d_entry table, FiresprayWindup, _BossFiresprayWindup d_entry table, FiresprayShoot, _BossFiresprayShoot @@ -558,6 +566,49 @@ _CheckMode: d_entry table, Scuttling, _BossScuttling D_END .ENDREPEAT +_BossEggPrepare: + jsr FuncC_Boss_Lava_BossCloseJaws + ;; Wait until the boss is in position. + jsr FuncC_Boss_Lava_BossMoveTowardGoal ; sets C when goal is reached + bcc @done + ;; Change modes to drop an egg. + lda #eBossMode::EggDrop + sta Zp_RoomState + sState::Current_eBossMode + @done: + rts +_BossEggDrop: + ;; Wait until the boss's jaws are fully open. + jsr FuncC_Boss_Lava_BossOpenJaws ; sets Z when jaws are fully open + bne @done + ;; Drop an egg. + lda #kBossHeightPx / 2 + kTileHeightPx / 2 ; param: offset + jsr FuncC_Boss_Lava_SetPointBelowBossCenter + jsr Func_FindEmptyActorSlot ; returns C and X + bcs @done + jsr Func_SetActorCenterToPoint ; preserves X + jsr FuncA_Room_InitActorProjEgg + ;; Change modes to wait for the egg to hatch and the solifuge be killed. + lda #eBossMode::EggWait + sta Zp_RoomState + sState::Current_eBossMode + @done: + rts +_BossEggWait: + jsr FuncC_Boss_Lava_BossCloseJaws + ;; Wait until no egg or solifuge exists. + ldx #kMaxActors - 1 + @loop: + lda Ram_ActorType_eActor_arr, x + cmp #eActor::ProjEgg + beq @done + cmp #eActor::BadSolifuge + beq @done + dex + .assert kMaxActors <= $80, error + bpl @loop + ;; Switch modes. + jmp _StartFirespray + @done: + rts _BossFiresprayPrepare: jsr FuncC_Boss_Lava_BossCloseJaws ;; Wait until the boss is in position. @@ -614,10 +665,8 @@ _BossFlamestrikeShoot: lda #70 sta Zp_RoomState + sState::BossCooldown_u8 ;; Shoot a flamestrike projectile. - ldy #kBossBodyPlatformIndex ; param: platform index - jsr Func_SetPointToPlatformCenter lda #kBossHeightPx / 2 - 1 ; param: offset - jsr Func_MovePointDownByA + jsr FuncC_Boss_Lava_SetPointBelowBossCenter jsr Func_FindEmptyActorSlot ; returns C and X bcs @done jsr Func_SetActorCenterToPoint ; preserves X @@ -716,10 +765,8 @@ _BossFiresprayShoot: and #$07 bne @done ;; Shoot a fireball. - ldy #kBossBodyPlatformIndex ; param: platform index - jsr Func_SetPointToPlatformCenter lda #kBossHeightPx / 2 + kTileHeightPx / 2 ; param: offset - jsr Func_MovePointDownByA + jsr FuncC_Boss_Lava_SetPointBelowBossCenter jsr Func_FindEmptyActorSlot ; returns C and X bcs @done jsr Func_SetActorCenterToPoint ; preserves X @@ -753,22 +800,40 @@ _BossScuttling: lda #kBossScuttleCooldown sta Zp_RoomState + sState::BossCooldown_u8 dec Zp_RoomState + sState::BossModeParam_byte - beq _StartFlamestrike + beq @attack lda #60 sta Zp_RoomState + sState::BossCooldown_u8 bne _StartNextScuttle ; unconditional + @attack: + jsr Func_GetRandomByte ; returns N + bmi _StartEgg + bpl _StartFlamestrike ; unconditional _StartFlamestrike: - ;; Choose a random valid position for firing a flamestrike. + ;; Choose a random valid position for firing a flamestrike (Y is 2, and X + ;; is in in the range 3-6). + lda #2 + sta Zp_RoomState + sState::BossGoalY_u8 jsr Func_GetRandomByte ; returns A - and #$03 + mod #4 add #3 sta Zp_RoomState + sState::BossGoalX_u8 - lda #2 - sta Zp_RoomState + sState::BossGoalY_u8 ;; Change modes to move to the firing position and shoot a flamestrike. lda #eBossMode::FlamestrikePrepare sta Zp_RoomState + sState::Current_eBossMode rts +_StartEgg: + ;; Choose a random valid position for dropping an egg (Y is 0, and X is in + ;; in the range 4-5). + lda #0 + sta Zp_RoomState + sState::BossGoalY_u8 + jsr Func_GetRandomByte ; returns A + mod #2 + add #4 + sta Zp_RoomState + sState::BossGoalX_u8 + ;; Change modes to move to the dropping position and drop an egg. + lda #eBossMode::EggPrepare + sta Zp_RoomState + sState::Current_eBossMode + rts .ENDPROC ;;; Moves the boss towards its goal position (as specified by BossGoalX_u8 and @@ -841,6 +906,17 @@ _StartFlamestrike: rts .ENDPROC +;;; Sets Zp_PointX_i16 to the horizontal center of the boss, and sets +;;; Zp_PointY_i16 to a position A pixels below the vertical center of the boss. +;;; @param A How many pixels below the center of the boss to set the point. +.PROC FuncC_Boss_Lava_SetPointBelowBossCenter + pha ; offset + ldy #kBossBodyPlatformIndex ; param: platform index + jsr Func_SetPointToPlatformCenter + pla ; param: offset + jmp Func_MovePointDownByA +.ENDPROC + ;;; Draw function for the BossLava room. ;;; @prereq PRGA_Objects is loaded. .PROC FuncC_Boss_Lava_DrawRoom diff --git a/src/rooms/boss_mine.asm b/src/rooms/boss_mine.asm index 255bcb05..dc5a075d 100644 --- a/src/rooms/boss_mine.asm +++ b/src/rooms/boss_mine.asm @@ -79,7 +79,7 @@ .IMPORT Func_ShakeRoom .IMPORT Ppu_ChrBgAnimB4 .IMPORT Ppu_ChrBgBossStatic -.IMPORT Ppu_ChrObjBoss2 +.IMPORT Ppu_ChrObjBoss1 .IMPORT Ram_MachineGoalHorz_u8_arr .IMPORT Ram_MachineGoalVert_u8_arr .IMPORT Ram_MachineStatus_eMachine_arr @@ -316,7 +316,7 @@ kBossSubsequentShootCooldown = 45 d_addr TerrainData_ptr, _TerrainData d_byte NumMachines_u8, 2 d_addr Machines_sMachine_arr_ptr, _Machines_sMachine_arr - d_byte Chr18Bank_u8, <.bank(Ppu_ChrObjBoss2) + d_byte Chr18Bank_u8, <.bank(Ppu_ChrObjBoss1) d_addr Ext_sRoomExt_ptr, _Ext_sRoomExt D_END _Ext_sRoomExt: diff --git a/src/rooms/boss_mine.inc b/src/rooms/boss_mine.inc index 95d21eed..04ce99fe 100644 --- a/src/rooms/boss_mine.inc +++ b/src/rooms/boss_mine.inc @@ -23,7 +23,7 @@ kTileIdBgAnimWyrmFirst = $70 kTileIdBgTerrainConveyorFirst = $b8 ;;; OBJ tile IDs for drawing the mine boss. -kTileIdObjBossMineEyeFirst = $c8 +kTileIdObjBossMineEyeFirst = $d8 ;;; The OBJ palette number to use for drawing the mine boss's eye. kPaletteObjBossMineEye = 1 diff --git a/src/tiles/proj_axe.ahi b/src/tiles/proj_axe.ahi index d397c6f2..873d9961 100644 --- a/src/tiles/proj_axe.ahi +++ b/src/tiles/proj_axe.ahi @@ -1,6 +1,6 @@ ahi1 f0 p1 i1 w16 h16 -;0;54;ECEEEC;FF0;FF0;982220;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0 +;0;FF0;ECEEEC;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0 0000000000013130 0000000000133310 diff --git a/src/tiles/proj_egg.ahi b/src/tiles/proj_egg.ahi new file mode 100644 index 00000000..70815cd3 --- /dev/null +++ b/src/tiles/proj_egg.ahi @@ -0,0 +1,12 @@ +ahi1 f0 p1 i1 w8 h8 + +;0;982220;ECEEEC;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0;FF0 + +00333300 +03233230 +02133120 +33133133 +33333333 +02333320 +03233230 +00333300