SMBX NPC AI

SMBX stores its AI values in special fields in the SMBX struct.

Para-Goomba (ID: 3)

 * 0x+F0 (ai1) Increments 1 per tick, at 32 the jumps are starting and it only increments one per jump until 35.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Piranha Plant (Green) (ID: 8)

 * 0x+F0 (ai1) Timer
 * 0x+F8 (ai2) Current AI phase (1=showing up [Tick 0-32; Then reset to 0], 2=showing [Tick 0-49; Then reset to 0], 3=hiding down [Tick 0-32], 4=hiding [Tick 33-74; Then reset to 0])
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Podoboo (ID: 12)

 * 0x+F0 (ai1) Timer
 * 0x+F8 (ai2) Current AI phase (1=jumping up, 2=fall down)
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Player Fireball (ID: 13)

 * 0x+F0 (ai1) Player-character logic to use for the fireball (1=Mario, 2=Luigi, 3=Peach, 4=Toad, 5=Link)

Boom Boom (ID: 15)

 * 0x+F0 (ai1) Current AI phase (0=running/walking, 1=spike mode, 2=transforming to spike mode, 3=jumping up)
 * 0x+F8 (ai2) Decimal Timer
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Bill Blaster (ID: 21)

 * 0x+F0 (ai1) Timer: Increments 1 per tick, at 200 one bullet bill is fired unless the player is over or underneath the blaster.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Billy Gun (ID: 22)

 * 0x+F0 (ai1) Timer: Increments 10 per tick when the player is holding the billy gun, at 200 one bullet bill is fired.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Ninji (Violet) (ID: 25)

 * 0x+F0 (ai1) Timer: When touching the ground then a timer decrements from 5 to 0. When the value is back to 0 then the ninji is jumping again.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Cheep-Cheep (Red) (ID: 28)

 * 0x+F0 (ai1) The selected Cheep-Cheep AI (From 0...)
 * 0x+F8 (ai2) Unknown
 * 0x+100 (ai3) Unknown
 * 0x+108 (ai4) 0 = Swim up, 1 = Swin down
 * 0x+110 (ai5) Unused

Hammer Bros. (ID: 29)

 * 0x+F0 (ai1) Timer: Direction Timer, if <0 then moving left, else moving right. Will reset about ~100 ticks (unknown)
 * 0x+F8 (ai2) Timer: Increments 1 per tick (while not shooting), if reaches 250 then super-jump is executed ==> Timer resets to 0
 * 0x+100 (ai3) Throwing releated. High number = more throws
 * 0x+108 (ai4)/110 (ai5) Unused

Super Leaf (ID: 34)

 * 0x+F0 (ai1) Timer: From 1 to 6. Controls the "swing"-effect for correct speed. When the value 6 is reached the direction of this swing is switched.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Thwomp (ID: 37, 180)

 * 0x+F0 (ai1) Current AI phase (0=idle, 1=going down, 2=staying down, 3=going up)
 * 0x+F8 (ai2) Timer: For state 2 => from 0 to 100; When hit value 100 then state is switched to 3.
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Boo (ID: 38, 43, 44)

 * 0x+F0 (ai1) Current AI phase (0=idle, 1=following player)
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Birdo (ID: 39)

 * 0x+F0 (ai1) Current AI phase (0=movement, 1=fire, or -30 to 0 if got hit)
 * 0x+F8 (ai2) Timer: Increments 1 per tick; if reaches 125 then jump, if reaches 250 then shoot, at 280 resets to 0
 * 0x+100 (ai3) Movement timer: Increments 1 per tick, when reached 500 ==> Direction changed
 * 0x+108 (ai4)/110 (ai5) Unused

Grab Block (ID: 45)

 * 0x+F0 (ai1) Current AI phase (0=untoched, 1=touched)
 * 0x+F8 (ai2) Timer: (Only in touched mode), 1 to 450; If reaches 450 then the block dissapears; If value is 0 in touched mode then the block is thrown and destroys itself on collision.
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Donut block (ID: 46, 212)

 * 0x+F0 (ai1) Current AI phase (0=idle, 1=falling)
 * 0x+F8 (ai2) 1 if someone is standing ==> Increments timer
 * 0x+100 (ai3) Timer: From 0 to 5 ticks for red version; 0 to 30 ticks for brown version
 * 0x+108 (ai4)/110 (ai5) Unused

Lakitu (SMB3) (ID: 47)

 * 0x+F0 (ai1) Movement related?
 * 0x+F8 (ai2) Unknown
 * 0x+100 (ai3) Current AI phase (0=???, 1=???, 2=normal movement?, 3=throwing)
 * 0x+108 (ai4) Direction Timer: Start from 100 decrementing 1 per tick. When reached 0 then Lakitu is changing direction. It only starts again counting when Lakitu reached the same position as the player.
 * 0x+110 (ai5) Timer: When timer starts (unknown?). Increments 1 per 6 ticks from 0 to 20. When 20 is reached one Spiky Egg is thrown.

Toothy Pipe (ID: 49)

 * 0x+F0 (ai1) Current AI phase (0=not holding, 1=holding)
 * 0x+F8 (ai2) NPC Array Index to find Toothy NPC Struct (NOTE: At high index experience laggs)
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Toothy (ID: 50)

 * 0x+F0 (ai1) Stays 1, if set to 0 then Toothy despawns
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Piranha Plant (Red, Upside-Down) (ID: 51)

 * 0x+F0 (ai1) Timer
 * 0x+F8 (ai2) Current AI phase (1=showing up [Tick 0-42; Then reset to 0], 2=showing [Tick 0-49; Then reset to 0], 3=hiding down [Tick 0-42], 4=hiding [Tick 43-109; Then reset to 0])
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Piranha Plant (Red Horizontal) (ID: 52)

 * 0x+F0 (ai1) Timer
 * 0x+F8 (ai2) Current AI phase (1=showing up [Tick 0-32; Then reset to 0], 2=showing [Tick 0-49; Then reset to 0], 3=hiding down [Tick 0-32], 4=hiding [Tick 33-109; Then reset to 0])
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Fighter Fly (ID: 54)

 * 0x+F0 (ai1) Timer: From 0 to 29. When reached value 29 then the jump is beeing made.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Platform (ID: 60, 62, 64, 66)

 * 0x+F0 (ai1) Speed X
 * 0x+F8 (ai2) Speed Y
 * 0x+100 (ai3) Unused/Unknown?
 * 0x+108 (ai4) Unused/Unknown?
 * 0x+110 (ai5) ID of Path riding on, if 0 then platform is using no path

Piranhacus Giganticus (ID: 74)

 * 0x+F0 (ai1) Timer
 * 0x+F8 (ai2) Current AI phase (1=showing up [Tick 0-42; Then reset to 0], 2=showing [Tick 0-49; Then reset to 0], 3=hiding down [Tick 0-42], 4=hiding [Tick 43-74; Then reset to 0])
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Toad (Jumping) (ID: 75)

 * 0x+F0 (ai1) Timer: [Tick 0-9 "Charging" Jump], [Tick 0-9 Jumping], When falling down timer stays at value 100... (strange algorithm)
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Para-Koopa (Green) (ID: 76, 121, 122, 123, 124)

 * 0x+F0 (ai1) The selected Para-Koopa (From 0...)
 * 0x+F8 (ai2) Unused/Unknown?
 * 0x+100 (ai3) For AI-State 2 (Hover left/right): Direction Flag for slightly going up/down.
 * 0x+108 (ai4)/110 (ai5) Unused

SMW Bowser Statue (ID: 84)

 * 0x+F0 (ai1) Increments 1 per tick, resetting when it shoots (shooting about Tick ~220 [Not fixed])
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

SMB3 Bowser (ID: 86)

 * 0x+F0 (ai1) Resets to 9 when starting to jump high and decrements 1 per tick. Not sure but may start arcing after it hits 0
 * 0x+F8 (ai2) Increments by a seemingly random number between 0.0 and 1.0 each tick. Resets from time to time but I don't can't tell exactly why.
 * 0x+100 (ai3) Increments by 1 per tick. Sometimes it gets reset to 0, but other times it gets reset to a negative number and counts back up to 0 to trigger something.
 * 0x+108 (ai4) Current AI phase (2=hopping, 3=jumping high+falling, 4=shooting fireballs, 10=turning right after hitting ground, -10=turning left after hitting ground)
 * 0x+110 (ai5) Other? (0=just after hitting ground, 1=other)

Herb (ID: 91)

 * 0x+F0 (ai1) The NPC ID of the content in the herb.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Piranha Plant SMB1 (ID: 93)

 * 0x+F0 (ai1) Timer
 * 0x+F8 (ai2) Current AI phase (1=showing up [Tick 0-32; Then reset to 0], 2=showing [Tick 0-49; Then reset to 0], 3=hiding down [Tick 0-32], 4=hiding [Tick 33-74; Then reset to 0])
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Colored egg (ID: 96)

 * 0x+F0 (ai1) The NPC ID of the content in the egg.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Star SMB3 (ID: 97)

 * 0x+F0 (ai1) Unused/Unknown?
 * 0x+F8 (ai2) Direction Flag (0 = fly up; 1 = fly down)
 * 0x+100 (ai3) Unused/Unknown?
 * 0x+108 (ai4) Direction Flag Timer (From 0 to 4; When 4 reset to 0 and toggle the Direction Flag)
 * 0x+110 (ai5) Unused

Wood platform (ID: 104)

 * 0x+F0 (ai1) The current Y-Speed
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Thin platform (ID: 105)

 * 0x+F0 (ai1) If the player stands on the platform, then this value is 1, else it is 0
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Bot (ID: 126, 127, 128)

 * 0x+F0 (ai1) AI-State (2 = Moving [Tick 0-119], 1 = Charging [Tick 0-89 or 29], -1 = Jumping [Tick stays at 0 until reaching the floor]). Note: The AI States are quite random.
 * 0x+F8 (ai2) Timer
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Tweeter (ID: 129)

 * 0x+F0 (ai1) Jump Timer: 0 to 3, on every jump this timer increases by 1 until it reaches value 3. Then the next jump is a high jump and the timer resets to 0.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Snifit (Red/Blue) (ID: 130, 131)

 * 0x+F0 (ai1) Timer: From 0 to 120 = Movement, from 121 to 149 = Init Fire, after that fire and the timer reset to 0
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Snifit (Gray) (ID: 132)

 * 0x+F0 (ai1) Timer: Unknown
 * 0x+F8 (ai2) Jump Timer: 0-99 to Jump with 0x+100 (ai3) is 0, 0-40; 91-99 with 0x+100 (ai3) is 2.
 * 0x+100 (ai3) Shoot related, 0 = (shoot nothing?); 2 = Shoot twice?, [Note: very unclear!]
 * 0x+108 (ai4)/110 (ai5) Unused

Mouser's Bomb (ID: 134)

 * 0x+F0 (ai1) Timer (until explode): 0-349 until explode; When 250 reached then AI-State is 1.
 * 0x+F8 (ai2) AI-State: 0 = Idle, 1 = Short before exploding
 * 0x+100 (ai3) Bomb animation state: 0-14 repeating when AI-State is 1.
 * 0x+108 (ai4)/110 (ai5) Unused

Bob-Omb (SMB2) (ID: 135)

 * 0x+F0 (ai1) Timer (until explode): 0-549 until explode; When 450 reached then AI-State is 1.
 * 0x+F8 (ai2) AI-State: 0 = Idle, 1 = Short before exploding
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Bob-Omb kicked (SMB3) (ID: 137)

 * 0x+F0 (ai1) Timer (until explode): 0-349 until explode; When 250 reached then AI-State is 1.
 * 0x+F8 (ai2) AI-State: 0 = Idle, 1 = Short before exploding
 * 0x+100 (ai3) Bomb animation state: 0-10 repeating when AI-State is 1.
 * 0x+108 (ai4)/110 (ai5) Unused

Galoomba Kicked (SMW) (ID: 166)

 * 0x+F0 (ai1) Timer (until standing back up): 0-399 until standing back up.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Para-Galoomba (SMW) (ID: 167)

 * 0x+F0 (ai1) Timer/AI-State: 0-61 Simple Movement; 62 First Jump and lock on to the Jump-Timer; 63 Second Jump; 64 Third Jump; 65 Fifth Jump;
 * 0x+F8 (ai2) Jump Timer: AI-State 62-64: Increment 1 per tick, from 0-15; AI-State 65: Increment 2 per tick; When reched 15, then jump if possible.
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Bully (SM64) (ID: 168)

 * 0x+F0 (ai1) Unknown/Unused?
 * 0x+F8 (ai2) AI-State: 0 = following player, 1 = kicked off by player
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Grinder (Circular saw) (ID: 179)

 * 0x+F0 (ai1) Grinder Speed Y
 * 0x+F8 (ai2) Grinder Speed X
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Bowser's statue (ID: 181)

 * 0x+F0 (ai1) Timer: 0-230 until shoot.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Dry Bones (ID: 189)

 * 0x+F0 (ai1) 0=Up walking around, 1=Collapsed
 * 0x+F8 (ai2) When broken, increments by 1 per tick until 400 at which point it gets up
 * 0x+100 (ai3) Alternates between 1 and 0 when wiggling (0x+F8 (ai2) between 300 and 400)
 * 0x+108 (ai4)/110 (ai5) Unused

Skull Raft (ID: 190)

 * 0x+F0 (ai1) AI-State: 0 = Idle, 1 = Active Moving
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Kamikaze Koopa (ID: 194)

 * 0x+F0 (ai1) Unknown/Unused?
 * 0x+F8 (ai2) Unknown/Unused?
 * 0x+100 (ai3) Unknown/Unused?
 * 0x+108 (ai4) Unknown/Unused?
 * 0x+110 (ai5) Animation Timer 0-15: The current color of the shell.

Takeable Star (ID: 196)

 * 0x+F0 (ai1) Unused/Unknown?
 * 0x+F8 (ai2) Direction Flag (0 = fly up; 1 = fly down; This flag gets toggled after running the animation timer 14 times (5 animation frames * 14 = 70 frames total per direction)
 * 0x+100 (ai3) Unused/Unknown?
 * 0x+108 (ai4) Animation Timer (From 0 to 4)
 * 0x+110 (ai5) Unused

SMW Exit point (ID: 197)

 * 0x+F0 (ai1) Direction Flag (1 = move up; 0 = move down)
 * 0x+F8 (ai2) The lower y coordinate. This y coordinate toggles the direction flag from moving down to moving up. Modifying this flag has no effect!
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Blargg (ID: 199)

 * 0x+F0 (ai1) AI-State (0 = idle; 1 = looking; 2 = moving)
 * 0x+F8 (ai2) Timer - AI-State 1: 0 to 89; AI-State 2: Stays at 90 until moving animation finished.
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

SMB1 Bowser (ID: 200)

 * 0x+F0 (ai1) 0: Walking, 1: Pre-fire, 2: spitting fire
 * 0x+F8 (ai2) The direction Bowser is moving, not facing. 0 is left, 1 is right.
 * 0x+100 (ai3) Fire timer, after spitting fire increments up to around 60
 * 0x+108 (ai4) Some sort of Hammer related timer, noted below.
 * 0x+110 (ai5) Unknown, always 1 (SMBX forces it to be 1) [Related to 2-player mode]

0x+108 (ai4) Details
(where tableOfBowser is a table of the active SMB1 Bowsers returned by `NPC.get(200, -1)`)
 * The timer is mostly random
 * However, repeatedly setting the values based on a range can modify the rate at which hammers are thrown. For example:
 * The internal ai4 equals to this C++ pseudocode
 * Note that in the Lua code, we set the value to 15. In the C++ code, the random spawn rate is based on a modulus of 16. This is due to the fact that when setting the value in Lua, it is automatically incremented to 1 above of what is set.

Wart (ID: 201)

 * 0x+F0 (ai1) AI-State: 0 - Idle, 1 - Bubbles; 2 - Got hit; 3 - Death
 * 0x+F8 (ai2) Walking Direction: 1 - left; -1 - right
 * 0x+100 (ai3) Timer (Idle: 0 to 180; Bubbles: 0 to 130)
 * 0x+108 (ai4) Death timer (0 to 120)
 * 0x+110 (ai5) Unused

Zoomer (ID: 205), Spark (ID: 206), Spike Top (ID: 207)

 * 0x+F0 (ai1) Walking side: 0 - in air (falling down), 1 - Walking on top side, 2 - Walking on left side, 3 - Walking on bottom side, 4 - Walking on right side
 * 0x+F8 (ai2) Unknown: Is -1 on top and right side, is 1 on left and bottom side
 * 0x+100 (ai3) Unknown Timer
 * 0x+108 (ai4) Unused/Unknown?
 * 0x+110 (ai5) Edge Timer: If hitting an edge, then timer starts from 1 to 6. When reaching value 6 then the NPC is switching walking side.

Mother Brain (ID: 209)

 * 0x+F0 (ai1) Shaking Timer: 0 to 44 (0 = Idle, otherwise lower value means harder shake)
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Rinka (ID: 210)

 * 0x+F0 (ai1) AI-State: 0 = Waiting, 1 = Moving
 * 0x+F8 (ai2) Timer for AI-State 0: From 0 to 88; When reaching 88, then AI-State is switched to 1 (Moving)
 * 0x+100 (ai3)/108 (ai4)/110 (ai5) Unused

Rinka block (ID: 211)

 * 0x+F0 (ai1) Spawn Timer: 0 to ~200 (Increments about 1 to 2 per tick [i.e. 1,835...]); If the value reaches over 200 then a new Rinka NPC is spawned. Then is it switched back to 0.
 * 0x+F8 (ai2)/100 (ai3)/108 (ai4)/110 (ai5) Unused

Lakitu (SMW) (ID: 284)

 * 0x+F0 (ai1) Thrown NPC identity
 * 0x+F8 (ai2) Init to 1, set to 0 a little while after throwing
 * 0x+100 (ai3) 0=Haven't yet passed over player, 2=Getting ready to throw, 3=Like 0 but after having thrown before
 * 0x+108 (ai4) When getting ready to throw, resets to 100 and starts decrementing. Throws once 0 again.
 * 0x+110 (ai5) Always increments 1 per tick, resets to 0 after throw

Toad's Boomerang (ID: 292)

 * 0x100 (ai1) (FIELD_DFLOAT) Unknown. Init to 1
 * 0x110 (ai5) (FIELD_DFLOAT) Follows player character (1 is follows)