;============================================================================== ; Sprite Properties ;============================================================================== !SPRID = $B6 ; The sprite ID you are overwriting (HEX) !NbrTiles = 4 ; Number of tiles used in a frame !Harmless = 00 ; 00 = Sprite is Harmful, 01 = Sprite is Harmless !HVelocity = 00 ; Is your sprite going super fast? put 01 if it is !Health = 0 ; Number of Health the sprite have !Damage = 0 ; (08 is a whole heart), 04 is half heart !DeathAnimation = 00 ; 00 = normal death, 01 = no death animation !ImperviousAll = 00 ; 00 = Can be attack, 01 = attack will clink on it !SmallShadow = 00 ; 01 = small shadow, 00 = no shadow !Shadow = 00 ; 00 = don't draw shadow, 01 = draw a shadow !Palette = 0 ; Unused in this template (can be 0 to 7) !Hitbox = 0 ; 00 to 31, can be viewed in sprite draw tool !Persist = 00 ; 01 = your sprite continue to live offscreen !Statis = 00 ; 00 = is sprite is alive?, (kill all enemies room) !CollisionLayer = 00 ; 01 = will check both layer for collision !CanFall = 00 ; 01 sprite can fall in hole, 01 = can't fall !DeflectArrow = 00 ; 01 = deflect arrows !WaterSprite = 00 ; 01 = can only walk shallow water !Blockable = 00 ; 01 = can be blocked by link's shield? !Prize = 0 ; 00-15 = the prize pack the sprite will drop from !Sound = 00 ; 01 = Play different sound when taking damage !Interaction = 00 ; ?? No documentation !Statue = 00 ; 01 = Sprite is statue !DeflectProjectiles = 00 ; 01 = Sprite will deflect ALL projectiles !ImperviousArrow = 00 ; 01 = Impervious to arrows !ImpervSwordHammer = 00 ; 01 = Impervious to sword and hammer attacks !Boss = 00 ; 00 = normal sprite, 01 = sprite is a boss %Set_Sprite_Properties(Sprite_Poltergeist_Prep, Sprite_Poltergeist_Long); ;================================================================================================== ; Sprite Long Hook for that sprite ; -------------------------------------------------------------------------------------------------- ; This code can be left unchanged ; handle the draw code and if the sprite is active and should move or not ;================================================================================================== Sprite_Poltergeist_Long: { PHB : PHK : PLB JSR Sprite_Poltergeist_Draw ; Call the draw code LDA $E0 : CMP #$F0 : BNE .onscreen LDA.w SprMiscA, X : BEQ .SpriteIsNotActive STZ.w SprState, X ; kill the sprite if offscreen and activated .onscreen JSL Sprite_CheckActive ; Check if game is not paused BCC .SpriteIsNotActive ; Skip Main code is sprite is innactive JSR Sprite_Poltergeist_Main ; Call the main sprite code .SpriteIsNotActive PLB ; Get back the databank we stored previously RTL ; Go back to original code } ;================================================================================================== ; Sprite initialization ; -------------------------------------------------------------------------------------------------- ; this code only get called once perfect to initialize sprites substate or timers ; this code as soon as the room transitions/ overworld transition occurs ;================================================================================================== Sprite_Poltergeist_Prep: { PHB : PHK : PLB ; LDA #$00 : STA $0F60, X ; Persist LDA #$02 : STA $0E40, X ;1 tile by default LDA #$01 : STA.w SprAction, X ; by default it's a chair LDA.w SprSubtype, X : CMP #$10 : BNE .notPictureFrame STZ.w SprMiscA, X STZ.w SprAction, X JMP .done .notPictureFrame CMP #$11 : BNE .notAxe LDA #$07 : STA.w SprFrame, X LDA #$02 : STA.w SprAction, X LDA #$04 : STA $0E40, X BRA .done .notAxe CMP #$12 : BNE .notKnife LDA #15 : STA.w SprFrame, X LDA #$02 : STA.w SprAction, X BRA .done .notKnife CMP #$13 : BNE .notFork LDA #37 : STA.w SprFrame, X LDA #$02 : STA.w SprAction, X BRA .done .notFork CMP #$14 : BNE .notBed LDA #5 : STA.w SprFrame, X LDA #$01 : STA.w SprAction, X LDA #$06 : STA $0E40, X BRA .done .notBed CMP #$15 : BNE .notDoor LDA #36 : STA.w SprFrame, X LDA #$01 : STA.w SprAction, X LDA #$04 : STA $0E40, X LDA.w SprY, X : SEC : SBC #$0C : STA.w SprY, X LDA.w SprX, X : CLC : ADC #$08 : STA.w SprX, X BRA .done .notDoor LDA.w SprSubtype, X : AND #$08 : BNE .secondset ;2nd set LDA.w SprSubtype, X : CLC : ADC #23 : STA.w SprFrame, X BRA .done .secondset LDA.w SprSubtype, X : AND #$07 : CLC : ADC #30 : STA.w SprFrame, X LDA.w SprSubtype, X .done PLB RTL } ;================================================================================================== ; Sprite Main routines code ; -------------------------------------------------------------------------------------------------- ; This is the main local code of your sprite ; This contains all the Subroutines of your sprites you can add more below ;================================================================================================== ; Subtype: ; 00:chair ; 01:lantern ; 02:(peg switch looks ugly i got colors wrong i think) ; 03:pot ; 04:alt chair1 ; 05:alt chair2 ; 06:plate ; 07 ---- DO NOT USE WILL TURN SPRITE INTO OVERLORD ; 08:block ; 09:pillar ; 10:barrel ; 11:small vase from shelf ; 12:right wall window ; 13:left wall window ; 14:UNUSED ; 15 ---- DO NOT USE WILL TURN SPRITE INTO OVERLORD ; 16:PictureFrame ; 17:Axe ; 18:Knife ; 19:Fork ; 20:bed ; 21:Shutter door Sprite_Poltergeist_Main: { LDA.w SprAction, X : JSL UseImplicitRegIndexedLocalJumpTable dw PictureFrame dw Chair dw Axe dw SpawnerTester PictureFrame: { JSL Sprite_CheckDamageToPlayer REP #$20 JSR GetLinkDistance16bit : CMP #$0050 : BCS .notcloseenough SEP #$20 LDA #$01 : STA.w SprMiscA, X LDA #$02 : STA.w SprHeight, X .notcloseenough SEP #$20 LDA.w SprMiscA, X : BNE .chase RTS .chase %PlayAnimation(0, 3, 6) LDA #$0A JSL Sprite_ApplySpeedTowardsPlayer JSL Sprite_MoveLong + JSL Sprite_CheckDamageFromPlayer : BCC .noShatter JMP Shatter .noShatter RTS } GetLinkDistance16bit: { LDA $0FD8 ; Sprite X SEC : SBC $22 ; - Player X BPL + EOR #$FFFF : INC + STA $00 ; Distance X (ABS) LDA $0FDA ; Sprite Y SEC : SBC $20 ; - Player Y BPL + EOR #$FFFF : INC + ; Add it back to X Distance CLC : ADC $00 : STA $00 ; distance total X, Y (ABS) RTS } Chair: { JSL Sprite_CheckDamageToPlayer REP #$20 JSR GetLinkDistance16bit : CMP #$0050 : BCS .notcloseenough SEP #$20 LDA.w SprMiscA, X : BNE + LDA #$01 : STA.w SprMiscA, X + .notcloseenough SEP #$20 LDA.w SprMiscA, X : CMP #$01 : BNE + ; Prepare to raise in the air LDA.b #$20 : STA.w SprTimerA, X INC.w SprMiscA, X RTS + CMP #$02 : BNE + ; Prepare to raise in the air LDA.w SprTimerA, X : BNE .stillrising LDA.b #$10 : STA.w SprTimerA, X INC.w SprMiscA, X RTS .stillrising ; OPTIONAL DELAY THE INCREASING SPRHEIGHT WITH TIMER LDA.w SprTimerC, X : BNE .optionalTimer LDA #$02 : STA.w SprTimerC, X INC.w SprHeight, X .optionalTimer RTS + CMP #$03 : BNE + LDA.w SprTimerA, X : BNE .waitingdelay JSL Sprite_MoveLong JSL Sprite_CheckDamageToPlayer : BCS Shatter JSL Sprite_CheckDamageFromPlayer : BCS Shatter ;JSL Sprite_CheckTileCollision : BNE Shatter RTS + RTS .waitingdelay LDA #$28 JSL Sprite_ApplySpeedTowardsPlayer RTS } Shatter: { LDA.b #$A6 : STA $0E40, X LDA.b #$1F : JSL Sound_SetSfx2PanLong STZ $0DC0, X LDA.b #$04 : STA $0DB0, X LDA.b #$06 : STA $0DD0, X LDA.b #$1F : STA $0DF0, X LDA.b #$EC : STA $0E20, X LDA $0E40, X : CLC : ADC #$04 : STA $0E40, X STZ $0EF0, X LDA.b #$80 : STA $0DB0, X RTS } Axe: { JSL Sprite_CheckDamageToPlayer REP #$20 JSR GetLinkDistance16bit : CMP #$0050 : BCS .notcloseenough SEP #$20 LDA.w SprMiscA, X : BNE + LDA #$01 : STA.w SprMiscA, X + .notcloseenough SEP #$20 LDA.w SprMiscA, X : CMP #$01 : BNE + ; Prepare to raise in the air LDA.b #$20 : STA.w SprTimerA, X INC.w SprMiscA, X RTS + CMP #$02 : BNE + ; Prepare to raise in the air LDA.w SprTimerA, X : BNE .stillrising LDA.b #$10 : STA.w SprTimerA, X INC.w SprMiscA, X RTS .stillrising ; OPTIONAL DELAY THE INCREASING SPRHEIGHT WITH TIMER LDA.w SprTimerC, X : BNE .optionalTimer LDA #$02 : STA.w SprTimerC, X INC.w SprHeight, X .optionalTimer RTS + CMP #$03 : BNE + LDA.w SprSubtype, X CMP #$11 : BNE .notAxe JSR PlayAxe BRA .done .notAxe CMP #$12 : BNE .notKnife JSR PlayKnife BRA .done .notKnife JSR PlayFork .notFork .done LDA.w SprTimerA, X : BNE .waitingdelay JSL Sprite_MoveLong JSL Sprite_CheckDamageToPlayer : BCC .noShatter JMP Shatter JSL Sprite_CheckDamageFromPlayer : BCC .noShatter JMP Shatter JSL Sprite_CheckTileCollision : BEQ .noShatter JMP Shatter .noShatter RTS + RTS .waitingdelay LDA #$20 JSL Sprite_ApplySpeedTowardsPlayer RTS } PlayAxe: %PlayAnimation(7, 14, 6) RTS PlayFork: %PlayAnimation(37, 44, 6) RTS PlayKnife: %PlayAnimation(15, 22, 6) RTS SpawnerTester: { LDA.w SprTimerA, X : BEQ + RTS + LDA #$FF : STA.w SprTimerA, X LDA #$00 JSL Sprite_SpawnDynamically JSL Sprite_SetSpawnedCoords LDA.w SprMiscD, X : STA.w SprSubtype, Y INC.w SprMiscD, X ;LDA #$28 : STA.w SprY, X LDA #$01 : STA.w SprAction, Y ; by default it's a chair LDA.w SprSubtype, Y : CMP #$10 : BNE .notPictureFrame LDA #$00 STA.w SprMiscA, Y STA.w SprAction, Y BRA .done .notPictureFrame CMP #$11 : BNE .notAxe LDA #$07 : STA.w SprFrame, Y LDA #$02 : STA.w SprAction, Y BRA .done .notAxe CMP #$12 : BNE .notKnife LDA #15 : STA.w SprFrame, Y LDA #$02 : STA.w SprAction, Y BRA .done .notKnife CMP #$13 : BNE .notFork LDA #37 : STA.w SprFrame, Y LDA #$02 : STA.w SprAction, Y BRA .done .notFork CMP #$14 : BNE .notBed LDA #5 : STA.w SprFrame, Y LDA #$01 : STA.w SprAction, Y BRA .done .notBed CMP #$14 : BNE .notDoor LDA #36 : STA.w SprFrame, Y LDA #$01 : STA.w SprAction, Y BRA .done .notDoor LDA.w SprSubtype, Y : AND #$08 : BNE .secondset ;2nd set LDA.w SprSubtype, Y : CLC : ADC #23 : STA.w SprFrame, Y BRA .done .secondset LDA.w SprSubtype, Y : AND #$07 : CLC : ADC #30 : STA.w SprFrame, Y LDA.w SprSubtype, Y .done RTS } } ;================================================================================================== ; Sprite Draw code ; -------------------------------------------------------------------------------------------------- ; Draw the tiles on screen with the data provided by the sprite maker editor ;================================================================================================== Sprite_Poltergeist_Draw: LDA.w SprAction, X : CMP #$03 : BNE + RTS + JSL Sprite_PrepOamCoord LDA #$08 JSL Sprite_OAM_AllocateDeferToPlayer LDA $0DC0, X : CLC : ADC $0D90, X : TAY;Animation Frame LDA .start_index, Y : STA $06 PHX LDX .nbr_of_tiles, Y ;amount of tiles -1 LDY.b #$00 .nextTile PHX ; Save current Tile Index? TXA : CLC : ADC $06 ; Add Animation Index Offset PHA ; Keep the value with animation index offset? ASL A : TAX REP #$20 LDA $00 : CLC : ADC .x_offsets, X : STA ($90), Y AND.w #$0100 : STA $0E INY LDA $02 : CLC : ADC .y_offsets, X : STA ($90), Y CLC : ADC #$0010 : CMP.w #$0100 SEP #$20 BCC .on_screen_y LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way STA $0E .on_screen_y PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore) INY LDA .chr, X : STA ($90), Y INY LDA .properties, X : STA ($90), Y PHY TYA : LSR #2 : TAY LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer PLY : INY PLX : DEX : BPL .nextTile PLX LDA.w SprMiscA, X : BEQ .noshadow JSL Sprite_DrawShadow .noshadow RTS ;================================================================================================== ; Sprite Draw Generated Data ; -------------------------------------------------------------------------------------------------- ; This is where the generated Data for the sprite go ;================================================================================================== .start_index db $00, $02, $04, $06, $08, $09, $0F, $15, $16, $17, $18, $19, $1A, $1B, $1C, $1D, $1F, $20, $22, $23, $25, $26, $28, $29, $2A, $2B, $2C, $2D, $2E, $2F, $30, $31, $33, $35, $37, $39, $3B, $3F, $41, $42, $44, $45, $47, $48, $4A .nbr_of_tiles db 1, 1, 1, 1, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, 1, 0, 1, 0, 1, 0, 1, 0 .x_offsets dw -8, 8 dw -8, 8 dw -8, 8 dw -8, 8 dw 0 dw -8, 8, -8, 8, -8, 8 dw -4, 12, -4, 20, 4, 12 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 4, 4 dw 0 dw 0, 8 dw 0 dw 4, 4 dw 0 dw 8, 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0, 0 dw 0, 0 dw 4, 4 dw -4, -4 dw 4, 4 dw -8, 8, -8, 8 dw 4, 4 dw 0 dw 0, 8 dw 0 dw 4, 4 dw 0 dw 0, 8 dw 0 .y_offsets dw 0, 0 dw 0, 0 dw 0, 0 dw 0, 0 dw 0 dw -12, -12, 4, 4, 12, 12 dw -4, -4, 12, 12, 12, 12 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0, 8 dw 0 dw 4, 4 dw 0 dw 8, 0 dw 0 dw 4, 4 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0, -16 dw 8, -8 dw 0, 8 dw -12, 4 dw -12, 4 dw -4, -4, 12, 12 dw 8, 0 dw 0 dw 4, 4 dw 0 dw 0, 8 dw 0 dw 4, 4 dw 0 .chr db $02, $02 db $00, $00 db $02, $02 db $04, $04 db $2C db $0C, $0C, $0E, $0E, $1E, $1E db $0A, $0A, $2A, $2A, $2B, $2B db $20 db $24 db $22 db $26 db $20 db $24 db $22 db $26 db $06, $16 db $08 db $3A, $3B db $08 db $06, $16 db $08 db $3A, $3B db $08 db $42 db $40 db $44 db $46 db $60 db $62 db $64 db $66 db $6A, $4A db $6C, $4C db $6F, $7F db $4E, $4E db $4E, $4E db $48, $48, $68, $68 db $07, $17 db $28 db $3F, $3E db $28 db $07, $17 db $28 db $3E, $3F db $28 .properties db $3D, $7D db $3D, $7D db $3D, $7D db $3D, $7D db $3D db $3D, $7D, $3D, $7D, $3D, $7D db $3D, $7D, $3D, $7D, $3D, $7D db $39 db $39 db $39 db $39 db $F9 db $F9 db $F9 db $F9 db $39, $39 db $39 db $39, $39 db $B9 db $B9, $B9 db $F9 db $79, $79 db $79 db $3D db $3D db $39 db $3D db $3D db $3D db $39 db $3D db $3D, $3D db $3D, $3D db $3D, $3D db $3D, $BD db $7D, $FD db $3D, $7D, $3D, $7D db $B9, $B9 db $F9 db $79, $79 db $79 db $39, $39 db $39 db $39, $39 db $B9 .sizes db $02, $02 db $02, $02 db $02, $02 db $02, $02 db $02 db $02, $02, $02, $02, $02, $02 db $02, $02, $00, $00, $00, $00 db $02 db $02 db $02 db $02 db $02 db $02 db $02 db $02 db $00, $00 db $02 db $00, $00 db $02 db $00, $00 db $02 db $00, $00 db $02 db $02 db $02 db $02 db $02 db $02 db $02 db $02 db $02 db $02, $02 db $02, $02 db $00, $00 db $02, $02 db $02, $02 db $02, $02, $02, $02 db $00, $00 db $02 db $00, $00 db $02 db $00, $00 db $02 db $00, $00 db $02