Mgamerz

MMBN3 White Boss Remix Plantman

Jan 2nd, 2017
494
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;Mgamerz Enhanced Enemies Mod v0.001
  2. ;12/17/2016
  3. ;Apply to MMBN3 ENGLISH WHITE version only! Apply with ARMIPS:
  4. ;armips filename.asm
  5.  
  6. input   equ whitevanilla.gba    ; Put the name of your ROM here
  7.  
  8. fspace equ 0x800000; Put the ROM free space offset here
  9.  
  10. .gba
  11. .open input,output.gba,8000000h
  12.  
  13. rngaddress EQU 0x080016a2|1b
  14. timestopchipcall EQU 08008E54h
  15. GetPlayer EQU 0x080013E0
  16. RecoveryChipRoutine EQU 0x80ADB04
  17. SpawnObject EQU 0x08003084
  18. ;FieldConfiguration EQU 0x
  19. SetPanelTeam EQU 0x0800B7C4
  20. PlaySound EQU 0x080005B8
  21. CalculateAIConstantsAddress EQU 0x080AEDBC
  22. GetPanelType EQU 0x0800B4F2
  23. SetInvincible EQU 0x080012B4
  24. SpawnLance EQU 0x080DE69E
  25. SpawnEnemyBoomer EQU 0x080DB2D4
  26. SpawnSnake EQU 0x080DD954
  27. SetPanelType EQU 0x0800B790
  28. GetPanelTeam EQU 0x0800BF06
  29. //Impacts
  30. FlinchAndInvisImpact EQU 0x3
  31. FlinchImpact EQU 0x1
  32. SuperArmorImpact EQU 0x0
  33.  
  34. ;Plantman
  35. plantmanPostVinesDelayRoutine EQU 0x080C1D33
  36. plantmanVinesEndingIndex EQU 0x4 ;Multiply index by 4 - default 2 indices (0, 4), now has 0=chooser, starting at 4 for attacks.
  37.  
  38. ;Flashman Chips
  39. flashmanchipcount EQU 1h
  40. flashmanChipHookAddress EQU 0x080B6726
  41.  
  42. gutsmanChipHookAddress EQU 0x080B8592
  43. gutsmanZPunchHookAddress EQU 0x080B84C6
  44. gutsmanChipCount EQU 4h
  45. gutsmanZPunchChipCount EQU 3h
  46. gutsmanMovesBeforeZPunch EQU 6h
  47.  
  48. teamfamily EQU 3Fh
  49. areafamily EQU 0h
  50. stagefamily EQU 4h
  51. trumpyfamily EQU 26h
  52. sensorfamily EQU 3Eh
  53. grabbackfamily EQU 15h
  54. mpchipfamily EQU 18h
  55. div EQU swi 6
  56.  
  57.  
  58. .org 0x08235154 ;Free Space
  59. .area 0xDAC
  60. .align 2
  61.  
  62. rngRoutine:
  63.     ldr r0, =rngaddress
  64.     bx r0
  65.     pop r15
  66.  
  67. ;setPanelToTeam:
  68. ;   ldr r0 =fieldConfiguration
  69.  
  70. ;callTimestopChipWithoutTimestop:
  71.     ;requires routine and parameters.
  72.  
  73.  
  74.     ;healSelf:
  75.     ;r0 = how much to heal
  76.     ;r5 = who to heal
  77.     ;bl RecoveryChipRoutine
  78.  
  79. ;===========================FLASH MAN==========================
  80. armRaiseMove:
  81.     ;Hijack at 080D7A66
  82.     push r1-r3,r5,r6
  83.     push r14
  84.     ;b performBulbSpawn
  85.     push r0
  86.     ldrh r0, [r5,24h] ;GetHP
  87.     ldr r4, =12Ch
  88.     cmp r0,r4
  89.     pop r0
  90.     bgt notInRecoveryThreshold
  91.  
  92.     inRecoveryThreshold:
  93.         ldr r0, =0x7D ;how much HP to heal at level 0 (125)
  94.         ldr r4, [r5,4h] ;get level
  95.         add r4, r4, 1h ; prevents *0
  96.         mul r0, r4 ;multiply how much HP to heal
  97.         bl RecoveryChipRoutine
  98.         mov r1, 0h ;0 = Navi Pixelated Summon
  99.         strb r1,[r5, 0xC]
  100.         mov r1, 1h  ;Give Flashman another chip to use as he may run out.
  101.         strb r1,[r5,0x1A] ;0xA offset is how many chips an AI have to use, but r5 is incremented by 4 here for some reason.
  102.         pop r1
  103.         pop r1-r3,r5,r6; including get rid of return address, we will set our own to resume control
  104.  
  105.         ldr r0, =080D7A84h|1b
  106.         bx r0 ;ignore post spawn
  107.  
  108.     notInRecoveryThreshold:
  109.        
  110.         push r1-r3
  111.         bl rngRoutine ;GET RNG result AND PUT INTO r0
  112.         mov r1, 02h ;remainder 0 = steal, anything else = bulbs
  113.         swi 6; Divide, remainder is in r1
  114.         mov r0, 0h
  115.         cmp r0, r1
  116.         pop r1
  117.         pop r2
  118.         pop r3
  119.         bne performBulbSpawn
  120.         stealPanels:
  121.             ;position is on the stack it seems...?
  122.             ;Make the areagrab noise since it won't automatically
  123.             mov r0, 0x78
  124.             bl PlaySound
  125.             mov r0, 9h
  126.             b armRaiseFinish
  127.             pop r1-r3,r5,r6
  128.             ldr r0, =080D7A84h|1b
  129.             bx r0 ;ignore post spawn
  130.  
  131.         performBulbSpawn:
  132.             mov r0, 11h
  133.  
  134.         armRaiseFinish:
  135.             bl SpawnObject
  136.             pop r15 ;finish
  137.  
  138. snakeTrace:
  139.     push r14
  140.     bl GetPlayer ;load X,Y into r0 r1
  141.     ;r0 - Player Current X
  142.     ;r1 - Player Current Y
  143.     push r1
  144.     push r3 ;temporary variable
  145.     ldr r1, [sp,0xC] ;next X pos of bulb
  146.     add r1, r1, 1h
  147.     cmp r0, r1 ;compare next X+1 (same) vs Megaman's X
  148.     ldrb r2,[r5,13h] ; highjacks at 080D7688 ;Current Y position
  149.     bne snakeTraceNotLinedUp ;exit if numbers aren't the same
  150.     snakeTraceLinedUp:
  151.         pop r3
  152.         pop r0 ;Player Y
  153.         cmp r2, r0 ;compare Y coordinates. also used by the routine we return to
  154.         bne snakeTraceDifferentYs
  155.         b snakeTraceLinedUpExit ;same Ys.
  156.  
  157.         snakeTraceDifferentYs:
  158.             str r1, [sp,0x4] ;store same X if our current Y is not the same as the player Y (hit and leave field)
  159.  
  160.         snakeTraceLinedUpExit:
  161.             pop r15
  162.  
  163.     snakeTraceNotLinedUp:
  164.         pop r3
  165.         mov r1, 1h
  166.         cmp r1, 1h ;force same y
  167.         pop r1
  168.         ;mov r2, 1h
  169.         ;cmp r2, 2h ;Same Y
  170.         pop r15
  171.    
  172.  
  173. loadFlashmanRandomChip:
  174.     push r14
  175.     bl rngRoutine ;GET RNG result AND PUT INTO r0
  176.     mov r1, flashmanchipcount ;number of chips in selection list
  177.     swi 6; Divide
  178.     ldr r0,=@@flashmanChipLookupTable ;Load address of chip lookup table (defined below)
  179.     mov r2,0x03 ; Load r2 with 3
  180.     mul r1,r2 ;Multiply the remainder result by the size of the structs (3 bytes) - this will provide an offset into the chip lookup table
  181.     add r0,r0,r1 ;calculate the address using the offset, store in r0
  182.     ldrb r3, [r0,0x02] ;load byte from *r0 (offset 2 forward) into r3 (dmg)
  183.     ldrb r1, [r0,0x01] ;load byte from *r0 (offset 1 forward) into r1 (sublevel)
  184.     ldrb r0, [r0,0x00] ;load byte from *r0 (direct addr) into r0 (family)
  185.     ldrb r2,[r5,16h] ; ...this is actually the object's alliance enemy/allied
  186.     pop r15
  187.  
  188. .pool
  189. @@flashmanChipLookupTable:
  190. ;.byte teamfamily, 1h, 0h
  191. .byte areafamily, 0h, 10h
  192. ;.byte stagefamily, 4h, 0h
  193. ;.byte trumpyfamily, 2h, 0h
  194.  
  195. ;Flashman zap throwdown
  196. .align 4
  197. flashmanThrowdownAction:
  198.     push r1,r2,r5,r6
  199.     push r14
  200.     bl rngRoutine ;GET RNG result AND PUT INTO r0
  201.     mov r1, 0x3 ;number of available actions
  202.     swi 6; Divide
  203.     ldr r0,=flashmanThrowdownLookupTable ;Load address of actions
  204.     add r0,r0,r1 ;calculate the address using the offset, store in r0
  205.     ldrb r1, [r0, 1h] ;sound check
  206.     ldrb r0, [r0] ;action
  207.     tst r1, r1
  208.     bne playThrowdownSFX
  209.     b finishFlashmanThrowdown
  210.     playThrowdownSFX:
  211.         push r0
  212.         mov r0, r1
  213.         bl PlaySound
  214.         pop r0
  215.  
  216.     finishFlashmanThrowdown:
  217.         pop r15
  218.  
  219. .pool
  220. flashmanThrowdownLookupTable:
  221. .byte 0x35, 0x00 ;Mine
  222. .byte 0x3A, 0x9D ;YoYo
  223. .byte 0x10, 0x00 ;ZapAttack
  224.  
  225. ;-----------------------------GUTS MAN----------------------
  226.  
  227. ;This block is unused right now due to spam issues
  228. ;loadGutsmanRandomChip:
  229. ;push r14
  230. ;bl rngRoutine
  231. ;mov r1, gutsmanchipcount
  232. ;swi 6; Divide
  233. ;ldr r0,=@@gutsmanChipLookupTable ;Load address of chip lookup table (defined below)
  234. ;mov r2,0x03 ; Load r2 with 3
  235. ;mul r1,r2 ;Multiple the remainder result by the size of the structs (3 bytes) - this will provide ;an offset into the chip lookup table
  236. ;add r0,r0,r1 ;calculate the address using the offset, store in r0
  237. ;ldrb r3, [r0,0x02] ;load byte from *r0 (offset 2 forward) into r3 (dmg)
  238. ;ldrb r1, [r0,0x01] ;load byte from *r0 (offset 1 forward) into r1 (sublevel)
  239. ;ldrb r0, [r0,0x00] ;load byte from *r0 (direct addr) into r0 (family)
  240. ;ldrb r2,[r5,16h] ; ...this is actually the object's alliance enemy/allied
  241. ;pop r15
  242.  
  243.  
  244. ;.pool
  245. ;@@gutsmanChipLookupTable:
  246. ;.byte teamfamily, 0h, 0h
  247. ;.byte areafamily, 1h, 10h
  248. ;.byte stagefamily, 4h, 0h
  249. ;.byte trumpyfamily, 1h, 0h
  250. ;.align 4
  251. loadZPunchRandomChip:
  252.     .align 2
  253.     push r14
  254.     bl rngRoutine
  255.     mov r1, gutsmanZPunchChipCount
  256.     swi 6; Divide
  257.     ldr r0,=@@gutsmanZPunchLookupTable ;Load address of chip lookup table (defined below)
  258.     mov r2,0x03 ; Load r2 with 3
  259.     mul r1,r2 ;Multiple the remainder result by the size of the structs (3 bytes) - this will provide an offset into the chip lookup table
  260.     add r0,r0,r1 ;calculate the address using the offset, store in r0
  261.     ldrb r3, [r0,0x02] ;load byte from *r0 (offset 2 forward) into r3 (dmg)
  262.     ldrb r1, [r0,0x01] ;load byte from *r0 (offset 1 forward) into r1 (sublevel)
  263.     ldrb r0, [r0,0x00] ;load byte from *r0 (direct addr) into r0 (family;)
  264.     ldrb r2,[r5,16h] ; ...this is actually the object's alliance enemy/allied
  265.     pop r15
  266.  
  267. .pool
  268. @@gutsmanZPunchLookupTable:
  269. ;.byte teamfamily, 0h, 0h
  270. ;.byte areafamily, 1h, 10h
  271. ;.byte stagefamily, 4h, 0h
  272. .byte trumpyfamily, 2h, 0h
  273. .byte sensorfamily, 2h, 100h
  274. .byte mpchipfamily, 2h, 0h
  275.  
  276. ;=================GRAB REVENGE===========
  277. .align 2
  278. grabRevengeResetBoard:
  279.     push r14
  280.     //Read what team called this chip 00 = Player 04 = Enemy. This conveniently also means the return value can be used as an offset to the list of timer pointers
  281.     ldrb r0, [r5,6h]
  282.     //lsr r2, r2, 2h //Divide by 4 - 1 is enemy 0 is us
  283.     //mul r1, r2, 4h ;0x4 = no offset, 1x4 = 2nd offset (enemy team offset in the pool)
  284.     ldr r1, =GrabRevengeMemoryTimerPointer
  285.     //ldr r1, [r1] //Load pointer to first item in pool
  286.     add r0, r1, r0 //get offset in the pool below
  287.     ldr r0, [r0] //load the value into 40 from there
  288.     mov r1, 5h ;timer value to set, will be incremented by 15 frames every time to create a nice
  289.     push r2,r3
  290.     mov r2, 0h
  291.     mov r3, 2h ;0-2 columns
  292.    
  293.     returnColumnsInCascade:
  294.         strh r1, [r0] ;Set the current timer of panels to 5 frames. After those 5 frames the panels will return
  295.         add r0, r0, 4h ;Go to next position for next row.
  296.         push r0
  297.         mov r0, 20h
  298.         add r1, r1, r0
  299.         pop r0
  300.         //add r1, r1, 7h;Add 14 frames for cascade
  301.         //add r1, r1, 7h;Add 14 frames for cascade
  302.         add r2, r2, 1h ;Update counter
  303.         cmp r2,r3
  304.         ble returnColumnsInCascade
  305.  
  306.  
  307.     pop r2,r3
  308.     mov r0, 5h ;original code
  309.     mov r1, 4h ;original code
  310.     pop r15
  311.  
  312. .pool
  313. GrabRevengeMemoryTimerPointer:
  314. .dw 0200F7A4h ;Panels that the enemy stole from you will reset
  315. .dw 0200F7B0h ;Panels that the player stole from the other team will reset
  316.  
  317. //=========================FLAME MAN======================================
  318. flamemanNextCandleStateRandom: //return next state on r0.
  319.     push r14
  320.     push r2
  321.     push r3
  322.     strb r0, [r5,6h]
  323.     bl rngRoutine
  324.     mov r1, 4h //Number of candle states
  325.     div //r1 = remainder
  326.     mov r0, r1
  327.     pop r3
  328.     pop r2
  329.     pop r15
  330.  
  331. flamemanYellowGuyChangeToHorizontalOnSameRowAsPlayer:
  332.     push r14
  333.     push r0-r2
  334.     bl GetPlayer ;r0 = X, r1 = Y
  335.     mov r3, r1 //Put player Y in r3
  336.     pop r0-r2
  337.     ldr r1,[r5,44h]
  338.     tst r1,r1
  339.     pop r15
  340.  
  341. flamemanYellowGuyChangeToVerticalOnSameColumnAsPlayer:
  342.     push r14
  343.     push r0-r2
  344.     bl GetPlayer ;r0 = X, r1 = Y
  345.     mov r3, r0 //Put player X in r3
  346.     pop r0-r2
  347.     ldr r1,[r5,40h]
  348.     tst r1,r1
  349.     pop r15
  350.  
  351. flamemanLevelUpCandleExtinguished:
  352.     push r14
  353.     push r1,r2
  354.     ldrb r0, [r5,0Ch] //Read state that is being extinguished
  355.     //Check if it is 0x4 (Level Up)
  356.     cmp r0, 8h //8 as its left shifted by 1.
  357.     bne @@flamemanCandleExtinguishedFinish
  358.  
  359.     //We are extinguishing a level up flame
  360.     ldr r0,[r5,4Ch] //Get Pointer To Parent
  361.     ldrb r2, [r0,4h] //Get current level
  362.     sub r2, 1h
  363.     strb r2,[r0,4h] //Store level -1
  364.     bl flamemanUpdateAIConstantsAddress
  365.  
  366.     @@flamemanCandleExtinguishedFinish:
  367.         pop r1,r2
  368.         mov r0, 0h //Original Code
  369.         strb r0,[r5,0Ch] //Original Code
  370.         pop r15
  371.  
  372. flamemanLevelUpCandleActivating:
  373.     push r1,r2,r14
  374.     ldrh r0, [r5,20h] //Read activation timer
  375.     cmp r0, 0h
  376.     bne @@flamemanEndCandleActivation
  377.     add r0, 1h
  378.     strh r0, [r5,20h] //Set candle timer to 1 (it doesn't count down while active) to indicate this effect has already been applied
  379.     ldrh r0, [r5,24h] //Get HP
  380.     lsl r0, r0, 0x2 //Quadruple HP
  381.     strh r0, [r5,24h]
  382.     //strh r0, [r5,26h]
  383.     ldr r0,[r5,4Ch] //Get Pointer To Parent
  384.     ldrb r2, [r0,4h] //Get current level
  385.     add r2, 1h
  386.     strb r2,[r0,4h] //Store level +1
  387.     bl flamemanUpdateAIConstantsAddress //R0 = FlamemanPointer, R2 = Level
  388.     @@flamemanEndCandleActivation:
  389.     pop r1,r2,r15
  390.  
  391. .align 4
  392. flamemanCustomCandleActivationArray:
  393.     .word 0x080E2CC9 //Green Empty Function
  394.     .word 0x080E2CCD //Red Empty Function
  395.     .word 0x080E2CD1 //Yellow Empty Function
  396.     //NEW ONE HERE //NEW Level Up Startup Function
  397.     .word flamemanLevelUpCandleActivating|1b
  398.  
  399. flamemanUpdateAIConstantsAddress:
  400.     push r14
  401.     push r5 //This operation requires r5 to point to flameman memory
  402.     mov r5, r0 //Update R5 with the one referenced by the candle parent
  403.     ldr r0, =flamemanNewAIData ;Flameman AI Base
  404.     mov r1, 0Ah ;Flameman's data is 0xA bytes wide per level
  405.     bl CalculateAIConstantsAddress
  406.     pop r5
  407.     pop r15
  408.  
  409.     .pool
  410.     //Flameman New AI Data
  411.     flamemanNewAIData:
  412.     //      0    1    2    3    4    5    6    7    8    9
  413.     .byte 0x3C,0x3C,0x3C,0x1E,0x2D,0x08,0xA4,0x0A,0x10,0x78 //Normal
  414.     .byte 0x64,0x50,0x50,0x19,0x28,0x0C,0x90,0x09,0x18,0x64 //Alpha
  415.     .byte 0x96,0x96,0x96,0x14,0x23,0x15,0x70,0x08,0x20,0x50 //Beta
  416.     .byte 0xC8,0xC8,0xC8,0x0F,0x1E,0x20,0x58,0x06,0x20,0x3C //Omega
  417.     .byte 0xE1,0xE1,0xE1,0x0A,0x0F,0x25,0x44,0x03,0x28,0x28 //Omega + 1
  418.     .byte 0xFA,0xFA,0xFA,0x05,0x0A,0x28,0x40,0x01,0x30,0x16 //Omega + 2
  419.  
  420.     //Candle info
  421.     //[02038A74]=CURRENT SELF POINTER
  422.     //[02038AC0]=PARENT POINTER
  423.     //r5+4C = Parent Pointer
  424.  
  425. flamemanAdditionalAttacksWithLevelUpCandleCheck:
  426.     push r0-r2,r14
  427.     mov r0, #0x0 //init bitmask
  428.  
  429.     //Check Candle 1
  430.     ldr r1, [r5,#0x60]
  431.     tst r1,r1 //Candle 1 is not null check
  432.     beq @@CheckCandle2
  433.     ldrb r2, [r1,#0xC]
  434.     orr r0, r2 //add effect to bitmask
  435.  
  436.     //Check Candle 2
  437.     @@CheckCandle2:
  438.     ldr r1, [r5,#0x64]
  439.     tst r1,r1 //Candle 2 is not null check
  440.     beq @@candleEffectCheck
  441.     ldrb r2, [r1,#0xC]
  442.     orr r0, r2
  443.  
  444.     @@candleEffectCheck:
  445.     //8 = Leveled Up
  446.     mov r1, 8h
  447.     and r0, r1
  448.     tst r0, r0
  449.     beq @@flamemanLaunchStandardFlameAttack
  450.  
  451.     //Different Flame Attack
  452.     @@flamemanLaunchDifferentFlameAttack:
  453.         bl rngRoutine ;GET RNG result AND PUT INTO r0
  454.         mov r1, 0x4
  455.         swi 6
  456.         tst r1,r1
  457.         bne @@flamemanLaunchModifiedFlameAttack
  458.         @@flamemanSpawnFireRatn:
  459.             //Check if square we are going to spawn in is occupied by something. If it is, we shouldn't spawn a ratton
  460.             pop r0-r2
  461.             push r0-r2 //we might still need these...
  462.             mov r0, r1
  463.             mov r1, r2 //move positions to correct registers
  464.             bl GetPanelType
  465.             mov r1, 0xE
  466.             lsl r1, r1, 0x18 //Occupied mask
  467.             //mov r1, 0x10 //broken panel mask
  468.             //orr r0, r1 //also check if panel is broken
  469.             tst r0, r1
  470.             bne @@flamemanLaunchModifiedFlameAttack //it is occupied
  471.  
  472.             //Spawn Ratton
  473.             pop r0-r2 //Discard
  474.             mov r0, 0xC8 //HP of Object
  475.             mov r3, 1h //Enemy Team
  476.             mov r4, 0h //Memory Space that will be assigned to this object on spawn (by spawnobject)
  477.             mov r6, 0xE6 //230 Damage
  478.             bl 0x080DA218 ;SpawnRatton
  479.             pop r15
  480.  
  481.         @@flamemanLaunchModifiedFlameAttack:
  482.             //Recover a small amount of HP
  483.             push r4
  484.             ldr r0, =0xA ;how much HP to heal at level 0 (125)
  485.             ldrb r4, [r5,4h] ;get level
  486.             add r4, r4, 1h ; prevents *0
  487.             mul r0, r4 ;multiply how much HP to heal
  488.             bl RecoveryChipRoutine
  489.             pop r4
  490.             mov r0, 30h
  491.             lsl r1, r1, 18h
  492.             orr r4, r1
  493.         @@flamemanLaunchStandardFlameAttack:
  494.             pop r0-r2
  495.             bl 0x080E317E ;FlamemanSpawnInitialFlameTower
  496.             pop r15
  497.  
  498. .align 4
  499. .pool
  500. @@FlamemanCustomFlameAttackPattern:
  501. .word 0x06280C00 //Straight Flame
  502. .word 0x02241401 //WideFlame
  503. .word 0x32241401 //WideFlame, goes 3 rows deep (at least)
  504. .word 0x02241400
  505.  
  506. //========================PLANT MAN================================
  507. setImpactEffect:
  508.     //r0 = Object Memory
  509.     //r3 = Impact Effect Bitmask (0x3 = Flinch + Invis, 0x1 = Flinch, 0x0 = Nothing)
  510.     ldr r1,[r0,0x60]
  511.     strb r3,[r1,0xA]
  512.     mov r15,r14
  513.  
  514. createCoordinateByte:
  515.     //r0 = X
  516.     //r1 = Y
  517.     lsl r0, r0, 4h
  518.     orr r0, r1
  519.     mov r15, r14
  520.  
  521. getFarthestRightPlayerColumn:
  522.     push r14
  523.     mov r0, 0h //Y
  524.     mov r1, 0h //X
  525.     mov r2, 0h //Farthest X
  526.     @@incrementY:
  527.         add r0, 1h //Y++
  528.         cmp r0, 3h //Y > 3
  529.         bgt @@returnFarthestRow
  530.         mov r1, 0h //X = 0
  531.     @@incrementX:
  532.         add r1, 1h //X++
  533.         push r0-r3 //Push Values
  534.         mov r2, 0x10
  535.         mov r3, 0x08
  536.         lsl r3, r3, 0x18
  537.         bl GetPanelTeam //team on r1, address on r2
  538.         tst r0,r0 // 1 = red team...?
  539.         pop r0-r3
  540.         beq @@incrementY //next row
  541.         cmp r1, r2
  542.         blt @@continueLoop
  543.         mov r2, r1 //FarthestX = New X
  544.  
  545.         @@continueLoop:
  546.             //pop r0-r2
  547.             cmp r1, 6h // X > 6
  548.             bgt @@incrementY
  549.             b @@incrementX
  550.  
  551.     @@returnFarthestRow:
  552.         mov r0, r2
  553.         pop r15
  554.  
  555. getNumPanelsForPlayer:
  556.     push r14
  557.     mov r0, 0h //Y
  558.     mov r1, 0h //X
  559.     mov r2, 0h
  560.     incrementY:
  561.         add r0, 1h //Y++
  562.         cmp r0, 3h //Y > 3
  563.         bgt returnNumPanels
  564.         mov r1, 0h //X = 0
  565.     incrementX:
  566.         add r1, 1h //X++
  567.         push r0-r2
  568.         bl GetPanelTeam
  569.         tst r0,r0 // 0 = red team
  570.         bne continueLoop
  571.         add r2, 1h //Team Panel
  572.  
  573.         continueLoop:
  574.             pop r0-r2
  575.             cmp r1, 6h // X > 6
  576.             bgt incrementY
  577.             b incrementX
  578.  
  579.     returnNumPanels:
  580.         pop r15
  581.  
  582. splitByteToPosition:
  583.     //r0 input = byte with X in upper 4 bits, lower 4 bits being Y
  584.     push r2,r14
  585.     lsr r2, r0, #0x4 //X - this can only be loaded with 8 bits so discard the bottom 4
  586.     lsl r1, r0, #0x1D  //register is 32 bits wide so shift 28 left to discard bits 7-4
  587.     lsr r1, r1, #0x1D
  588.     mov r0, r2 //put X into r0
  589.     pop r2,r15
  590.  
  591. getRandomPositionWithLessThanXIgnoringR3:
  592.     push r5,r14
  593.     //r2 = Farthest X we can choose.
  594.     //r3 = 32-bits of 8 bit coordinates that should not be chosen
  595.     //Internal r4 is the number of attempts. After so many attempts we will give up to prevent deadlock
  596.     //Internal r5 the original register we can restore to r3 if we find a bad coordinate
  597.     mov r4, 0h //attempts = 0
  598.     mov r5, r3 //cache the ignored bytes
  599.     mov r6, r2 //cache farthest right as r6
  600.     @@GetRandomCoordinatesInRange:
  601.         cmp r4, 9h
  602.         bgt @@GiveUpFindingCoordinate
  603.  
  604.         bl rngRoutine
  605.         mov r1, r6 //farthest right
  606.         swi 6
  607.         add r1, 0x1 //remainder + 1 is our X
  608.         push r1 //pop as r0
  609.  
  610.         bl rngRoutine
  611.         mov r1, 0x3 //Max Y
  612.         swi 6
  613.         add r1, 0x1 //remainder + 1 is our Y.
  614.         pop r0 //X
  615.         bl createCoordinateByte
  616.  
  617.     mov r3, r5 //Restore Ignored Bytes
  618.     @@emptyR3RegisterLoop:
  619.         //r0 = coordinate to check
  620.         mov r1, #0xFF
  621.         and r1, r3 //keep only bottom 8 bits
  622.  
  623.         tst r1,r1 //check if 00. if it is we have nothing left to check.
  624.         beq @@FinishFindingCoordinate
  625.  
  626.         cmp r0, r1 //Test if values are the same
  627.         beq @@CoordinateShouldBeIgnored
  628.         lsr r3, r3, 0x08 //next coordinate check
  629.         b @@emptyR3RegisterLoop
  630.  
  631.  
  632.     @@CoordinateShouldBeIgnored:
  633.         add r4, 0x1
  634.         b @@GetRandomCoordinatesInRange
  635.  
  636.     @@GiveUpFindingCoordinate:
  637.         mov r0, 0h
  638.  
  639.     @@FinishFindingCoordinate:
  640.         pop r5,r15
  641.  
  642. plantmanInvincibilityCheck:
  643.     push r14
  644.     ldrb r0,[r5,0x12] ;GetX
  645.     ldrb r1,[r5,0x13] ;GetY
  646.     bl GetPanelType //Returns on r0
  647.     mov r1, #0x4
  648.     lsl r1, r1, #0x8 //Grass Bitmask
  649.     tst r0, r1
  650.     beq plantmanEndInvincibilityCheck
  651.     plantmanStandingOnGrass:
  652.         ldrb r0,[r5,0x4] ;Get Level
  653.         mov r1, #0x2 //Beta or higher
  654.         cmp r0, r1
  655.         blt plantmanEndInvincibilityCheck
  656.  
  657.     plantmanSetInvincible:
  658.         mov r0, #0x1D ;Enemy Invincibility apparently
  659.         bl SetInvincible
  660.    
  661.     plantmanEndInvincibilityCheck:
  662.         bl #0x08000F58 //Original Hook Code
  663.         pop r15
  664.  
  665. plantmanLanceRowAttack:
  666.     push r14
  667.     ldrb r0,[r5,#0xB]
  668.     tst r0, r0 //Check that we are busy
  669.     bne plantmanLanceRowDecrementEndingTimer
  670.     //Setup Damage
  671.     mov r6,#0x8C //Get AI Constants Offset
  672.     ldr r6,[r5,r6]
  673.     ldrb r6,[r6,#0x2] //Set Damage
  674.  
  675.     bl GetPlayer
  676.     ;r0 - Player Current X
  677.     mov r2, 1h //if player is in back row
  678.     cmp r0, r2
  679.     beq plantmanLance
  680.     //Check our HP, snakes on lower HP, needles on higher
  681.     ldrh r0,[r5,0x24]
  682.     ldrh r1,[r5,0x26]
  683.     lsr r1, r1, 0x1
  684.     cmp r0, r1
  685.     blt plantmanHalfHPBasicAttack //Half HP or less
  686.     b plantmanNeedle //Half HP More
  687.  
  688.     plantmanNeedle:
  689.         mov r6,#0x8C //Get AI Constants Offset
  690.         ldr r6,[r5,r6]
  691.         ldrb r1,[r5,#0x12] ;My X Value
  692.         ldrb r2,[r5,#0x13] ;My Y Value
  693.         ldrb r3,[r6,#0x3] //Speed of Needle
  694.         ldrb r6,[r6,#0x2] //Damage of Needle
  695.         lsl r3, r3, 0xC
  696.         bl 0x080E07D6 //SpawnNeedle()
  697.         b plantmanAttackCleanup
  698.  
  699.     plantmanLance:
  700.         mov r0, #0x4
  701.         strb r0,[r5,#0x10]
  702.         mov r1, #0x1 //Players X column
  703.         mov r2, #0x3
  704.         lsr r6, r6, 0x1
  705.         plantmanLanceSpawnLoop:
  706.             mov r0, 4h //Element
  707.             mov r7, 3h //Impact Effect
  708.             bl SpawnLance
  709.             //push r3
  710.             //mov r3, FlinchAndInvisImpact
  711.             //mov r0, r7 //oldwood pillar memory
  712.             //bl setImpactEffect
  713.             //pop r3
  714.             sub r2, #0x1
  715.             bne plantmanLanceSpawnLoop
  716.         b plantmanAttackCleanup
  717.  
  718.     plantmanHalfHPBasicAttack:
  719.         //Randomly choose an attack (boomer or snake)
  720.         //bl rngRoutine
  721.         //mov r1, #0x2
  722.         //swi 6
  723.         //tst r1,r1
  724.         //beq plantmanSnake
  725.         b plantmanSnake
  726.  
  727.     plantmanBoomer:
  728.         mov r0, 0xB7 ;Boomer Throw
  729.         bl PlaySound
  730.         mov r1, 6h //Spawn position
  731.         ldrb r2,[r5,#0x13] ;My Y Value
  732.         ldrb r0,[r6,#0x3] //Speed of Boomer
  733.         lsl r0, r0, 0xB
  734.         //mov r7, 3h //Impact Effect
  735.         push r6
  736.         mov r6, 0x1E
  737.         bl SpawnEnemyBoomer
  738.         pop r6
  739.         b plantmanAttackCleanup
  740.  
  741.     plantmanSnake:
  742.         //end
  743.         bl GetPlayer
  744.         mov r2, r0
  745.         mov r3, r1
  746.         //start
  747.         ldrb r0,[r5,0x12]
  748.         ldrb r1,[r5,0x13]
  749.  
  750.         //mov r2, 0x2
  751.         //mov r3, 0x2
  752.         mov r4, 0x64 //Damage
  753.         bl SpawnSnake
  754.         b plantmanAttackCleanup
  755.  
  756.     plantmanAttackCleanup:
  757.         mov r0, #0x4
  758.         strb r0,[r5,#0x10]
  759.         mov r0,#0x1E
  760.         strh r0,[r5,#0x20]
  761.         mov r0, #0x4
  762.         strb r0,[r5,#0xB]
  763.         b plantmanLanceRowAttackEnd
  764.  
  765.     plantmanLanceRowDecrementEndingTimer:
  766.         ldrh r0,[r5,#0x20]
  767.         sub r0, #0x1
  768.         strh r0,[r5,#0x20]
  769.         bgt plantmanLanceRowAttackEnd
  770.         mov r0, #0x8
  771.         strh r0,[r5,#0xA]
  772.  
  773.     plantmanLanceRowAttackEnd:
  774.         pop r15
  775.  
  776. plantmanVinesInGroundAttackChooser:
  777.     push r14
  778.     //Check panel standing on
  779.     ldrb r0,[r5,0x12] //X
  780.     ldrb r1,[r5,0x13] //Y
  781.     bl GetPanelType //Returns on r0
  782.     mov r1, #0x4
  783.     lsl r1, r1, #0x8 //Grass Bitmask
  784.     tst r0, r1
  785.     beq plantmanAttackChoosingNotStandingOnGrass
  786.  
  787.     plantmanAttackChoosingStandingOnGrass:
  788.         //Check HP
  789.         ldrh r0,[r5,#0x24]
  790.         ldrh r1,[r5,#0x26]
  791.         lsr r1,r1,#0x1 //divide max HP by 2
  792.         cmp r0, r1
  793.         bge plantmanOnGrassMoreThanHalfHP
  794.             //less than half HP, on grass. Restore HP.
  795.             mov r0, 0x8 //Restore HP Vines
  796.             b plantmanVinesInGroundAttackChooserEnd
  797.         //On grass panel but not at less than half HP
  798.  
  799.         plantmanOnGrassMoreThanHalfHP:
  800.             bl rngRoutine
  801.             mov r1, #0x2
  802.             swi 6
  803.             mov r0, 0x4
  804.             //r1 = remainder
  805.             mul r1, r0
  806.             mov r0, 0x10 //start of normal attacks
  807.             add r0, r0, r1
  808.             b plantmanVinesInGroundAttackChooserEnd
  809.  
  810.     plantmanAttackChoosingNotStandingOnGrass:
  811.         //mov r1, 0x2 //attacks that don't restore HP directly
  812.         bl rngRoutine
  813.         mov r1, #0x3 //+1 chance to grass spawn
  814.         swi 6
  815.         tst r1,r1
  816.         beq plantmanForceGrassSpawn
  817.         sub r1, 0x1 //subtract one since its already 1 or 2
  818.         mov r0, 0x4
  819.         //r1 = remainder
  820.         mul r1, r0
  821.         mov r0, 0xC //start of normal attacks
  822.         add r0, r0, r1
  823.         b plantmanVinesInGroundAttackChooserEnd
  824.  
  825.     plantmanForceGrassSpawn:
  826.         mov r0, 0xC
  827.         b plantmanVinesInGroundAttackChooserEnd
  828.  
  829.     plantmanVinesInGroundAttackChooserEnd:
  830.         strb r0,[r5,0xA]
  831.         pop r15
  832.  
  833.  
  834. SpawnOldWoodPillarObject EQU 0x080E0684
  835. plantmanVinesSpawnOldWood:
  836.     push r14
  837.     ldrb r0, [r5,#0xB]
  838.     tst r0, r0 //Check that we are busy
  839.     bne plantmanVinesSpawnOldWoodDecrementTimer
  840.         //First loop here. Set timers and set busy
  841.         mov r0, #0x1E
  842.         strh r0,[r5,#0x20]
  843.         mov r0, #0x3
  844.         strb r0,[r5,#0x10]
  845.         mov r0, #0x4
  846.         strb r0,[r5,#0xB]
  847.  
  848.         ldrb r0,[r5,0x4]
  849.         add r0, 0x1
  850.         strb r0,[r5,0x6] //Number of times we should do spikes
  851.  
  852.         b plantmanVinesSpawnOldWoodAttackEnd
  853.     plantmanVinesSpawnOldWoodDecrementTimer:
  854.         ldrh r0,[r5,#0x20]
  855.         sub r0, #0x1
  856.         strh r0,[r5,#0x20]
  857.        
  858.         //Make Invincible while using super grass attack
  859.         push r0
  860.         mov r0, #0x1D ;Enemy Invincibility apparently
  861.         bl SetInvincible
  862.         pop r0
  863.  
  864.         mov r1, #0x1
  865.         cmp r0, r1 //When timer hits 1
  866.         bne plantmanVinesSpawnOldWoodAttackEnd
  867.             //Play the sound
  868.             mov r0, #0x5 //Make plantman vines in ground wiggle sprite
  869.             strb r0,[r5,#0x10]
  870.  
  871.             bl GetPlayer
  872.             push r0
  873.             bl createCoordinateByte
  874.             mov r3, r0 //Byte of coordinate
  875.             pop r0
  876.             mov r2, r1 //Y
  877.             mov r1, r0 //X
  878.  
  879.             push r3 //save megaman's pos
  880.             mov r0, 0x4
  881.             mov r3, 0x4
  882.             mov r4, 0x4 //seems important for some reason...
  883.             mov r6, 0x64 //Damage...?
  884.             mov r7, 3h //Impact Effect
  885.             bl SpawnOldWoodPillarObject
  886.             push r3
  887.             mov r3, FlinchAndInvisImpact
  888.             mov r0, r7 //oldwood pillar memory
  889.             bl setImpactEffect
  890.             pop r3
  891.        
  892.                 //Spawn Extra Wood Setup
  893.                 bl getFarthestRightPlayerColumn
  894.                 mov r2, r0 //farthest X we can choose
  895.                 pop r3 //Megaman's position. We'll left shift this with the new spawn position up to 3 times for a full 32-bits of stored wood coordinates
  896.                 mov r0, 0h //how many wood we've spawned
  897.                 push r0
  898.             plantmanSpawnAdditionalWood:
  899.                 pop r0
  900.                 add r0, 0x1 //spawning a new wood
  901.                 push r0
  902.                 push r3
  903.                 bl getRandomPositionWithLessThanXIgnoringR3
  904.                 //r0 = random position where X < r4 and nothing in r3 is chosen.
  905.                 pop r3
  906.                 lsl r3, 0x8
  907.                 orr r3, r0 //New coordinate is added to the register of used positions
  908.                 bl splitByteToPosition
  909.                 //Spawn Wood
  910.                 mov r2, r1 //Y
  911.                 mov r1, r0 //X
  912.                 mov r0, 0x4
  913.                 mov r3, 0x4
  914.                 mov r4, 0x4 //seems important for some reason...
  915.                 mov r6, 0x64 //Damage...?
  916.                 mov r7, 3h //Impact Effect
  917.                 bl SpawnOldWoodPillarObject
  918.                
  919.  
  920.                 ldrb r1,[r5,0x4] //Get Level
  921.                 add r1, 0x1 //0 based
  922.                 ldr r0,[sp] //How many wood have spawned
  923.                 cmp r0, r1
  924.                 blt plantmanSpawnAdditionalWood
  925.                 //All wood spawned
  926.                 ldrb r0,[r5,0x6]
  927.                 sub r0, 0x1
  928.                 strb r0,[r5,0x6]
  929.                 tst r0,r0
  930.                 beq plantmanVinesSpawnOldWoodCleanup
  931.                 //Spawn More In a few seconds
  932.                 mov r0, #0x40 //Timer Value
  933.                 mov r1, #0x20 //Timer Offset
  934.                 strb r0,[r5,r1] //Next Timer
  935.                 b plantmanVinesSpawnOldWoodAttackEnd
  936.  
  937.             //tst r7,r7
  938.             //beq plantmanOldWoodFailed
  939.             //ldrb r0,[r7]
  940.             //mov r1, #0x10
  941.             //orr r0, r1
  942.             //strb r0,[r7] //seems to be timestop related...
  943.             ; ldr r4, =plantmanGrassSpawningArray
  944.             ; ldrb r3,[r5,#0x6] ;Get initial offset into the array
  945.             ; push r3 //push the original offset value
  946.             ; add r4, r4, r3 //Base offset
  947.             ; ldrb r3,[r4] //Get first byte of our offset. This is how many panels will be spawned
  948.             ; tst r3,r3
  949.             ;beq plantmanVinesSpawnOldWoodCleanup //Hit end marker 00
  950.             //plantmanOldWoodFailed:
  951.             //  b plantmanVinesSpawnOldWoodCleanup
  952.  
  953.             //mov r0, #0x10
  954.             //add r0, #0xFF
  955.             //bl PlaySound //Play Brushman Noise
  956.  
  957.             //mov r7, 0x0 //how many panels have spawned so far
  958.             //plantmanSpawnOldWoodPanel:
  959.             //  add r7, 0x1
  960.             //  ldrb r0,[r4,r7] //panel position to spawn at
  961.             //  bl splitByteToPosition
  962.             //  mov r2, 0x6 //Grass type
  963.             //  push r3-r4,r7
  964.             //  bl SetPanelType //X Y TYPE
  965.             //  pop r3-r4,r7
  966.             //  //Check if we have more panels to spawn
  967.             //  cmp r7, r3
  968.             //  blt plantmanSpawnOldWoodPanel
  969.  
  970.             //Store next offset
  971.             ; pop r3 //the original offset
  972.             ; add r7, 0x1
  973.             ; add r3, r3, r7
  974.             ; strb r3,[r5,#0x6] //Store next starting offset
  975.             ; ldrb r3,[r4,r7]
  976.             ; tst r3,r3 //if 00 we hit the end
  977.             ; beq plantmanVinesSpawnOldWoodCleanup
  978.  
  979.             //Set next timer
  980.             //mov r0, #0x15
  981.             //mul r0, r3
  982.             //strh r0,[r5,#0x20] //next timer = 0x15*num panels to spawn next
  983.  
  984.             //b plantmanVinesSpawnOldWoodAttackEnd
  985.  
  986.     plantmanVinesSpawnOldWoodCleanup:
  987.         pop r0 //Get rid of how many wood we've spawned
  988.         //Reset panel i'm on.
  989.         ldrb r0,[r5,0x12]
  990.         ldrb r1,[r5,0x13]
  991.         mov r2, 0x2; Normal Panel
  992.         bl SetPanelType
  993.         mov r0, 0x91 ;Chippoof
  994.         bl PlaySound
  995.         mov r0, plantmanVinesEndingIndex
  996.         strh r0,[r5,#0xA]
  997.  
  998.     plantmanVinesSpawnOldWoodAttackEnd:
  999.         pop r0
  1000.         pop r15
  1001.  
  1002. plantmanVinesSpawnGrass:
  1003.     push r14
  1004.     ldrb r0,[r5,#0xB]
  1005.     tst r0, r0 //Check that we are busy
  1006.     bne plantmanVinesSpawnGrassDecrementTimer
  1007.         //First loop here. Set timers and set busy
  1008.         mov r0, #0x1E
  1009.         strh r0,[r5,#0x20]
  1010.         mov r0, #0x3
  1011.         strb r0,[r5,#0x10]
  1012.         mov r0, #0x4
  1013.         strb r0,[r5,#0xB]
  1014.         mov r0, #0x0 //Current offset into spawning array
  1015.         strb r0,[r5,#0x6]
  1016.         b plantmanVinesSpawnGrassAttackEnd
  1017.     plantmanVinesSpawnGrassDecrementTimer:
  1018.         ldrh r0,[r5,#0x20]
  1019.         sub r0, #0x1
  1020.         strh r0,[r5,#0x20]
  1021.  
  1022.         mov r1, #0x1 //stop on timer = 1
  1023.         cmp r0, r1
  1024.         bne plantmanVinesSpawnGrassAttackEnd
  1025.             //Play the sound
  1026.             mov r0, #0x5 //Make plantman vines in ground wiggle sprite
  1027.             strb r0,[r5,#0x10]
  1028.            
  1029.             ldr r4, =plantmanGrassSpawningArray
  1030.             ldrb r3,[r5,#0x6] ;Get initial offset into the array
  1031.             push r3 //push the original offset value
  1032.             add r4, r4, r3 //Base offset
  1033.             ldrb r3,[r4] //Get first byte of our offset. This is how many panels will be spawned
  1034.             tst r3,r3
  1035.             beq plantmanVinesSpawnGrassCleanup //Hit end marker 00
  1036.  
  1037.             mov r0, #0x10
  1038.             add r0, #0xFF
  1039.             bl PlaySound //Play Brushman Noise
  1040.  
  1041.             mov r7, 0x0 //how many panels have spawned so far
  1042.             plantmanSpawnGrassPanel:
  1043.                 add r7, 0x1
  1044.                 ldrb r0,[r4,r7] //panel position to spawn at
  1045.                 bl splitByteToPosition
  1046.                 push r0,r1
  1047.                     //Check to make sure its not broken
  1048.                     bl GetPanelType //Returns on r0
  1049.                     mov r1, #0x1
  1050.                     lsl r1, r1, 0x8
  1051.                     tst r0, r1
  1052.                     pop r0,r1
  1053.                     bne plantmanSkipPanel
  1054.                 //not broken
  1055.                 mov r2, 0x6 //Grass type
  1056.                 push r3-r4,r7
  1057.                 bl SetPanelType //X Y TYPE
  1058.                 pop r3-r4,r7
  1059.  
  1060.                 //Check our level for extra effects on player side
  1061.                 // Beta = Sand, Omega = Poison
  1062.                 ldrb r0,[r5,0x4]
  1063.                 cmp r0, 2h //Min Level (Beta)
  1064.                 blt plantmanFinishPanelChange
  1065.                 ldrb r0,[r4,r7]
  1066.                 sub r0, 0x30 //left 3 panels
  1067.                 bl splitByteToPosition
  1068.                 push r0,r1
  1069.                     //Check to make sure its not broken
  1070.                     bl GetPanelType //Returns on r0
  1071.                     mov r1, #0x1
  1072.                     lsl r1, r1, 0x8
  1073.                     tst r0, r1
  1074.                     pop r0,r1
  1075.                     bne plantmanFinishPanelChange
  1076.                 push r0
  1077.                 ldrb r0,[r5,0x4]
  1078.                 cmp r0, 2h //Min Level (Beta)
  1079.                 pop r0
  1080.                 bgt plantmanOmegaPanel
  1081.                 beq plantmanBetaPanel
  1082.                 b plantmanFinishPanelChange
  1083.  
  1084.                     plantmanOmegaPanel:
  1085.                         push r4,r5
  1086.                         mov r5, 1h //palette
  1087.                         mov r2, 0x4 //Poison
  1088.                         b plantmanSetPlayersSidePanel
  1089.                     plantmanBetaPanel:
  1090.                         push r4,r5
  1091.                         mov r2, 0xA //Sand
  1092.                         mov r5, 4h //palette
  1093.                         b plantmanSetPlayersSidePanel
  1094.  
  1095.                     plantmanSetPlayersSidePanel:
  1096.                         push r3,r7
  1097.                         push r0,r1
  1098.                         bl SetPanelType
  1099.                         pop r0,r1
  1100.                         bl 0x0801455A //Get Pixel Coordinates
  1101.                         mov r2,r1
  1102.                         mov r1,r0
  1103.                         mov r4,r5
  1104.                         bl 0x080EE26E // SpawnGeddonPoof       
  1105.                         pop r3,r7
  1106.                         pop r4,r5
  1107.                         b plantmanFinishPanelChange
  1108.  
  1109.                 plantmanFinishPanelChange:
  1110.                     //pop r3-r4,r7
  1111.  
  1112.                 plantmanSkipPanel:
  1113.  
  1114.                     //Check if we have more panels to spawn
  1115.                     cmp r7, r3
  1116.                     blt plantmanSpawnGrassPanel
  1117.  
  1118.             //Store next offset
  1119.             pop r3 //the original offset
  1120.             add r7, 0x1
  1121.             add r3, r3, r7
  1122.             strb r3,[r5,#0x6] //Store next starting offset
  1123.             ldrb r3,[r4,r7]
  1124.             tst r3,r3 //if 00 we hit the end
  1125.             beq plantmanVinesSpawnGrassCleanup
  1126.  
  1127.             //Set next timer
  1128.             mov r1, #0x6
  1129.             ldrb r0,[r5,0x4] //get level
  1130.             mul r1, r0
  1131.             mov r0, #0x20
  1132.             sub r0, r0, r1
  1133.             mul r0, r3
  1134.             strh r0,[r5,#0x20] //next timer = 0x20-(level*8)*numberPanelsToSpawn
  1135.  
  1136.             b plantmanVinesSpawnGrassAttackEnd
  1137.  
  1138.     plantmanVinesSpawnGrassCleanup:
  1139.        
  1140.         mov r0, plantmanVinesEndingIndex
  1141.         strh r0, [r5,#0xA]
  1142.  
  1143.     plantmanVinesSpawnGrassAttackEnd:
  1144.         pop r15
  1145.  
  1146. .pool
  1147. plantmanGrassSpawningArray:
  1148. //Panels to spawn at each interval. Values need to be bitshifted to get their proper values separated
  1149. .byte 0x1, 0x52
  1150. .byte 0x2, 0x51, 0x53
  1151. .byte 0x2, 0x42, 0x62
  1152. .byte 0x4, 0x41, 0x61,0x43, 0x63
  1153. .byte 0x0 //End marker
  1154.  
  1155.  
  1156. plantmanVinesRestoreHP:
  1157.     push r14
  1158.     ldrb r0, [r5,#0xB]
  1159.     tst r0, r0 //Check that we are busy
  1160.     bne plantmanVinesRestoreHPTimerCheck
  1161.     mov r0, #0x76
  1162.     strh r0,[r5,#0x20]
  1163.     mov r0, #0x3
  1164.     strb r0,[r5,#0x10]
  1165.     //bl #0x080C1DF6 //PlantmanFindPositionToSpawnVineInRow
  1166.     //strb r0,[r5,#0x6]
  1167.     //strb r1,[r5,#0x7]
  1168.     mov r0, #0x4
  1169.     strb r0,[r5,#0xB]
  1170.     b plantmanVinesRestoreHPAttackEnd
  1171.  
  1172.     plantmanVinesRestoreHPTimerCheck:
  1173.         ldrh r0,[r5,#0x20]
  1174.         //cmp r0,#0x1E
  1175.         //bne plantmanVinesRestoreHPTimerCheckIsTen
  1176.         mov r1, #0x10
  1177.         strh r1,[r5,#0x30]
  1178.  
  1179.     lsr r0, r0, #0x2
  1180.     bcc plantmanVinesRestoreHPDecrementTimer
  1181.     ldrb r0, [r5,#0x6]
  1182.     ldrb r1, [r5,#0x7]
  1183.     //bl 0x0800B76C //unknown what this does
  1184.  
  1185.     plantmanVinesRestoreHPDecrementTimer:
  1186.         ldrh r0,[r5,#0x20]
  1187.         sub r0, #0x1
  1188.         strh r0,[r5,#0x20]
  1189.  
  1190.         //Make Invincible while using super grass attack
  1191.         push r0
  1192.         mov r0, #0x1D ;Enemy Invincibility apparently
  1193.         bl SetInvincible
  1194.         pop r0
  1195.  
  1196.         mov r1, #0x25 //every 25 frames, check to see if we should heal our HP.
  1197.         swi 6
  1198.         //r1 = remainder
  1199.         ldrb r0,[r5,#0x4]
  1200.         add r0,r0,#0x1 ;Set to level+X to make sure 1 bit is set.
  1201.         //and r0, r0, r1
  1202.         tst r0, r1
  1203.         beq plantmanTestIfSoundShouldPlay
  1204.             //RestoreHP
  1205.             //mov r0, #0x1
  1206.             push r1
  1207.             bl 0x080ADA0C //AddHPRoutine
  1208.             pop r1
  1209.         plantmanTestIfSoundShouldPlay:
  1210.             tst r1, r1
  1211.             bne plantmanVinesRestoreHPAttackEnd
  1212.             //Play the sound
  1213.             mov r0, #0x5 //Make plantman vines in ground wiggle sprite
  1214.             strb r0,[r5,#0x10]
  1215.             mov r0, #0x80
  1216.             bl PlaySound //Play Bass Fist Charging Noise
  1217.            
  1218.             ldrh r0,[r5,#0x20]
  1219.             tst r0,r0
  1220.             beq plantmanVinesRestoreHPCleanup
  1221.             b plantmanVinesRestoreHPAttackEnd
  1222.  
  1223.     plantmanVinesRestoreHPCleanup:
  1224.         ldrb r0,[r5,0x12]
  1225.         ldrb r1,[r5,0x13]
  1226.         mov r2, 0x2; Normal Panel
  1227.         bl SetPanelType
  1228.         mov r0, 0x91 ;Chippoof
  1229.         bl PlaySound
  1230.         mov r0, plantmanVinesEndingIndex
  1231.         strh r0,[r5,#0xA]
  1232.  
  1233.     plantmanVinesRestoreHPAttackEnd:
  1234.         pop r15
  1235.  
  1236. plantmanVinesInGroundAttack:
  1237.     push r14
  1238.     ldrb r0,[r5,#0xB]
  1239.     tst r0, r0 //Check that we are busy
  1240.     bne plantmanVinesTimerCheck
  1241.     mov r0, #0x2B
  1242.     strh r0,[r5,#0x20]
  1243.     mov r0, #0x3
  1244.     strb r0,[r5,#0x10]
  1245.     bl #0x080C1DF6 //PlantmanFindPositionToSpawnVineInRow
  1246.     strb r0,[r5,#0x6]
  1247.     strb r1,[r5,#0x7]
  1248.     mov r0, #0x4
  1249.     strb r0,[r5,#0xB]
  1250.     b plantmanVinesInGroundAttackEnd
  1251.  
  1252.     plantmanVinesTimerCheck:
  1253.         ldrh r0,[r5,#0x20]
  1254.         cmp r0,#0x1E
  1255.         bne VineSproutCheckIfTimerIsTen
  1256.         mov r1, #0x10
  1257.         strh r1,[r5,#0x30]
  1258.  
  1259.     VineSproutCheckIfTimerIsTen:
  1260.         cmp r0, #0x10
  1261.         bge plantmanVineSproutDecrementTimer
  1262.  
  1263.     lsr r0, r0, #0x2
  1264.     bcc plantmanVineSproutDecrementTimer
  1265.     ldrb r0,[r5,#0x6]
  1266.     ldrb r1,[r5,#0x7]
  1267.     bl 0x0800B76C //unknown what this does
  1268.  
  1269.     plantmanVineSproutDecrementTimer:
  1270.         ldrh r0,[r5,#0x20]
  1271.         sub r0, #0x1
  1272.         strh r0,[r5,#0x20]
  1273.         bgt plantmanVinesInGroundAttackEnd
  1274.  
  1275.     plantmanVineSproutTimerZero:
  1276.         mov r0, #0x5
  1277.         strb r0,[r5,#0x10]
  1278.         ldrb r1,[r5,#0x6]
  1279.         tst r1,r1
  1280.         beq plantmanVineSproutCleanup
  1281.         ldrb r2,[r5,#0x7]
  1282.         mov r3,#0x8C
  1283.  
  1284.         ldr r3,[r5,r3]
  1285.         ldrb r6,[r3,#0x4]
  1286.         ldrb r3,[r3,#0x5]
  1287.         mov r0, #0x60
  1288.         strh r3,[r5,r0]
  1289.         ldrb r3,[r5,#0x4]
  1290.         mov r7,r5
  1291.         bl 0x80E09F4 //PlantmanSpawnVine
  1292.  
  1293.     plantmanVineSproutCleanup:
  1294.         mov r0, plantmanVinesEndingIndex
  1295.         strh r0,[r5,#0xA]
  1296.  
  1297.     plantmanVinesInGroundAttackEnd:
  1298.         pop r15
  1299.  
  1300.  
  1301.  
  1302. plantmanVinesSpawnVine EQU 0x080C1CCC //Sprout a vine
  1303. .pool
  1304. plantmanVinesInGroundRoutinesArray:
  1305. .word plantmanVinesInGroundAttackChooser|1b
  1306. .word plantmanPostVinesDelayRoutine|1b //This is in the default game and we can share it across others it seems. The default goes to 0x4 so we need to keep this here.
  1307. .word plantmanVinesRestoreHP|1b ;0x8
  1308. .word plantmanVinesSpawnGrass|1b ;0xC
  1309. .word plantmanVinesSpawnVine|1b ;0x10
  1310. .word plantmanVinesSpawnOldWood|1b ;0x14
  1311.  
  1312. //plantmanLowHPAttackRoutinesArray
  1313.  
  1314. ; plantmanVinesSpawnFlowers EQU 0x080C1D7D //Sprout a vine
  1315. ; .pool
  1316. ; plantmanVinesInGroundRoutinesArray:
  1317. ; .word plantmanVinesInGroundAttackChooser|1b
  1318. ; .word plantmanPostVinesDelayRoutine|1b //This is in the default game and we can share it across others it seems. The default goes to 0x4 so we need to keep this here.
  1319. ; .word plantmanVinesRestoreHP|1b ;0x8
  1320. ; .word plantmanVinesSpawnGrass|1b ;0xC
  1321. ; .word plantmanVinesSpawnVine|1b ;0x10
  1322. ; .word plantmanVinesSpawnOldWood|1b ;0x14
  1323.  
  1324.  
  1325. .endarea
  1326. ;==================HOOKS================
  1327. ;.org 0x080C1990
  1328. ;plantmanGrassInvincibilityHook: //bl #0x08000F58
  1329. ;   bl plantmanInvincibilityCheck
  1330.  
  1331. .org 0x080E2F84 //ldr r1,[r5,44h]
  1332. flamemanYellowGuyYHook:
  1333.     bl flamemanYellowGuyChangeToHorizontalOnSameRowAsPlayer
  1334.  
  1335. .org 0x080E2F2A //ldr r1,[r5,40h]
  1336. flamemanYellowGuyXHook:
  1337.     bl flamemanYellowGuyChangeToVerticalOnSameColumnAsPlayer
  1338.  
  1339. .org 0x080E2D46 //strb r0,[r5,6h]
  1340. flamemanRandomCandleStateHook:
  1341.     push r14
  1342.     nop
  1343.     bl flamemanNextCandleStateRandom
  1344.     pop r15
  1345.  
  1346. .org 0x080E2C10 //mov r0, 0h
  1347. flamemanCandleExtinguishLevelUpHook:
  1348.     bl flamemanLevelUpCandleExtinguished
  1349.  
  1350. .org 0x080C57C0 //bl FlameManSpawnInitialTower
  1351.     bl flamemanAdditionalAttacksWithLevelUpCandleCheck
  1352.  
  1353. .org 0x080F9E9E
  1354. grabRevengeResetBoardHook:
  1355.     bl grabRevengeResetBoard
  1356.  
  1357. .org flashmanChipHookAddress
  1358. flashmanChipHook:
  1359.     bl loadFlashmanRandomChip
  1360.     nop
  1361.  
  1362. .org 0x080D7A66 ;Flashman Bulb Spawn (Arm Raise Move to heal)
  1363. flashmanArmRaiseMoveHook:
  1364.     bl armRaiseMove
  1365.     nop
  1366.     nop
  1367.  
  1368. .org 0x080D7664 ;In the Follow Trace Y calculation area (will only affect follow and not zigzag tracer)
  1369. snakeTraceHook:
  1370.     bl snakeTrace
  1371.     nop
  1372.     nop
  1373.  
  1374. .org 0x080D7850 ;Flashman zap throwdown
  1375. flashmanThrowdownHook:
  1376.     bl flashmanThrowdownAction
  1377.  
  1378. ;.org gutsmanChipHookAddress
  1379. ;gutsmanAreaGrabChipHook:
  1380. ;bl loadGutsmanRandomChip
  1381. ;nop
  1382.  
  1383. .org gutsmanZPunchHookAddress
  1384.     bl loadZPunchRandomChip ;Hook z-punch chip and use my routine instead
  1385.     ;nop
  1386.  
  1387. ;=================PATCHES===============
  1388.  
  1389. ;--------------HP SPEED PATCH---------------------
  1390. ;Makes HP display change faster than default (which is 2)
  1391. .org 0x08010E22
  1392.     mov r0, 8h
  1393.  
  1394. ;------------FLAME MAN PATCHES----------
  1395. .org 0x080C53EC
  1396.     mov r1, 5h ;Candle 1 at X=5 rather than X=6
  1397.  
  1398. .org 0x080C5406
  1399.     mov r1, 5h ;Candle 2 at X=5 rather than X=6
  1400.  
  1401. .org 0x080E2F98
  1402.     cmp r0, r3 ;YellowGuyY will now go left on same row rather than 3
  1403.  
  1404. .org 0x080E2F40
  1405.     cmp r0, r3 ;YellowGuyX will now go down on same row rather than 3
  1406.  
  1407. .org 0x080E2CB8
  1408.     .word flamemanCustomCandleActivationArray ;Rewrite the activation array pointer to my own so the level up function can activate (and avoid crash)
  1409.  
  1410. .org 0x080C5440
  1411.     .word flamemanNewAIData ;Repoint AI data to my own so we have omega +2 levels
  1412.  
  1413. .org 0x080C5916
  1414.     .byte 7h ;Allow flameman to attack from back row
  1415.  
  1416. .org 0x080C5424
  1417.     //Patch out Flameman's Off-Limits 6,2 position.
  1418.     nop
  1419.     nop
  1420.     nop
  1421.     nop
  1422.  
  1423. .org 0x080C566A
  1424.     //Patch out FlameMan's additional off-limits 6,2 check
  1425.     nop
  1426.     nop
  1427.  
  1428. .org 0x080E30B8
  1429.     //Patch out flames despawning on holes
  1430.     nop
  1431.     nop
  1432.  
  1433. .org 0x080C559A
  1434.     cmp r0, #0x6 //Flameman 6 moves in upper half HP instead of 8
  1435.  
  1436. .org 0x080C55B8
  1437.     cmp r0, #0x3 //Flameman 3 moves in lower half of HP instead of 5
  1438.  
  1439. ;--------------Flashman Patches---------
  1440.  
  1441. ;--------------Plantman Patches---------
  1442. //.org 0x080C1C4A
  1443. //  bl SpawnLance ;TEST INSTEAD OF NEEDLE
  1444.  
  1445. .org 0x080C1C08
  1446.     .word plantmanLanceRowAttack|1b ;TEST MY SPAWNLANCE METHOD INSTEAD
  1447.  
  1448. .org 0x080C1CC0 ;Plantman Vines In Ground Attack Choosing Array
  1449.     .word plantmanVinesInGroundRoutinesArray
  1450.  
  1451. ;.org 0x080DE5E0
  1452. ;   mov r0, #0x1 //Make lance give mercy frames
  1453.  
  1454. //.org 0x080C2D74 ;Plantman Vines In Ground Flower Attack Array
  1455. //  .word plantmanLowHPAttackRoutinesArray
  1456.  
  1457. .org 0x080C1B9A ;Plantman Can't Spawn Anything cause flowers exist
  1458.     bne 0x080C1BCE ;Make it so he chooses a normal attack instead
  1459.  
  1460. .org 0x080EE284 ;Old Wood Delay (0x1E by default)
  1461.     .byte 0x18
  1462.  
  1463. .org 0x080C1D32 ;VineSprout (not flower sprout) post-delay
  1464.     mov r0, #0x40
  1465.  
  1466. .org 0x080AE923 ;Plantman Omega Movement Delay
  1467.     .byte 0x2A
  1468.  
  1469. .org 0x080AE92C ;Plantman Omega Movement Delay
  1470.     .byte 0x25
  1471.  
  1472. .org 0x080E0425 ;Old Wood Impact Effect... don't know how this got stored like this in data.
  1473.     .byte FlinchAndInvisImpact
  1474. ;--------------GUTSMAN PATCHES----------
  1475. ;.org 0x080B7DF0 ;gutsmans sets move counter here to 0xFF so Z-Punch attack no longer comes up
  1476. ;mov r0, #0x0 ;reset to 0 instead so he can use it again. this is the amount of moves he has done.
  1477.  
  1478. ;.org 0x080b7de8 ;gutsmans checks if his move count is same as this in order to activate Z-Punch
  1479. ;cmp r0, gutsmanMovesBeforeZPunch
  1480.  
  1481. ;.org 0x080b7dcc ;gutsman checks this value and if his hp is less he can use zpunch. by default it is division by 2 by shifting to the right by 1.
  1482. ;add r1, r1, 1 ;add 1 HP so its one over the max. Can use zpunch anytime now
  1483.  
  1484. .org 0x080b8590 ;gutsmans areagrab response chip
  1485. mov r0, grabbackfamily
  1486. mov r1, 0x1 ;grabrevenge sublevel
  1487. ldrb r2,[r5,#0x16]
  1488. mov r3,#0x32 ;50 damage per hit
  1489.  
  1490. ;-.org 0x080ae6a4 ;gutsman beta AI - delay after shockwave
  1491. ;-.byte 0x64 ;contact damage
  1492.  
  1493. .org 0x08019b68 ;flashman beta HP
  1494. .byte 0xe8
  1495. .byte 0x03 ;1000 HP 0x03e8
  1496.  
  1497. .close
  1498.  ; eof
Advertisement
Add Comment
Please, Sign In to add comment