GameMaker Touhou Engine   Home   Downloads   Documentation
Jump to:

Beta 1.3 Changelog


Added:


-Last Word spells:

   -Spells can now be marked as Last Words and are listed in their own special category inside spell practice.

   -They can be unlocked when certain conditions are met, and can also have a description on how to meet said condition that shows up in spell select.

      -Of course, due to how arbitrary those conditions can be, their validation has to be implemented independently.

   -Information regarding Last Words is stored in the same fashion as the rest of spell card data.

   -In accordance to this, a new reserved difficulty value has been added. The value of 9 now represents the Last Word difficulty and all Last Words are registered only for this difficulty.

      -Also, when registering Last Words, the "previously encountered spells" attribute is irrelevant. However, there shouldn't be any gaps in the values used as the Last Words are sorted by that attribute inside the menu.

-Conditional bullet behaviors:

   -Bullets can now also be given behaviors to perform in response to certain things.

   -Currently, the configurable events are for when a bullet gets close enough to a player and when it's speed reaches a certain amount.

   -As more possibilities are added, these will remove the need to create separate bullet objects in most cases.

-New Scripts:

   -_ENEMY_SPELL_SET_LAST_WORD(): Register a spell as a Last Word.

   -_ENEMY_SPELL_UNLOCK_LAST_WORD(): Make a Last Word available for play in spell practice.

   -_ENEMY_SPELL_LAST_WORD_LOCKED/UNLOCK_CONDITION(): Get a piece of data regarding a Last Word.

   -_BULLET_CLEAR_BEHAVIOR(): Make it so a bullet's behavior will be ignored on the next cycle of repetition (see below).

   -_BULLET_SET_EV_BEHAVIOR(): Configure which behavior will be performed by a bullet when a certain condition is met.

   -_BULLET_SET_EV_BEHAVIOR_C(): Configure which behavior will be performed by a bullet which hasn't been spawned yet when a certain condition is met by targeting it's delay cloud.

-New macros:

   -_BULLET_BEHAVIOR_CHANGE_SPRITE for changing a bullet's sprite.

   -_BULLET_BEHAVIOR_BOUNCE for making a bullet bounce as if it collided with a solid surface.

   -_BULLET_BEHAVIOR_ADD_BEHAVIORS for adding additional behaviors that a bullet should perform.

   -_BULLET_BEHAVIOR_SET_EV_BEHAVIOR for changing the behavior a bullet should perform when a specified condition is met.

   -_EVENT_BEHAVIOR... signify unique numerical identifiers for different events in the new system (see above).

   -_LAST_WORD_COUNT signifies the total number of Last Words.


Modified:


-Script changes:

   -_UPDATE_RESULTS_FIRST_TIME() should have all of the Last Word declarations added to it at the bottom of the script.

-Miscellaneous:

   -Items now display a marker when they're above the top HUD border.

   -The boss' X position can now also be seen at the bottom of the screen when one is present (can be turned off, configured in _HUD_DRAW).

   -Delay clouds now have extra parameters for event behaviors.

   -Bullet behaviors whose ID is set to undefined are now ignored when behaviors are cycled through.

-Bugfixes/Optimization:

   -Removed some leftover uses of legacy systems.

   -Fixed a bug where the example bosses weren't moving during spell practice.


Beta 1.0 Changelog


Added:


-Advanced, easily customizable behavior patterns for bullets:

   -Bullets have new local variables relating to a new behavior system.

   -This system dictates special actions that the bullet peforms at specified or regular intervals, such as speeding up, turning or curving.

      -The timing of these behaviors is easy to customize with built-in systems to handle timers and repetitions.

      -They can also be preemptively added onto delay clouds before the bullet itself is even created.

   -In accordance to this, some bullet objects with special behaviors have been removed.

-Curvy lasers:

   -Two new objects, _CURVY_LASER_HEAD/TAIL_PARENT.

   -These objects signify the start/end points of a single bezier curve that represents a curvy laser.

   -The laser is drawn using many smaller segments, merged into a single sprite with a precise collision box.

   -The new behavior system is also applicable to these, but in a more limited scope.

-Customizable movement patterns for bosses:

   -Similar to bullet behaviors, the movement of bosses can now also be customized much more easily.

   -Bosses can move to a fixed point or randomly within a bounded space.

   -They also now handle deaccelerated movement by default.

-New Scripts:

   -_BULLET_ADD_BEHAVIOR(): Add a behavior to a bullet.

   -_BULLET_ADD_BEHAVIOR_C(): Add a behavior to a bullet that hasn't spawned yet by targeting it's delay cloud.

   -_ENEMY_BOSS_SET_MOVE...(): Modify various parameters regarding a boss' movement.

   -_BULLET_CREATE_CURVY_LASER(): Fires a curvy laser with the given parameters.

   -_MISC_GET_ARRAY(): A utility script that creates an array from it's arguments.

   -_MISC_GET_BEZIER_POINT(): A utility script that helps calculate the math regarding bezier curves, for drawing curvy lasers.

-New macros:

   -_BULLET_BEHAVIOR... signify unique numerical identifiers for different bullet behaviors.

   -_BOSS_MOVE... signify unique numerical identifiers for different boss movement patterns.

   -_POWER_LOSS... signify parameters regarding how much power is lost by the player when losing a life.

      -Modify these macros according to your own game.


Modified:


-Consistency:

   -In accordance to the new boss movement system, deacceleration for boss objects is now implemented in the parent object and not in individual child objects.

   -The same is true for the old type of movement implemented in _REIMU_BOSS.

-Bugfixes/Optimization:

   -Fixed a bug where _BULLET_CREATE_ARC() could crash the game.

   -Fixed some of the example timelines not working as intended.


Alpha 2.4 Changelog


Added:


-The ability to replay practice runs:

   -Replays now have an extra piece of data indicating the type of replay, with the header being different for different types.

   -During the replay itself, that type is stored in a new global variable, global._REPLAY_TYPE.

-New macros:

   -_NUM_STAGES signifies the number of total stages.

   -_NUM_STAGES_B signifies the number of non-extra stages.

   -Modify these macros according to your own game.


Modified:


-Practice Object Changes:

   -In accordance to the new macros being added, the local variables that store stage numbers in the practice stage/spell selection objects have been removed.

   -The replay saving UI is no longer skipped over in practice modes when finishing stages or not retrying spells.

-Item Changes:

   -In order to resemble the ones from actual Touhou games more, items now continue moving towards players even while they're not focusing or have moved below the POC.

   -Items will now also start moving towards the player if they are hit by a bomb.

-Bugfixes/Optimization:

   -During dialogue, cutins of characters that are currently speaking will now always be drawn in front of non-speaking ones.

   -global._STAGE_OBJECT now stores object indexes instead of instance IDs for more versatility.


Alpha 2.3 Changelog


Added:


-Stage/Spell Practice:

   -New object: _PRACTICE_STAGE_SELECT.

      -An object that allows the player to select a stage to practice.

      -Data regarding these is stored inside "score.dat".

      -A separate high score is kept for each stage achieved with each player and difficulty.

   -Spells are now stored in "score.dat" differently, using unique IDs (see documentation).

      -In accordance, the old scripts for changing spell data have been removed.

   -New global variables:

      -global._SPELL_ENCOUNTERS: used to keep track of how many spells the player has encountered during play.

      -global._NULLITY: whether or not the player is in the special "nullity" state. For clarity, see the last spells/last words in

   -New objects for spell practice:

      -_PRACTICE_SPELL_SELECT: The object in charge of the spell practice menu.

      -_SPELL_PRACTICE_OBJECT: The object in charge of the spell practice gameplay.

      -_SPELL_PRACTICE_RETRY: The object that replaces the continue menu with a retry menu within spell practice.

-New Scripts:

   -_UPDATE_..._PRACTICE_STAGE(): Update a piece of data about a stage in stage practice.

   -_UPDATE_GET_PRACTICE_STAGE_...(): Fetch a piece of data about a stage in stage practice.

   -_ENEMY_BOSS_SET_PARAMS(): Easily initialize the attributes of a boss fight, removing the need to hardcode things into boss' create events.

   -There's also a variety of scripts related to the new spell card system, check the _ENEMY category in the documentation for more information.


Modified:


-Replay system (FUNCTIONAL):

   -Fixed the remaining causes of desynchronization, meaning replays are now in a usable state.

-Script changes:

   -The cutin argument in _ENEMY_DECLARE_SPELL() can now be set to noone for there to be no cutin.

   -_DESTROY_BULLET_ALL() now also interrupts delay clouds preventing further bullets from being created right after the script is called.

   -_UPDATE_RESULTS_FIRST_TIME() now also locks the spell practice function.

-Timeline System:

   -Timeline objects have a new local variable, _RUNNING which dictates whether the timeline is running or not.

   -The logic for it has to manually be implemented for each timeline object.

-Bugfixes/Optimization:

   -Data regarding spell cards is now saved immediately into "score.dat" removing the need for global._SPELL_MAP_TEMP.

   -Fixed a bug where players could retain the bomb invincibilty frames and still get a spell card bonus as long as the boss never touched the bomb.

   -Fixed a bug where players could avoid dying by standing still inside a non-moving hurtbox.

   -Fixed a bug where _BULLET_CREATE_STREAM() could create infinite bullets.

   -Removed the need for _BOMB_IMMUNE_ENEMY_BULLET_PARENT to store copied code from it's parent object.

   -Changed some instances of _PLAYER_PARENT to global._PLAYER in the code for consistency reasons.

   -Removed some leftover debug data.


Alpha 2.0 Changelog


Added:


-Stationary/Anchored Lasers:

   -New object: _LASER_GENERATOR_PARENT_S.

      -An object that creates and maintains stationary lasers.

      -These lasers are always tethered to their generator, and the generator can also tether to an object.

      -The laser doesn't actually have a hitbox until it's fully formed, with the appearing/disappearing animations being handled with particles.

-Custom Timeline System:

   -New object: _TIMELINE_SURROGATE_PARENT.

      -The children objects of this one should have a large switch statement in their step event which performs different actions (see the existing objects for examples).

      -This system is free of the inconsistent step updating of the built-in timelines.

      -It's also flexible, allowing the manipulation of multiple timelines at once without the complication of having to keep track of timeline_index.

      -In accordance, objects which utilized timelines now use objects instead.

-Dialogue Choice:

   -The formatting rules in _DRAW_MARKUP_STRING() now support naming choices that the player can make (similar to Imperishable Night stage 5).

   -Each choice results in a specified timeline object being created.

-Multiple Bosses:

   -Bosses have a new variable, _SECONDARY_BOSS.

      -All boss objects should have it set to true except for one.

      -The boss object for which it's set to false will control the logic for all of the present boss objects.

   -In accordance, _HEALTH_DRAW no longer assumes only one boss is present.

-New Scripts:

   -_BULLET_CREATE_LASER_S(): Create a stationary laser.

   -_ITEM_MAKE_ARRAY(): A simplified way to generate an array of items for use with enemies (see documentation page for details).


Modified:


-Script changes:

   -_ENEMY_CREATE() now takes an additional argument for a death effect, allowing it to be set upon creation.

   -_BULLET_CREATE_LASER...() scripts now set sprite origins properly.

-Replay changes (NOT IN FUNCTIONAL STATE):

   -Inputs are now recorded through the player object for less complication, removing the need for a separate recorder object.

   -The individual bytes in the replay file now store player actions rather than keyboard inputs, uniting the global._REPLAY_EV... variables into one.

   -Replay ghosts now have a parent object that loads a byte from the replay buffer at the beginning of every step.

-Bugfixes/Optimization:

   -Completely removed the use of keyboard and collision events for consistency reasons, as they can sometimes be registered with a one-frame difference in replays.

   -Player movement, shooting and bombing are now controlled by variables which are constant for one given frame and are set at the beginning of each step.

   -Fixed a bug where spell capture counts would go up during replays.

   -Fixed a bug where the player would sometimes not respawn after continuing due to global._PLAYER_DEAD being set incorrectly.

   -Stemming from the collision changes, player bullets which aren't supposed to can no longer hit multiple enemies lined up behind one another (as long as they don't overlap).

   -Fixed a bug where boss health bars weren't being drawn in between phases.

   -Fixed a bug where the cutin of the character who has the first speaking line in a dialogue sequence could show up as invisible before the dialogue starts.


Alpha 2.0pre Changelog


Added:


-Replay System (NOT IN FUNCTIONAL STATE):

   -New objects: _REPLAY_RECORDER/_REPLAY_PLAYBACK.

      -Objects that record/play replays as their names suggest.

      -Replays are stored in a binary file format created specifically for use in GMTE.

      -Playback is done in a special room intended for use with a special object that mimics player actions based on recorded inputs (see _REIMU_REPLAY_GHOST for an example).

   -New object: _SAVE_REPLAY.

      -Serves the same function as _INPUT_RESULTS, but for replays.

   -New global variables:

      -global._REPLAY_DATA is a buffer that stores data about a play sesssion while a replay is being recorded.

      -global._REPLAY_EV... is a set of variables that stores data about which inputs are being pressed during a replay's playback.

-Laser Flexibility:

   -Lasers now have death animations, just like bullets do.

   -Instance IDs of lasers can now also be grabbed after they're created using a new script: _BULLET_GET_LASER().

-Heavily Streamlined Bullets:

   -Removed the need for separate bullet objects entirely save for bullets with special behavior or bomb-immune bullets.

   -Bullets can now have their sprites and death effects set upon creation.

   -They also have a new variable _SYNC_ANGLE that dictates whether their sprite should rotate with them.

   -New global variable, global._STANDARD_BULLET_DEPTH which dictates the depth that bullets are drawn at by default.

-Even Better Particles:

   -Objects that inherit from either of the _DISAPPEARING_PARTICLE objects can now have dynamically created sprites.

   -They have a new variable, _SPRITE_DYNAMIC which dictates whether the resources used by the sprite should be freed upon the particle being destroyed.

      -Be very careful, as using this wrongly can lead to resources being permantently deleted from the game.


Modified:


-Script changes:

   -In accordance to the bullet changes, the _BULLET_CREATE...() now take additional arguments, i.e. the sprites, death effects and whether to sync the image angle with the bullets' movement angle.

      -_BULLET_CREATE_LASER() only has a new argument for the death effect however.

   -_DRAW_CREATE_DISAPPEARING_PARTICLE() also has a new argument that says whether or not the sprite used for the particle is a dynamic resource.

-Changes related to replays:

   -Several objects that relied on input-based events have been modified in accordance to the newly-added replay system.

      -Examples include _HITBOX_OBJECT and the dialogue-related _SYSTEM objects.

      -The events that used to trigger based on keyboard inputs now have user-defined triggers.

      -They are manually triggered within the keyboard events unless a replay is being played back.

-Bugfixes/Optimization:

   -Fixed a bug where bosses were being drawn on top of their bullets.

   -Fixed several instances of ord() being used with keyboard_check in a non-standard way.

   -Fixed the inconsistent variable types inside the _REIMU object.

   -Replaced all instances of round(random_range()) with irandom_range() for better readability and to avoid potential inconsistencies related to decimal rounding.


Alpha 1.7 Changelog


Added:


-Loose Lasers:

   -New object: _LASER_PARENT.

      -Effectively just a bullet that uses a duplicated sprite.

   -New object: _LASER_GENERATOR_PARENT.

      -An object that fires lasers.

      -Handles most of the logic in relation to creating them, much like delay clouds.

-Survival Cards:

   -New global variable: global._SURVIVAL_CARD.

      -Indicates whether or not the ongoing spellcard is a survival card.

      -If it is, the spell bonus will be given even if the boss' timer runs out.

-Streamlined Particle Effects:

   -New objects: _DISAPPEARING_PARTICLE and _DISAPPEARING_PARTICLE_ALARM.

      -Can be used to create particle effects without the need for a specific object for each one.

      -In accordance to this, a lot of objects which were simply used as particles have been removed.

-New Scripts:

   -_ENEMY_SET_UNTARGETABLE(): Makes a given stage enemy or boss untargetable. (see below)

   -_DRAW_CREATE_DISAPPEARING_PARTICLE(): Creates a particle effect with a given sprite, depth etc.

   -_BULLET_CREATE_LASER(): A script that fires a laser.


Modified:


-Script changes:

   -_ENEMY_DECLARE_SPELL() now requires you to specify whether or not the spell is a survival card.

   -The _BULLET_CREATE...() scripts now take a sprites instead of an object for the delay clouds, removing the need for separate objects entirely.

      -In accordance to this, all of the different delay cloud objects have been removed.

   -_DESTROY_BULLET_ALL() now destroys laser generators too, as otherwise they'd stay in their animation forever after the lasers themselves are gone.

-Enemy changes:

   -Enemies and bosses can now be made untargetable.

   -This means player shots will simply phase through them, and they will not hurt the player upon collision.

-Bullet changes:

   -Bomb immune bullets now inherit from normal bullets to reduce the amount of duplicate code.

   -They also no longer disappear when hitting the player.

-Bugfixes/Optimization:

   -Fixed a bug where bullets sometimes wouldn't deaccelerate properly.

   -Fixed a bug where bomb immune bullets wouldn't get grazed properly.

   -_RESULTS_SCREEN no longer restarts the room when you exit it, instead returning to the title screen like the other menu objects.


Alpha 1.5 Changelog


Added:


-Dialogue System:

   -New object: _DIALOGUE_CONTROLLER.

      -Controls and draws a given dialogue sequence.

      -Dialogue sequences are dictated by special strings for which characters are speaking and what the text is.

   -New object: _DIALOGUE_EVENT_HANDLER_STG1.

      -An example object that shows how one would go about making specific things happen in the middle of a dialogue sequence.

   -New global variable: global._DIALOGUE_ACTIVE.

      -Signifies whether or not dialogue is in progress.

      -While dialogue is in progress, the player and bosses cannot attack, and bosses cannot move.

-Spell Card History System:

   -New global variable: global._SPELL_MAP_TEMP.

      -A ds_map that stores values for how many each spell card has been attempted/captured during play.

      -Similar to the high score, the content of this map is added into global._DATA_MAP after the results input screen, then saved into "score.dat".

      -The keys are unique arbitrary names for each spell, represented by short strings.

-New Globals:

   -global._PLAYER_FAMILIAR: Stores the object used for shooting the player's secondary shots, such as Reimu's Yin-Yang orbs.

   -global._DATA_MAP: The ds_map that stores data such as the high score.

      -It's declared in a new room _DATA_LOAD_ROOM which is loaded before everything else, by a new persistent object _DATA_LOADER.

-New Scripts:

   -_UPDATE_INIT_DIALOGUE(): Begins a given dialogue sequence.

   -_UPDATE_UNINIT_DIALOGUE(): Ends the active dialogue sequence.

   -_ENEMY_SPELL_GET_...(): Returns the amount of times a given spell card has been attempted/captured.

   -_UPDATE_SPELL_...(): Updates the amount of times a given spell card has been attempted/captured.


Modified:


-Script changes:

   -_DRAW_TEXT_BORDER() now supports custom alpha values.

   -Scripts that change values within ds_maps now use accessors.

   -_ENEMY_DECLARE_SPELL() now requires an "internal name" for the spell which tells the game how to refer to the specific spell being declared and a ds_map to update the amount of times the given spell has been attempted.

-Boss changes:

   -Bosses now have a new variable: _CURRENT_SPELL_NAME.

   -Signifies the "internal name" of the active spell card, and should be updated through timelines.

-Bugfixes/Optimization:

   -Items now move to the player's hitbox properly when they are collected, rather than disappearing at a distance.

   -The ..._TIMER... variables in _REIMU are now booleans.

   -The example bosses no longer occasionally fire off a few extra bullets after death if they are killed at a specific moment.

   -Bosses now have enough delay between patterns to ignore potential bomb damage that carries over from a previous pattern.

   -If a bomb does manage to damage them in this way, the spell card bonus now properly gets set to 0 in this scenario too.

   -The player's power is now an integer that goes up to 400 rather than a real value that goes up to 4, in order to make calculations easier.

   -The ds_map that stores the data such as the high score is now one global variable for ease of access. This also makes it so all data can be stored inside one file.

   -Fixed a bug where the player could keep their hitbox visible while unfocused if they paused while holding shift, and cleaned the code that regulates the animations up.

      -Cleaned the code that regulates the animations for _FOCUS_AURA up as well.


Alpha 1.3 Changelog


Added:


-Parent object for delay clouds, _DELAY_CLOUD_PARENT:

   -Delay clouds now have two new variables: _FIRST_ANIMATION and _SECOND_ANIMATION.

      -_DELAY_CLOUD_PARENT performs a more generalized version of the code that each delay cloud used to call at the end of their animations.

      -_FIRST_ANIMATION is set to sprite_index on creation by default.

      -Child delay clouds now only call event_inherited() and set their _SECOND_ANIMATION upon being created.

-Hi-Score system:

   -New global variable: global._HI_SCORE, which stores the high score during play.

   -New object: _HI_SCORE_CONTROLLER, which monitors the high score and displays it on the HUD.

      -Results are permanently stored in the file score.dat.

      -score.dat works like a standard INI file, encrypted using the built-in ds_map system. It stores the 10 best achieved scores in rank1 through rank10.

      -It also stores the names corresponding to each score in name1 through name10.

      -There's also plrank which stores the best player-achieved score.

   -New object: _RESULTS_SCREEN which simpy loads and draws the top 10 scores stored in score.dat.

      -_RESULTS_SCREEN is meant to be used in conjunction with the other menu screen objects like _TITLE_OBJECT and _CHARACTER_SELECT.

   -New object: _INPUT_RESULTS which the player is meant to access after beating the game, not continuing after running out of lives, or running out of continues.

      -_INPUT_RESULTS is stored in a separate room, _RESULTS_ROOM. It allows the player to input a name, if they've made it into the top 10 scores. It then stores the updated info in score.dat.

-New Scripts:

   -_BULLET_GET(): returns the bullet created by a given delay cloud. (see below)

   -_UPDATE_RESULTS_FIRST_TIME(): writes the default score values into a given ds_map.

   -_UPDATE_RESULTS(): inserts a given name and score into the proper position inside a given ds_map.


Modified:


-Script changes:

   -All of the previously existing _ENEMY_CREATE...() scripts have been combined into _ENEMY_CREATE().

      -The alarm/path-related arguments can be ignored by setting them to noone.

   -All of the _BULLET_CREATE...() scripts now return the id (or array of ids) for the delay clouds set to create the bullets themselves.

   -_DESTROY_IF_OUTSIDE_BOUNDS(): Now setting an argument to noone will make the script ignore it (as opposed to setting it to -1).

   -_FAMILIAR_CREATE(): Now setting alrm to noone will make the script ignore it.

   -_DRAW_DIGIT...() and _DRAW_COLLECTIBLE(): Now sensically return void instead of an integer/real number.

-Delay cloud changes:

   -Delay clouds have a new variable: _CREATED_BULLET_ID.

      -This variable stores the id of the bullet that it's created after finishing its _FIRST_ANIMATION.

      -Beware: this variable is empty until the bullet has actually been created, so you should wait a bit before trying to access it.

-Player bullet changes:

   -_PLAYER_BULLET_PARENT now executes a more generalized version of the code that each player bullet used to call every step.

      -The effect the player bullets are set to create before destroying themselves is stored in a new variable: _DEATH_EFF.

      -Both _DEATH_EFF and _DAMAGE_VALUE are meant to be set for each bullet during their create events.

-Bugfixes/Optimization:

   -Replaced some instances of _REIMU and _PLAYER_PARENT with global._PLAYER to prevent potential issues and for consistency reasons.

   -Fixed a bug where the player would sometimes not respawn after continuing.

   -Fixed a bug where graze wouldn't properly increase more if there were a lot of nearby bullets.

   -Added a limit for the origin point x and y coordinates of _SPELL_BG to prevent overflowing.

   -Made diagonal movement using _MOVE_OBJECT() more accurate math-wise.