546 - bombShield(int a, int script)
Sets the bomb invulnerability flag (a=0 false, a=1 true), the caller's ANM script will change to script when a bomb is active.
611 - etEx(int etId, int async, int type, float a, float b)
Adds bullet transformation to bullet manager etId, Transformation of flag type determines the specific behaviour of the bullet. Documentation can be found here.
BulletEffectType-67108864 - etExDelay(string et, string isAsync, string time)
Hide the bullet for time frames. During this time, it will not move, will be invisible and won't have a hitbox. If used as a first transformation, can be used to delay when the bullet actually appears.
6 - isDelayedSpawn
While this flag is set, the bullet will be invisible and not have a hitbox. This flag is cleared once the delay timer ends.
4 - short_timer
Integer value between -1 and 15 inclusive (by default -1). If non-negative, shooters using short_timer shoot their bullets and timer increments by 1 per frame until 15 is reached. Once 15, timer reset to -1 or 0 depending on Z key state.
5 - long_timer
Integer value between -1 and 120 inclusive (by default -1). If non-negative, shooters using long_timer shoot their bullets and timer increments by 1 per frame until 120 is reached. Once 120, timer reset to -1 or 0 depending on Z key state.
91 - floatTime(int slot, float var, int time, int mode, float start, float final)
In time frames using mode mode, variable var changes from start to final. slot is used to set the slot to be used by this ins, every enemy has 8 slots.
-9980 - F1
Local float variable, inherited by spawned enemies.
-9984 - I1
Local integer variable, inherited by spawned enemies.
-9989 - ANGLE_PLAYER
Angle from the enemy to the player.
-9962 - BOSS_Y
Final Y position of the boss.
-9990 - PLAYER_Y
Player's Y position.
-9963 - BOSS_X
Final X position of the boss.
-9991 - PLAYER_X
Player's X position.
81 - circlePos(float varX, float varY, float angle, float radius)
Performs following operation: varX = cos(angle) * radius and varY = cos(angle) * radius
-9981 - F0
Local float variable, inherited by spawned enemies.
300 - enmCreate(string sub, float x, float y, int hp, int score, int item)
Creates an enemy using subroutine sub at coordinates (x, y) (relative to position of the parent), health of created enemy is hp, score bonus is score and item drop is item.
601 - etOn(int etId)
Shoots bullet(s) using properties from bullet manager etId.
23 - wait(int time)
Stops sub execution for time frames.
1 - delete()
Returns to the top of current call stack.
2 - GAME_SPEED
The value controls by how much faster the game speed is run. This variable is often set to a number between 0 and 1. This value is often changed when a (final) boss dies or when a photo is taken. Its default value is 1.
-9985 - I0
Local integer variable, inherited by spawned enemies.
-9983 - I2
Local integer variable, inherited by spawned enemies.
-9982 - I3
Local integer variable, inherited by spawned enemies.
-9954 - ENEMY_HP
Enemy's current HP.
3 - goheiExists
A flag that determines if a gohei exists on-screen or not. Flag is set to true by active gohei. Flag is set to false if gohei goes off-screen or is despawning.
Item Collection Bonus Persisting
Specifications
- Versions:
1.00a -
1.00b
- Difficulty:
Easy -
Normal -
Hard -
Lunatic -
Extra
- Mode:
Main game -
Practice mode -
Spell practice - Shottype:
ReimuA -
ReimuB -
MarisaA -
MarisaB -
SakuyaA -
SakuyaB
What happens
It is possible for the player to continuously increase item count for the point of collection bonus while not actually activating the bonus.
How it happens
For this bug to happen, the player must be at a very precise y-coordinate. The y-coordinates differ per character since Marisa has a lower PoC height. In particular, the PoC heights are as follows:
- Reimu or Sakuya:
poc_height = 128 - Marisa:
poc_height = 148
As such, this is mainly feasible to replicate when normalizing the position, meaning the player would be aligned with the top/bottom of the screen and only move vertically to ensure the player y-coordinate is exactly equal to the poc_height

Why it happens
To understand this bug we must first understand the two mechanics that make up the Bonus mechanic:
- Bonus Timer: Timer that represents the time left before the player obtains the bonus.
- Bonus Item Count: Counter that keeps track of how many items have been collected for the bonus.
Bonus Timer
The Bonus Timer is a value between 0 and 8 inclusive. This timer represents the time left before the player obtains the bonus. Its default value is 0. The Bonus Timer is set to 8 when it meets ALL the following criteria:
player_height >= poc_height: the player must be above or at the PoC height.player_height != poc_height: the player must not be at the PoC height.
I wrote the list in this exact way because this is how it is represented in the code (for technical readers, assembly code can be found at offset of 0x43886a in 1.00b). Nonetheless, both conditions can be simplified to the following: player_height > poc_height.
The Bonus Timer remains at its maximum value of 8 as long as there is at least one item in the AUTO_COLLECT state. When an item is in the AUTO_COLLECT state, it flies straight towards the player. This state can be triggered through means such as bombing or going above the PoC height.
The Bonus Timer decreases by 1 every frame if there are no items in the AUTO_COLLECT state. When the Bonus Timer reaches 0, the player receives the Bonus.
Bonus Item Count
The Bonus Item Count increases when at least one of the following conditions are met:
player_height >= poc_height: the player must be above or at the PoC height.item_state == AUTO_COLLECT: the item must be in an autocollect state.
Additionally, the counter only updates if any of the following three items are picked up: small power item, point item, or big power item. When an item is picked up, the counter increments by 1. This counter is reset to 0 when the bonus is triggered as described in the previous section. The player receives a different Score Bonus depending on the Bonus Item Count.
The difference
It is immediately noticeable that there are two differing conditions. The Bonus Timer only starts ticking when player_height > poc_height, but the Bonus Item Count increases when player_height >= poc_height, so the difference between the two statements is player_height == poc_height. When player_height == poc_height, the Bonus Timer remains at 0, but the player can still increase the Bonus Item Count, assuming that all items have item_state != AUTO_COLLECT
Links
Replays
This section has no content yet. Would you like to add to this section? Contact me if you are interested!
Videos
This section has no content yet. Would you like to add to this section? Contact me if you are interested!
All Double Dealing Character pages: | |
|---|---|
| Score Underflow · Bulletless Kagerou · Marisa's Lasers · Barrier Bug · Gohei Duplication · Benben Spell 2 Crash · Screen-flipping Effect Undo · Slowdown Item Duplication · Timeouts on Tsukumo Sisters on Extra · Shinmyoumaru's 2nd Non-spell Bowl Breaking · Item Collection Bonus Persisting | All Frame-perfect-related pages: |