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.

503 - flagClear(int n)


Clears flag(s) according to n. Refer to the flag table here for exact values.

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.

(Sub-)shottypes Not Functioning


Specifications


  • Versions: 1.00a
  • Difficulty: Easy - Normal - Hard - Lunatic - Extra
  • Mode: Main game - Practice mode - Spell practice
  • Shottype: ReimuSpring - CirnoSpring - AyaSpring - MarisaSpring - ReimuSummer - CirnoSummer - AyaSummer - MarisaSummer - ReimuAutumn - CirnoAutumn - AyaAutumn - MarisaAutumn - ReimuWinter - CirnoWinter - AyaWinter - MarisaWinter - ReimuExtra - CirnoExtra - AyaExtra - MarisaExtra

What happens


Occasionally, the player's (sub-)shottypes do not work in which case their bullets are not shot. This affects the shottypes Cirno (focus and unfocus shot) and Aya (unfocus shot). This also applies to the subseasons Spring, Summer and Autumn. This issue can be resolved by releasing Z for about half a second.

How it happens


To activate this condition, the player must involve releasing and holding Z multiple times. In particular, the following needs to be done:

  1. The player must press Z.
  2. The player must press Z again anywhere between 104 and 119 frames after the initial Z input.
  3. The player must hold Z 120 frames after the initial Z input.

This sequence of actions is very easy to do accidentally meaning that it isn't uncommon to encounter this problem.

Why it happens


In this game, each player's shooter is controlled by two timers (short_timer and long_timer), which determine when bullets are fired by the player. short_timer operates on a 15-frame interval, and long_timer operates on a 120-frame interval.

The shooters that use long_timer are Cirno (focus and unfocus shot), Aya (unfocus shot) and the subseasons Spring, Summer and Autumn; the other shooters use short_timer. The reason why some shooters are using long_timer is because those shooters have been manually assigned to long_timer by ZUN. In other words, ZUN made the decision to assign long_timer to certain shooters himself.

Both timers have a default value of -1. Whenever the player presses the Z key, both timers increment by 1 every frame: short_timer increments to 15 and long_timer increments to 120. Once their treshold is reached, the game looks at the current Z input. If Z is held, the timer is set to 0, otherwise the timer is reset to -1. This explains why if you press Z even for one frame, the player continues to shoot bullets for 15 frames instead of immediately stopping.

The player can only shoot bullets only if short_timer is a value between 0 and 15. This means that the player bullets from long_timer are dependent on short_timer: if long_timer is ticking but short_timer is -1 then no bullets of long_timer are be shot.

For long_timer to go from -1 to 0, short_timer also needs to go from -1 to 0. In other words, to activate long_timer, short_timer also needs to be activated simultaneously. In pseudocode its the following:

if (short_timer < 0) {
    if (long_timer < 0) {
        [...] // logic that activates long_timer
    }
}

This proposes a slight issue. If short_timer is already active (i.e. its value is between 0 and 15), then long_timer cannot go from -1 to 0. We can achieve this problem by running both timers by pressing Z. Once both timers are active, we stop short_timer by releasing Z. This pause in short_timer creates a misalignment between the two timers' cycles. After this, we press Z again to restart short_timer while long_timer continues its cycle independently. We then release Z to fully reset long_timer to -1: long_timer stops completely. By holding Z once more, we ensure that short_timer stays active: we end up with a situation where short_timer runs while long_timer remains inactive.

Is Z button held?
short_timer -1 0 1 2 -1 0 1 2 3
long_timer -1 0 1 2 117 118 119 -1 -1

Because long_timer has stopped, it means that the shooters that use long_timer are inactive, thus those shooters do not produce any bullets. However, shooters that use short_timer still produce bullets.



Replays


This section has no content yet. Would you like to add to this section? Contact me if you are interested!

Videos