- Welcome to Touhou Wiki!
- Registering is temporarily disabled. Check in our Discord server to request an account and for assistance of any kind.
User:Mddass/Touhou File Format Specification/ECL: Difference between revisions
No edit summary |
|||
(44 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
'''ECL'''/'''.ecl''' files ([https://github.com/pbghogehoge/ssg/blob/master/GIAN07/ECL.H 敵コントロール言語] ''teki-kontorōru gengo'', '''''enemy control language''''') are compiled scripts | '''ECL'''/'''.ecl''' files ([https://github.com/pbghogehoge/ssg/blob/master/GIAN07/ECL.H 敵コントロール言語] ''teki-kontorōru gengo'', '''''enemy control language''''') are compiled scripts responsible for the control of the gameplay portions of stages in the Touhou games, ranging from stage enemy timings, bullet patterns, enemy movement to some background (3D) particle effects, boss setup, etc.. | ||
== Versions == | == Versions == | ||
The ECL format | The ECL format changes constantly over the years, specially in regards to the functions that it executes. From MoF onwards (version 2), ECL is a stack-based compiled script language. | ||
* [[User:Mddass/Touhou_File_Format_Specification/ECL/V1|ECL V1: Th06-Th095]] - First version of ECL, | * [[User:Mddass/Touhou_File_Format_Specification/ECL/V1|ECL V1: Th06-Th095]] - First version of ECL. Register based, and uses a separate section to control stage timing. | ||
* [[User:Mddass/Touhou_File_Format_Specification/ECL/V2|ECL V2: Th10-Th16]] - Complete revamp of the first version. | * [[User:Mddass/Touhou_File_Format_Specification/ECL/V2|ECL V2: Th10-Th16]] - Complete revamp of the first version. Notably, it is now stack based instead of register based, and all of the functions are now named to enable dynamic linking of multiple ECL files. | ||
== Syntax (thtk) == | == Syntax (thtk) == | ||
Line 18: | Line 18: | ||
These are the variables that can be used in EoSD ECL. They're very few (just 25), even when compared to its immediate successor: PCB. | These are the variables that can be used in EoSD ECL. They're very few (just 25), even when compared to its immediate successor: PCB. | ||
<div style="font-size:95%;text-align:center;"> | |||
{| border="0" class="sortable" | |||
|- | |||
!style="background-color:papayawhip;"|ID | |||
!style="background-color:papayawhip;"|Name | |||
!style="background-color:papayawhip;"|Description | |||
!style="background-color:papayawhip;"|Type | |||
|- | |||
| -10001 | |||
|I0 | |||
|Local variable (int) | |||
|Integer (0) | |||
|- | |||
| -10002 | |||
|I1 | |||
|Local variable (int) | |||
|Integer (0) | |||
|- | |||
| -10003 | |||
|I2 | |||
|Local variable (int) | |||
|Integer (0) | |||
|- | |||
| -10004 | |||
|I3 | |||
|Local variable (int) | |||
|Integer (0) | |||
|- | |||
| -10005 | |||
|F0 | |||
|Local variable (float) | |||
|Float (1) | |||
|- | |||
| -10006 | |||
|F1 | |||
|Local variable (float) | |||
|Float (1) | |||
|- | |||
| -10007 | |||
|F2 | |||
|Local variable (float) | |||
|Float (1) | |||
|- | |||
| -10008 | |||
|F3 | |||
|Local variable (float) | |||
|Float (1) | |||
|- | |||
| -10009 | |||
|I4 | |||
|Local variable (int) | |||
|Integer (0) | |||
|- | |||
| -10010 | |||
|I5 | |||
|Local variable (int) | |||
|Integer (0) | |||
|- | |||
| -10011 | |||
|I6 | |||
|Local variable (int) | |||
|Integer (0) | |||
|- | |||
| -10012 | |||
|I7 | |||
|Local variable (int) | |||
|Integer (0) | |||
|- | |||
| -10013 | |||
|RANK | |||
|Rank (Easy: 0; Lunatic: 3; Extra: 4) | |||
|Read-only (2) | |||
|- | |||
| -10014 | |||
|DIFFICULTY | |||
|[[Embodiment_of_Scarlet_Devil/Gameplay#Rank|Difficulty]] | |||
|Read-only (2) | |||
|- | |||
| -10015 | |||
|X | |||
|X-position | |||
|Float (1) | |||
|- | |||
| -10016 | |||
|Y | |||
|Y-position | |||
|Float (1) | |||
|- | |||
| -10017 | |||
|Z | |||
|Z-position | |||
|Float (1) | |||
|- | |||
| -10018 | |||
|PLAYER_X | |||
|Player X-position | |||
|Read-only (2) | |||
|- | |||
| -10019 | |||
|PLAYER_Y | |||
|Player Y-position | |||
|Read-only (2) | |||
|- | |||
| -10020 | |||
|PLAYER_Z | |||
|Player Z-position | |||
|Read-only (2) | |||
|- | |||
| -10021 | |||
|AIM | |||
|Angle to player | |||
|Read-only (2) | |||
|- | |||
| -10022 | |||
|TIME | |||
|Current lifetime | |||
|Integer (0) | |||
|- | |||
| -10023 | |||
|DIST | |||
|Distance to player | |||
|Read-only (2) | |||
|- | |||
| -10024 | |||
|LIFE | |||
|Current life | |||
|Integer (0) | |||
|- | |||
| -10025 | |||
|SHOT_TYPE | |||
|Current shot type<br />Calculated as "player * 2 + type", where Reimu is player 0 and Marisa is player 1 | |||
|Integer (0) (wtf?) | |||
|- | |||
|} | |||
</div> | |||
=== Th07: PCB (Final) === | === Th07: PCB (Final) === | ||
Line 94: | Line 204: | ||
* [10045.0f]: Angle to origin point (orbital movement). | * [10045.0f]: Angle to origin point (orbital movement). | ||
* [10046.0f]: Rotation speed (orbital movement). | * [10046.0f]: Rotation speed (orbital movement). | ||
* [10047.0f] | |||
* [10048.0f] | |||
* [10049.0f]: Distance from origin point (orbital movement). | * [10049.0f]: Distance from origin point (orbital movement). | ||
* [10050.0f]: Origin point X-coord (orbital movement). | * [10050.0f]: Origin point X-coord (orbital movement). | ||
Line 108: | Line 220: | ||
* [10061]: Unknown. <span style="color:grey">Used by the Prismrivers.</span> | * [10061]: Unknown. <span style="color:grey">Used by the Prismrivers.</span> | ||
* [10062]: Unknown byte. <span style="color:grey">Seems to be some state byte. Used by the Prismrivers.</span> | * [10062]: Unknown byte. <span style="color:grey">Seems to be some state byte. Used by the Prismrivers.</span> | ||
* [10063.0f] | |||
* [10064.0f] | |||
* [10065.0f] | |||
* [10066]: Boss life threshold. | * [10066]: Boss life threshold. | ||
* [10067]: Boss life threshold. <span style="color:grey">What's the difference from [10066]?</span> | * [10067]: Boss life threshold. <span style="color:grey">What's the difference from [10066]?</span> | ||
Line 217: | Line 332: | ||
=== Th16: [[HSiFS]] === | === Th16: [[HSiFS]] === | ||
* [-9903]: Current subseason. | * [-9903]: Current subseason. | ||
=== Th17: [[WBaWC]] === | |||
* [-9902]: Graze last second? | |||
== ECL Instruction | == ECL Instruction Tables (V1) == | ||
=== | === EoSD (th06) === | ||
This list below lists the opcode, mnemonic/name, format and a description for each main ECL instruction used in the subroutines section of the ECL file. | This list below lists the opcode, a mnemonic/name, the format and a description for each main ECL instruction used in the subroutines section of the ECL file. This section may also contain some implementation details (irrelevant for most people). | ||
<div style="font-family:monospace;font-size:12px;"> | <div style="font-family:monospace;font-size:12px;"> | ||
{| border="1" | {| border="1" class="sortable" | ||
|- | |- | ||
!style="background-color:papayawhip;"|Name | !style="background-color:papayawhip;"|Name | ||
Line 238: | Line 348: | ||
!style="background-color:papayawhip;"|Format | !style="background-color:papayawhip;"|Format | ||
!style="background-color:papayawhip;"|Description | !style="background-color:papayawhip;"|Description | ||
{{User:Mddass/ECL_TABLE_ROW|nop|0x0000 (0)|void|No operation. Technically, every invalid opcode is considered "nop", which includes 0.}} | |||
{{User:Mddass/ECL_TABLE_ROW|delete|0x0001 (1)|int a|Stop script execution on this enemy and delete it if a {{=}}{{=}} 1. Implementation detail: Returns -1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp|0x0002 (2)|int t, int cp|Unconditionally sets current time to t and sets the current seek offset in this function to cp.}} | |||
{{User:Mddass/ECL_TABLE_ROW|loop|0x0003 (3)|int t, int cp, int& var|If var !{{=}} 0, sets current time to t, sets the current seek offset in this function to cp and decrements var by 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|iset|0x0004 (4)|int &var, int a|Sets var to a. Equiv.: var {{=}} a. Interchangeable with fset.}} | |||
{{User:Mddass/ECL_TABLE_ROW|fset|0x0005 (5)|int &var, float a|Sets var to a. Equiv.: var {{=}} a. Interchangeable with iset.}} | |||
{{User:Mddass/ECL_TABLE_ROW|iset_r|0x0006 (6)|int &var, uint a|Sets var to a random value in the range [0, a). If a is 0, sets it to 0. Equiv.: var {{=}} rand()}} | |||
% a | |||
{{User:Mddass/ECL_TABLE_ROW|iset_r2|0x0007 (6)|int &var, int min, int a|Sets var to a random value in the range [min, min+a). If a is 0, sets it to 0. Equiv.: var {{=}} rand()}} | |||
% a + min | |||
{{User:Mddass/ECL_TABLE_ROW|fset_r|0x0008 (8)|int &var, float a|Sets var to a random value in the range [0, a).}} | |||
{{User:Mddass/ECL_TABLE_ROW|fset_r2|0x0009 (9)|int &var, float min, float a|Sets var to a random value in the range [min, min+a).}} | |||
{{User:Mddass/ECL_TABLE_ROW|get_x|0x000A (10)|int &var|Sets var to the enemy's x-position.}} | |||
{{User:Mddass/ECL_TABLE_ROW|get_y|0x000B (11)|int &var|Sets var to the enemy's y-position.}} | |||
{{User:Mddass/ECL_TABLE_ROW|get_z|0x000C (12)|int &var|Sets var to the enemy's z-position.}} | |||
{{User:Mddass/ECL_TABLE_ROW|iadd|0x000D (13)|int &var, int l, int r|Sets var to the result of l + r. Equiv.: var {{=}} l + r. Interchangeable with fadd.}} | |||
{{User:Mddass/ECL_TABLE_ROW|isub|0x000E (14)|int &var, int l, int r|Sets var to the result of l - r. Equiv.: var {{=}} l - r. Interchangeable with fsub.}} | |||
{{User:Mddass/ECL_TABLE_ROW|imul|0x000F (15)|int &var, int l, int r|Sets var to the result of l * r. Equiv.: var {{=}} l * r. Interchangeable with fmul.}} | |||
{{User:Mddass/ECL_TABLE_ROW|idiv|0x0010 (16)|int &var, int l, int r|Sets var to the result of l / r. Equiv.: var {{=}} l / r. Interchangeable with fdiv.}} | |||
{{User:Mddass/ECL_TABLE_ROW|imod|0x0011 (17)|int &var, int l, int r|Sets var to the result of l % r. Equiv.: var {{=}} l % r. Interchangeable with fmod.}} | |||
{{User:Mddass/ECL_TABLE_ROW|inc|0x0012 (18)|int &var|Increment var by 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|dec|0x0013 (19)|int &var|Decrement var by 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|fadd|0x0014 (20)|int &var, float l, float r|Sets var to the result of l + r. Equiv.: var {{=}} l + r. Interchangeable with iadd.}} | |||
{{User:Mddass/ECL_TABLE_ROW|fsub|0x0015 (21)|int &var, float l, float r|Sets var to the result of l - r. Equiv.: var {{=}} l - r. Interchangeable with isub.}} | |||
{{User:Mddass/ECL_TABLE_ROW|fmul|0x0016 (22)|int &var, float l, float r|Sets var to the result of l * r. Equiv.: var {{=}} l * r. Interchangeable with imul.}} | |||
{{User:Mddass/ECL_TABLE_ROW|fdiv|0x0017 (23)|int &var, float l, float r|Sets var to the result of l / r. Equiv.: var {{=}} l / r. Interchangeable with idiv.}} | |||
{{User:Mddass/ECL_TABLE_ROW|fmod|0x0018 (24)|int &var, float l, float r|Sets var to the result of l % r (IEEERemainder). Equiv.: var {{=}} IEEERemainder(l, r). Interchangeable with imod.}} | |||
{{User:Mddass/ECL_TABLE_ROW|atan2|0x0019 (25)|int &var, float ox, float oy, float tx, float ty|Sets var to the result of atan2(tx - ox, ty - oy). Effectively gives the angle towards tx,ty with ox,oy as the origin.}} | |||
{{User:Mddass/ECL_TABLE_ROW|norm_r|0x001A (26)|int &var|Normalizes var into a value that's within the (-pi, pi) range. var will be reduced by 2*pi until it is within that range if it is greater than pi, or incresed by 2*pi until it is within that range if it is lower than pi.}} | |||
{{User:Mddass/ECL_TABLE_ROW|itest|0x001B (27)|int a, int b|Compares a with b (integer values). The result will be stored in the enemy's comparison register. The result is -1 if a < b, 0 if a {{=}}{{=}} b or 1 if a > b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|ftest|0x001C (28)|float a, float b|Compares a with b (floating-point values). The result will be stored in the enemy's comparison register. The result is -1 if a < b, 0 if a {{=}}{{=}} b or 1 if a > b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_l|0x001D (29)|int t, int cp|If the comparison register is -1, sets current time to t and sets the current seek offset in this function to cp.}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_le|0x001E (30)|int t, int cp|If the comparison register is -1 or 0, sets current time to t and sets the current seek offset in this function to cp.}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_e|0x001F (31)|int t, int cp|If the comparison register is 0, sets current time to t and sets the current seek offset in this function to cp.}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_g|0x0020 (32)|int t, int cp|If the comparison register is 1, sets current time to t and sets the current seek offset in this function to cp.}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_ge|0x0021 (33)|int t, int cp|If the comparison register is 1 or 0, sets current time to t and sets the current seek offset in this function to cp.}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_n|0x0022 (34)|int t, int cp|If the comparison register is -1 or 1, sets current time to t and sets the current seek offset in this function to cp.}} | |||
{{User:Mddass/ECL_TABLE_ROW|call|0x0023 (35)|int func, int iarg, float farg|Copies variables -10001 to -10012 to backup registers and calls function func. Also, -10001 is set to iarg and -10005 is set to farg.}} | |||
{{User:Mddass/ECL_TABLE_ROW|return|0x0024 (36)|void|Returns to the parent function and copies variables -10001 to -10012 from the backup registers. Crashes the game if there is no parent function.}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_l|0x0025 (37)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a < b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_le|0x0026 (38)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a <{{=}} b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_e|0x0027 (39)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a {{=}}{{=}} b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_g|0x0028 (40)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a > b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_ge|0x0029 (41)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a >{{=}} b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_n|0x002A (42)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a !{{=}} b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|pos|0x002B (43)|float x, float y, float z|Sets the enemy position accordingly.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x002C (44)|float a, float b, float c|Unknown. Sets 3 values in the enemy.}} | |||
{{User:Mddass/ECL_TABLE_ROW|dir|0x002D (45)|float r, float s|Sets enemy movement direction to r and movement speed to s.}} | |||
{{User:Mddass/ECL_TABLE_ROW|rot|0x002E (46)|float r|Sets enemy movement direction acceleration to r.}} | |||
{{User:Mddass/ECL_TABLE_ROW|spd|0x002F (47)|float s|Sets enemy movement speed to s.}} | |||
{{User:Mddass/ECL_TABLE_ROW|acc|0x0030 (48)|float s|Sets enemy movement speed acceleration to s.}} | |||
{{User:Mddass/ECL_TABLE_ROW|rot_r|0x0031 (49)|float min, float max|Sets enemy movement direction to a value in the range [min, max). Does not read variables.}} | |||
{{User:Mddass/ECL_TABLE_ROW|rot_r2|0x0032 (50)|float min, float max|Sets enemy movement direction to a value in the range [min, max), according the enemy clip. Does not read variables.}} | |||
{{User:Mddass/ECL_TABLE_ROW|rot_aim|0x0033 (51)|float r, float s, float t|Sets enemy movement direction towards the player (+ r) with speed s.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_dec|0x0034 (52)|int t, float r, float s|Moves in a decelerating fashion with direction r, speed s and for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_dec2|0x0035 (53)|int t, float r, float s|Moves in a quickly-decelerating fashion with direction r, speed s and for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_acc|0x0036 (54)|int t, float r, float s|Moves in a accelerating fashion with direction r, speed s and for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_acc2|0x0037 (55)|int t, float r, float s|Moves in a quickly-accelerating fashion with direction r, speed s and for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_lin|0x0038 (56)|int t, float x, float y, float z|Moves in a linear fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_dec|0x0039 (57)|int t, float x, float y, float z|Moves in a decelerating fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_dec2|0x003A (58)|int t, float x, float y, float z|Moves in a quickly-decelerating fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_acc|0x003B (59)|int t, float x, float y, float z|Moves in a accelerating fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_acc2|0x003C (60)|int t, float x, float y, float z|Moves in a quickly-accelerating fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_t_dec|0x003D (61)|int t|Moves in a decelerating fashion for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_t_dec2|0x003E (62)|int t|Moves in a quickly-decelerating fashion for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_t_acc|0x003F (63)|int t|Moves in a accelerating fashion for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_t_acc2|0x0040 (64)|int t|Moves in a quickly-accelerating fashion for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|clip|0x0041 (65)|float x1, float y1, float x2, float y2|Confines enemy movement to the defined rectangle. Does not read variables.}} | |||
{{User:Mddass/ECL_TABLE_ROW|unclip|0x0042 (66)|void|Disables enemy movement boundaries.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_fan_aim|0x0043 (67)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 0 (aimed fan), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim offset to r1, aim variance per bullet to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_fan|0x0044 (68)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 1 (unaimed fan), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim to r1, aim variance per bullet to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_cir_aim|0x0045 (69)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 2 (aimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim offset to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_cir|0x0046 (70)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 3 (unaimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_cir2_aim|0x0047 (71)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 4 (offset aimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim offset to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_cir2|0x0048 (72)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 5 (offset unaimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_random_r|0x0049 (73)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 6 (random angle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, maximum direction to r1, minimum direction to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_random_sp|0x004A (74)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 7 (random speed), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, maximum speed to sp1, minimum speed to sp2, aim to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_random|0x004B (75)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 8 (random angle speed), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, maximum speed to sp1, minimum speed to sp2, maximum direction to r1, minimum direction to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_auto|0x004C (76)|int t|Sets the interval between automatic shooting to t. Zero disables automatic shooting. Does not read variables. Affected by difficulty (~0.8x delay at 32).}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_auto_delay|0x004D (77)|int t|Sets the interval between automatic shooting to t and delays the first shot by a random value in the range [0, t). Zero disables automatic shooting. Does not read variables. Affected by difficulty (~0.8x delay at 32).}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_delay|0x004E (78)|void|Sets it so setting bullet atributes does not automatically shoot.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on|0x004F (79)|void|Sets shoot flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on2|0x0050 (80)|void|Unused. ''Immediately'' shoots.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_ofs|0x0051 (81)|float x, float y, float z|Sets bullet shooting offset relative to self.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_ex|0x0052 (82)|int a, int b, int c, int d, float r, float s, float m, float n|Sets extra bullet attributes, used in conjuction with bullet flags.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_clear|0x0053 (83)|void|Clears all bullets and turns them into star items.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_se|0x0054 (84)|int a|Sets bullet sound effect to a. Bullet flag 0x200 (512) must be set for this to work. Using a negative value will turn that flag off.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_on|0x0055 (85)|short spr, short col, float r, float sp, float start_ofs, float end_ofs, float start_len, float w, int start_t, int t, int stop_t, int graze_delay, int graze_tol, int unk|Shoots a laser with the specified attributes and stores it in a specified index (see laser_id).}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_on_aim|0x0056 (86)|short spr, short col, float r, float sp, float start_ofs, float end_ofs, float start_len, float w, int start_t, int t, int stop_t, int graze_delay, int graze_tol, int unk|Shoots an aimed laser with the specified attributes and stores it in a specified index (see laser_id).}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_id|0x0057 (87)|int i|Sets the index where shot lasers are stored. Defaults to 0. Valid values are 0 to 31.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_rot|0x0058 (88)|int i, float r|Rotates the specified laser by r.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_aim|0x0059 (89)|int i, float r|Aims the specified laser towards the player and further rotates it by r.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_ofs|0x005A (90)|int i, float x, float y, float z|Offsets the specified laser by x,y,z.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_test|0x005B (91)|int i|Checks if a specified laser is disabled and stores the result in the comparison register.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_break|0x005C (92)|int i|Instantly cancels out the specified laser and turns it into star bullets.}} | |||
{{User:Mddass/ECL_TABLE_ROW|card|0x005D (93)|short face, short card_id, char* name|Begins a spellcard. Increases attempt count by 1, decodes name and sets it as the spellcard name, changes background, displays a portrait face, sets damage reduction to 8x, clears all bullets and calls et_diff_set(-0.5f, 0.5f, 0, 0, 0, 0).}} | |||
{{User:Mddass/ECL_TABLE_ROW|card_end|0x005E (94)|void|Ends the spellcard. Clears all bullets, removes spellcard text, restores background, restores damage reduction and gives spellcard and cancel bonuses.}} | |||
{{User:Mddass/ECL_TABLE_ROW|enm_new|0x005F (95)|int func, float x, float y, float z, short life, short item, int score|Spawns an enemy func at x,y,z. Sets its life to life, item reward on kill to item and score reward on kill to score.}} | |||
{{User:Mddass/ECL_TABLE_ROW|enm_clear|0x0060 (96)|void|Kills all enemies, except for untargetable ones or bosses.}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_at|0x0061 (97)|int id|Runs an anm script on the enemy. TBD}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_at_move|0x0062 (98)|short default, short far_left, short far_right, short left, short right|Sets the various anm script IDs for varying stages of enemy movement. Note: Last 2 bytes go unused due to packing.}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_at2|0x0063 (99)|int slot, int id|Runs an anm script on the enemy in a separate slot. Only slots 0-7 are valid. TBD}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_at_dead|0x0064 (100)|int id|Sets the anm script ID to run on death. TBD}} | |||
{{User:Mddass/ECL_TABLE_ROW|boss_set|0x0065 (101)|int id|Sets the boss ID for this enemy. Will also enable boss health bar and other things when set to a value other than -1, which disables everything again. Defaults to -1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|boss_card|0x0066 (102)|int id, float x_rot, float y_rot, float z_rot, float dist|Creates a spinning card graphic around the enemy with the corresponding settings.}} | |||
{{User:Mddass/ECL_TABLE_ROW|hitbox_set|0x0067 (103)|float w, float h, float d|Sets the enemy hitbox.}} | |||
{{User:Mddass/ECL_TABLE_ROW|hit_set|0x0068 (104)|int a|Toggles enemy contact with the player. Only the LSB is checked!}} | |||
{{User:Mddass/ECL_TABLE_ROW|hurt_set|0x0069 (105)|int a|Toggles enemy damage. Only the LSB is checked!}} | |||
{{User:Mddass/ECL_TABLE_ROW|se_play|0x006A (106)|int se|Plays a sound effect.}} | |||
{{User:Mddass/ECL_TABLE_ROW|flag_death_set|0x006B (107)|int flag|Sets death flags. 0-7 are valid values.}} | |||
{{User:Mddass/ECL_TABLE_ROW|death_at|0x006C (108)|int func|Sets the function to call on death.}} | |||
{{User:Mddass/ECL_TABLE_ROW|var_set|0x006D (109)|int a, int i|Writes a value into a variable the variable pool at index i. The pool is 4 integers followed by 4 floats. Anything else will over/underflow into other regions.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x006E (110)|int a|Unknown. Does various modifications to the enemy.}} | |||
{{User:Mddass/ECL_TABLE_ROW|life|0x006F (111)|int l|Sets the enemy life and max life.}} | |||
{{User:Mddass/ECL_TABLE_ROW|timeout|0x0070 (112)|int t|Sets the current timeout time to t.}} | |||
{{User:Mddass/ECL_TABLE_ROW|life_at_amt|0x0071 (113)|int l|Sets the life to trigger life_at at.}} | |||
{{User:Mddass/ECL_TABLE_ROW|life_at|0x0072 (114)|int func|Sets the function to call when life reaches an amount determined by life_at_amt.}} | |||
{{User:Mddass/ECL_TABLE_ROW|time_at_amt|0x0073 (115)|int t|Sets the time at which time_at will trigger.}} | |||
{{User:Mddass/ECL_TABLE_ROW|time_at|0x0074 (116)|int func|Sets the function to call when timeout time reaches an amount determined by time_at_amt.}} | |||
{{User:Mddass/ECL_TABLE_ROW|invinc_set|0x0075 (117)|int a|Toggles enemy invincibility. Invincible enemies cannot be hurt, touched, cleared or targeted.}} | |||
{{User:Mddass/ECL_TABLE_ROW|eff_at|0x0076 (118)|int func, int amt, int col|Spawn a particle effect.}} | |||
{{User:Mddass/ECL_TABLE_ROW|item_drop|0x0077 (119)|int amt|Drops amt items around the enemy. Drops power items if not at max power, else drops point items.}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_rot_set|0x0078 (120)|int a|Toggles whether the enemy graphic will rotate according the enemy's angle.}} | |||
{{User:Mddass/ECL_TABLE_ROW|func_call|0x0079 (121)|int func, int param|Immediately calls a function from a set of hardcoded functions with parameter param.}} | |||
{{User:Mddass/ECL_TABLE_ROW|func_set|0x007A (122)|int func|Sets a function to call every frame from a set of hardcoded functions. Function -1 will disable this.}} | |||
{{User:Mddass/ECL_TABLE_ROW|func_time_set|0x007B (123)|int t|Sets the current time variable in this function to t.}} | |||
{{User:Mddass/ECL_TABLE_ROW|item_drop2|0x007C (124)|int item|Drops a specific item at the enemy's position.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x007D (125)|void|Unknown.}} | |||
{{User:Mddass/ECL_TABLE_ROW|boss_lives_set|0x007E (126)|int a|Sets the amount of "lives" a boss has. Not automatically decremented!}} | |||
{{User:Mddass/ECL_TABLE_ROW|debug_watch|0x007F (127)|int& a|Unavailable debug operation, but probably puts a specific variable in a watchlist.}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_break|0x0080 (128)|int a|Terminates the current enemy graphic if a & 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_break2|0x0081 (129)|int slot, int a|Terminates the current enemy graphic in slot slot if a & 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x0082 (130)|int a|Unknown. Toggles a flag. Used by Patchouli.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_diff_set|0x0083 (131)|float sp_l, float sp_h, float am1_l, float am1_h, float am2_l, float am2_h|Sets the influence of difficulty (rank) on bullets. Default is et_diff_set(-0.5f, 0.5f, 0, 0, 0, 0). Resets to default when a spellcard begins.}} | |||
{{User:Mddass/ECL_TABLE_ROW|inv_set|0x0084 (132)|int a|Toggles enemy invisibility.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x0085 (133)|void|Unknown.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_clear|0x0086 (134)|void|Clears all 32 laser pointers.}} | |||
{{User:Mddass/ECL_TABLE_ROW|time_card_set|0x0087 (135)|int a|Toggles survival spellcard.}} | |||
|- | |- | ||
| | |} | ||
</div> | |||
| | ==== Extra Bullet Functions (et_ex) ==== | ||
These are tables for the extra functions bullets can have, along with the variables that can be used with them and a description of them. Note that you can mix and match as many flags as you want in order to get multiple effects by ORing them together, though certain games might only allow you to set a certain number of attributes. | |||
<div style="font-family:monospace;font-size:12px;"> | |||
{| border="1" | |||
|- | |- | ||
! style="background-color:papayawhip" rowspan="2"|Flag | |||
! style="background-color:papayawhip" colspan="4"|Variables | |||
! style="background-color:papayawhip" rowspan="2"|Description | |||
|- | |- | ||
| | ! style="background-color:papayawhip" |a | ||
| | ! style="background-color:papayawhip" |b | ||
! style="background-color:papayawhip" |r | |||
| | ! style="background-color:papayawhip" |s | ||
| | {{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0001 (1)|X|X|X|X|Deceleration effect at the beginning.}} | ||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0002 (2)|X|X|X|X|Spawn effect 1 (short).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0004 (4)|X|X|X|X|Spawn effect 2 (medium).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0008 (8)|X|X|X|X|Spawn effect 3 (long).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0010 (16)|O|X|O|O|Accelerate towards direction s (-999 for current direction) with speed r for a frames (negative for 99999 frames).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0020 (32)|O|X|O|O|Increase speed by s and direction by r for a frames (negative for 99999 frames).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0040 (64)|O|O|O|O|Stop in a frames, then change angle by r and set speed to s (negative to keep previous speed). Do this b times.}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0080 (128)|O|O|O|O|Stop in a frames, then aim at the player and change angle by r and set speed to s (negative to keep previous speed). Do this b times.}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0100 (256)|O|O|O|O|Stop in a frames, then set direction to r and speed to s (-999 to keep previous speed). Do this b times.}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0200 (512)|X|X|X|X|Play a sound when shot.}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0400 (1024)|O|X|O|X|Make bullet bounce on all 4 walls up to a times and set speed to r on contact (-999 to keep previous speed).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0800 (2048)|O|X|O|X|Make bullet bounce on all non-bottom walls up to a times and set speed to r on contact (-999 to keep previous speed).}} | |||
|- | |- | ||
| | |} | ||
</div> | |||
< | |||
The address of the ECL::RunInstruction function is located at Rx74A0 and return type is a byte type. | |||
| | |||
==== Hardcoded Functions (func_call and func_set) ==== | |||
These are tables for the hardcoded functions that can be used for each game. Note that functions that do not need "param" to be set can still be run through func_call. | |||
<div style="font-family:monospace;font-size:12px;"> | |||
{| border="1" | |||
|- | |- | ||
!ID | |||
!Needs param? | |||
!Description | |||
|- | |- | ||
| | {{User:Mddass/ECL_FUNC_TABLE_ROW|-1|No|Null pointer. Used to reset func_set.}} | ||
|5 | {{User:Mddass/ECL_FUNC_TABLE_ROW|0|Yes|If param is 0, then freeze all bullets in place and change their color to 15. If param is 1, then change every bullet's color to 15 and simulate et_ex(220, -1, -1, -1, 0.01f, -999.0f, -1.0f, -1.0f) with flag 0x10 set.}} | ||
{{User:Mddass/ECL_FUNC_TABLE_ROW|1|Yes|Casts param to float, sets bullet offset to a random point in a param x param area around the enemy and then shoots.}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|2|No|Used in Meiling's Yumekazura (2nd spell). Shoots every 6th frame in a star-shape and aims the bullets in a specific way, and spins every 30. I3 keeps track of the current duration (in frames) of the attack and I4 is the max duration. The hardcoded function is automatically disabled once it reaches the max duration.}} | |||
< | {{User:Mddass/ECL_FUNC_TABLE_ROW|3|No|Sets variables -10002, -10003 and -10004 respectively according to the shot type:<br/>- [0, 3, 1] if ReimuA.<br/>- [2, 3, 4] if ReimuB.<br/>- [1, 4, 0] if MarisaA.<br/>- [4, 2, 3] if MarisaB.}} | ||
| | {{User:Mddass/ECL_FUNC_TABLE_ROW|4||}} | ||
{{User:Mddass/ECL_FUNC_TABLE_ROW|5||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|6||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|7||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|8||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|9||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|10||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|11||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|12||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|13||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|14||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|15||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|16||}} | |||
|} | |||
</div> | |||
=== PCB (th07) === | |||
This list below lists the opcode, mnemonic/name, format and a description for each main ECL instruction used in the subroutines section of the ECL file. This section may also contain some implementation details (irrelevant for most people). | |||
<div style="font-family:monospace;font-size:12px;"> | |||
{| border="1" class="sortable" | |||
|- | |- | ||
|iset_r | !style="background-color:papayawhip;"|Name | ||
|6 | !style="background-color:papayawhip;"|Opcode | ||
|int &var, int a | !style="background-color:papayawhip;"|Format | ||
|Sets var to a random value in the range [ | !style="background-color:papayawhip;"|Description | ||
{{User:Mddass/ECL_TABLE_ROW|nop|0x0000 (0)|void|No operation. Technically, every invalid opcode is considered "nop", which includes 0.}} | |||
{{User:Mddass/ECL_TABLE_ROW|delete|0x0001 (1)|void|Stop script execution on this enemy and delete it.}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp|0x0002 (2)|int t, int cp|Unconditionally sets current time to t and sets the current seek offset in this function to cp.}} | |||
{{User:Mddass/ECL_TABLE_ROW|loop|0x0003 (3)|int t, int cp, int& var|If var !{{=}} 0, sets current time to t, sets the current seek offset in this function to cp and decrements var by 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|iset|0x0004 (4)|int &var, int a|Sets var to a. Equiv.: var {{=}} a.}} | |||
{{User:Mddass/ECL_TABLE_ROW|fset|0x0005 (5)|float &var, float a|Sets var to a. Equiv.: var {{=}} a.}} | |||
<!--{{User:Mddass/ECL_TABLE_ROW|iset_r|0x0006 (6)|int &var, uint a|Sets var to a random value in the range [0, a). If a is 0, sets it to 0. Equiv.: var {{=}} rand()}} | |||
% a | |||
{{User:Mddass/ECL_TABLE_ROW|iset_r2|0x0007 (6)|int &var, int min, int a|Sets var to a random value in the range [min, min+a). If a is 0, sets it to 0. Equiv.: var {{=}} rand()}} | |||
% a + min | |||
{{User:Mddass/ECL_TABLE_ROW|fset_r|0x0008 (8)|int &var, float a | |||
{{User:Mddass/GAME_COLOR_TEXT|int &var, float a|7}}|Sets var to a random value in the range [0, a).}} | |||
{{User:Mddass/ECL_TABLE_ROW|fset_r2|0x0009 (9)|int &var, float min, float a | |||
{{User:Mddass/GAME_COLOR_TEXT|int &var, float min, float a|7}}|Sets var to a random value in the range [min, min+a).}} | |||
{{User:Mddass/ECL_TABLE_ROW|get_x|0x000A (10)|int &var|Sets var to the enemy's x-position.}} | |||
{{User:Mddass/ECL_TABLE_ROW|get_y|0x000B (11)|int &var|Sets var to the enemy's y-position.}} | |||
{{User:Mddass/ECL_TABLE_ROW|get_z|0x000C (12)|int &var|Sets var to the enemy's z-position.}} | |||
{{User:Mddass/ECL_TABLE_ROW|iadd|0x000D (13)|int &var, int l, int r|Sets var to the result of l + r. Equiv.: var {{=}} l + r}} | |||
{{User:Mddass/ECL_TABLE_ROW|isub|0x000E (14)|int &var, int l, int r|Sets var to the result of l - r. Equiv.: var {{=}} l - r}} | |||
{{User:Mddass/ECL_TABLE_ROW|imul|0x000F (15)|int &var, int l, int r|Sets var to the result of l * r. Equiv.: var {{=}} l * r}} | |||
{{User:Mddass/ECL_TABLE_ROW|idiv|0x0010 (16)|int &var, int l, int r|Sets var to the result of l / r. Equiv.: var {{=}} l / r}} | |||
{{User:Mddass/ECL_TABLE_ROW|imod|0x0011 (17)|int &var, int l, int r|Sets var to the result of l % r. Equiv.: var {{=}} l % r}} | |||
{{User:Mddass/ECL_TABLE_ROW|inc|0x0012 (18)|int &var|Increment var by 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|dec|0x0013 (19)|int &var|Decrement var by 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|fadd|0x0014 (20)|int &var, float l, float r|Sets var to the result of l + r. Equiv.: var {{=}} l + r}} | |||
{{User:Mddass/ECL_TABLE_ROW|fsub|0x0015 (21)|int &var, float l, float r|Sets var to the result of l - r. Equiv.: var {{=}} l - r}} | |||
{{User:Mddass/ECL_TABLE_ROW|fmul|0x0016 (22)|int &var, float l, float r|Sets var to the result of l * r. Equiv.: var {{=}} l * r}} | |||
{{User:Mddass/ECL_TABLE_ROW|fdiv|0x0017 (23)|int &var, float l, float r|Sets var to the result of l / r. Equiv.: var {{=}} l / r}} | |||
{{User:Mddass/ECL_TABLE_ROW|fmod|0x0018 (24)|int &var, float l, float r|Sets var to the result of l % r (IEEERemainder). Equiv.: var {{=}} IEEERemainder(l, r)}} | |||
{{User:Mddass/ECL_TABLE_ROW|atan2|0x0019 (25)|int &var, float ox, float oy, float tx, float ty|Sets var to the result of atan2(tx - ox, ty - oy). Effectively gives the angle towards tx,ty with ox,oy as the origin.}} | |||
{{User:Mddass/ECL_TABLE_ROW|norm_r|0x001A (26)|int &var|Normalizes var into a value that's within the (-pi, pi) range. var will be reduced by 2*pi until it is within that range if it is greater than pi, or incresed by 2*pi until it is within that range if it is lower than pi.}} | |||
{{User:Mddass/ECL_TABLE_ROW|itest|0x001B (27)|int a, int b|Compares a with b (integer values). The result will be stored in the enemy's comparison register. The result is -1 if a < b, 0 if a {{=}}{{=}} b or 1 if a > b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|ftest|0x001C (28)|float a, float b|Compares a with b (floating-point values). The result will be stored in the enemy's comparison register. The result is -1 if a < b, 0 if a {{=}}{{=}} b or 1 if a > b.}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_l|0x001D (29)|int t, int cp|If the comparison register is -1, sets current time to t and sets the current seek offset in this function to cp.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_le|0x001E (30)|int t, int cp|If the comparison register is -1 or 0, sets current time to t and sets the current seek offset in this function to cp.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_e|0x001F (31)|int t, int cp|If the comparison register is 0, sets current time to t and sets the current seek offset in this function to cp.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_g|0x0020 (32)|int t, int cp|If the comparison register is 1, sets current time to t and sets the current seek offset in this function to cp.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_ge|0x0021 (33)|int t, int cp|If the comparison register is 1 or 0, sets current time to t and sets the current seek offset in this function to cp.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|jmp_n|0x0022 (34)|int t, int cp|If the comparison register is -1 or 1, sets current time to t and sets the current seek offset in this function to cp.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|call|0x0023 (35)|int func, int iarg, float farg|Copies variables -10001 to -10012 to backup registers and calls function func. Also, -10001 is set to iarg and -10005 is set to farg.}} | |||
{{User:Mddass/ECL_TABLE_ROW|return|0x0024 (36)|void|Returns to the parent function and copies variables -10001 to -10012 from the backup registers. Crashes the game if there is no parent function.}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_l|0x0025 (37)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a < b.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_le|0x0026 (38)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a <{{=}} b.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_e|0x0027 (39)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a {{=}}{{=}} b.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_g|0x0028 (40)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a > b.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_ge|0x0029 (41)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a >{{=}} b.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|call_n|0x002A (42)|int func, int iarg, float farg, int a, int b|Runs call(func, iarg, farg) if a !{{=}} b.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|pos|0x002B (43)|float x, float y, float z|Sets the enemy position accordingly.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x002C (44)|float a, float b, float c|Unknown. Sets 3 values in the enemy.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|dir|0x002D (45)|float r, float s|Sets enemy movement direction to r and movement speed to s.}} | |||
{{User:Mddass/ECL_TABLE_ROW|rot|0x002E (46)|float r|Sets enemy movement direction acceleration to r.}} | |||
{{User:Mddass/ECL_TABLE_ROW|spd|0x002F (47)|float s|Sets enemy movement speed to s.}} | |||
{{User:Mddass/ECL_TABLE_ROW|acc|0x0030 (48)|float s|Sets enemy movement speed acceleration to s.}} | |||
{{User:Mddass/ECL_TABLE_ROW|rot_r|0x0031 (49)|float min, float max|Sets enemy movement direction to a value in the range [min, max). {{User:Mddass/GAME_COLOR_TEXT|Does not read variables.|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|rot_r2|0x0032 (50)|float min, float max|Sets enemy movement direction to a value in the range [min, max), according the enemy clip. {{User:Mddass/GAME_COLOR_TEXT|Does not read variables.|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|rot_aim|0x0033 (51)|float r, float s, float t|Sets enemy movement direction towards the player (+ r) with speed s.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_dec|0x0034 (52)|int t, float r, float s|Moves in a decelerating fashion with direction r, speed s and for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_dec2|0x0035 (53)|int t, float r, float s|Moves in a quickly-decelerating fashion with direction r, speed s and for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_acc|0x0036 (54)|int t, float r, float s|Moves in a accelerating fashion with direction r, speed s and for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_acc2|0x0037 (55)|int t, float r, float s|Moves in a quickly-accelerating fashion with direction r, speed s and for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_lin|0x0038 (56)|int t, float x, float y, float z|Moves in a linear fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_dec|0x0039 (57)|int t, float x, float y, float z|Moves in a decelerating fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_dec2|0x003A (58)|int t, float x, float y, float z|Moves in a quickly-decelerating fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_acc|0x003B (59)|int t, float x, float y, float z|Moves in a accelerating fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_pt_acc2|0x003C (60)|int t, float x, float y, float z|Moves in a quickly-accelerating fashion towards x,y,z in t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_t_dec|0x003D (61)|int t|Moves in a decelerating fashion for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_t_dec2|0x003E (62)|int t|Moves in a quickly-decelerating fashion for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_t_acc|0x003F (63)|int t|Moves in a accelerating fashion for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|it_t_acc2|0x0040 (64)|int t|Moves in a quickly-accelerating fashion for t frames.}} | |||
{{User:Mddass/ECL_TABLE_ROW|clip|0x0041 (65)|float x1, float y1, float x2, float y2|Confines enemy movement to the defined rectangle. {{User:Mddass/GAME_COLOR_TEXT|Does not read variables.|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|unclip|0x0042 (66)|void|Disables enemy movement boundaries.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_fan_aim|0x0043 (67)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 0 (aimed fan), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim offset to r1, aim variance per bullet to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_fan|0x0044 (68)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 1 (unaimed fan), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim to r1, aim variance per bullet to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_cir_aim|0x0045 (69)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 2 (aimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim offset to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_cir|0x0046 (70)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 3 (unaimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_cir2_aim|0x0047 (71)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 4 (offset aimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim offset to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_cir2|0x0048 (72)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 5 (offset unaimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_random_r|0x0049 (73)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 6 (random angle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, maximum direction to r1, minimum direction to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_random_sp|0x004A (74)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 7 (random speed), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, maximum speed to sp1, minimum speed to sp2, aim to r1, aim variance per layer to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on_random|0x004B (75)|short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag|Sets bullet attributes. Sets type to 8 (random angle speed), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, maximum speed to sp1, minimum speed to sp2, maximum direction to r1, minimum direction to r2 and bullet flags to flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_auto|0x004C (76)|int t|Sets the interval between automatic shooting to t. Zero disables automatic shooting. {{User:Mddass/GAME_COLOR_TEXT|Does not read variables. Affected by difficulty (~0.8x delay at 32).|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_auto_delay|0x004D (77)|int t|Sets the interval between automatic shooting to t and delays the first shot by a random value in the range [0, t). Zero disables automatic shooting. {{User:Mddass/GAME_COLOR_TEXT|Does not read variables. Affected by difficulty (~0.8x delay at 32).|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_delay|0x004E (78)|void|Sets it so setting bullet atributes does not automatically shoot.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on|0x004F (79)|void|Sets shoot flag.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_on2|0x0050 (80)|void|Unused. ''Immediately'' shoots.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_ofs|0x0051 (81)|float x, float y, float z|Sets bullet shooting offset relative to self.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_ex|0x0052 (82)|int a, int b, int c, int d, float r, float s, float m, float n|Sets extra bullet attributes, used in conjuction with bullet flags.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_clear|0x0053 (83)|void|Clears all bullets and turns them into star items.}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_se|0x0054 (84)|int a|Sets bullet sound effect to a. Bullet flag 0x200 (512) must be set for this to work. Using a negative value will turn that flag off.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_on|0x0055 (85)|short spr, short col, float r, float sp, float start_ofs, float end_ofs, float start_len, float w, int start_t, int t, int stop_t, int graze_delay, int graze_tol, int unk|Shoots a laser with the specified attributes and stores it in a specified index (see laser_id).}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_on_aim|0x0056 (86)|short spr, short col, float r, float sp, float start_ofs, float end_ofs, float start_len, float w, int start_t, int t, int stop_t, int graze_delay, int graze_tol, int unk|Shoots an aimed laser with the specified attributes and stores it in a specified index (see laser_id).}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_id|0x0057 (87)|int i|Sets the index where shot lasers are stored. Defaults to 0. Valid values are 0 to 31.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_rot|0x0058 (88)|int i, float r|Rotates the specified laser by r.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_aim|0x0059 (89)|int i, float r|Aims the specified laser towards the player and further rotates it by r.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_ofs|0x005A (90)|int i, float x, float y, float z|Offsets the specified laser by x,y,z.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_test|0x005B (91)|int i|Checks if a specified laser is disabled and stores the result in the comparison register.}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_break|0x005C (92)|int i|Instantly cancels out the specified laser and turns it into star bullets.}} | |||
{{User:Mddass/ECL_TABLE_ROW|card|0x005D (93)|short face, short card_id, char* name|Begins a spellcard. Increases attempt count by 1, decodes name and sets it as the spellcard name, changes background, displays a portrait face, sets damage reduction to 8x, clears all bullets and calls et_diff_set(-0.5f, 0.5f, 0, 0, 0, 0).}} | |||
{{User:Mddass/ECL_TABLE_ROW|card_end|0x005E (94)|void|Ends the spellcard. Clears all bullets, removes spellcard text, restores background, restores damage reduction and gives spellcard and cancel bonuses.}} | |||
{{User:Mddass/ECL_TABLE_ROW|enm_new|0x005F (95)|int func, float x, float y, float z, short life, short item, int score|Spawns an enemy func at x,y,z. Sets its life to life, item reward on kill to item and score reward on kill to score.}} | |||
{{User:Mddass/ECL_TABLE_ROW|enm_clear|0x0060 (96)|void|Kills all enemies, except for untargetable ones or bosses.}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_at|0x0061 (97)|int id|Runs an anm script on the enemy. TBD}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_at_move|0x0062 (98)|short default, short far_left, short far_right, short left, short right|Sets the various anm script IDs for varying stages of enemy movement. Note: Last 2 bytes go unused due to packing.}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_at2|0x0063 (99)|int slot, int id|Runs an anm script on the enemy in a separate slot. Only slots 0-7 are valid. TBD}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_at_dead|0x0064 (100)|int id|Sets the anm script ID to run on death. TBD}} | |||
{{User:Mddass/ECL_TABLE_ROW|boss_set|0x0065 (101)|int id|Sets the boss ID for this enemy. Will also enable boss health bar and other things when set to a value other than -1, which disables everything again. Defaults to -1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|boss_card|0x0066 (102)|int id, float x_rot, float y_rot, float z_rot, float dist|Creates a spinning card graphic around the enemy with the corresponding settings.}} | |||
{{User:Mddass/ECL_TABLE_ROW|hitbox_set|0x0067 (103)|float w, float h, float d|Sets the enemy hitbox.}} | |||
{{User:Mddass/ECL_TABLE_ROW|hit_set|0x0068 (104)|int a|Toggles enemy contact with the player. Only the LSB is checked!}} | |||
{{User:Mddass/ECL_TABLE_ROW|hurt_set|0x0069 (105)|int a|Toggles enemy damage. Only the LSB is checked!}} | |||
{{User:Mddass/ECL_TABLE_ROW|se_play|0x006A (106)|int se|Plays a sound effect.}} | |||
{{User:Mddass/ECL_TABLE_ROW|flag_death_set|0x006B (107)|int flag|Sets death flags. 0-7 are valid values.}} | |||
{{User:Mddass/ECL_TABLE_ROW|death_at|0x006C (108)|int func|Sets the function to call on death.}} | |||
{{User:Mddass/ECL_TABLE_ROW|var_set|0x006D (109)|int a, int i|Writes a value into a variable the variable pool at index i. The pool is 4 integers followed by 4 floats. Anything else will over/underflow into other regions.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x006E (110)|int a|Unknown. Does various modifications to the enemy.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|life|0x006F (111)|int l|Sets the enemy life and max life.}} | |||
{{User:Mddass/ECL_TABLE_ROW|timeout|0x0070 (112)|int t|Sets the current timeout time to t.}} | |||
{{User:Mddass/ECL_TABLE_ROW|life_at_amt|0x0071 (113)|int l|Sets the life to trigger life_at at.}} | |||
{{User:Mddass/ECL_TABLE_ROW|life_at|0x0072 (114)|int func|Sets the function to call when life reaches an amount determined by life_at_amt.}} | |||
{{User:Mddass/ECL_TABLE_ROW|time_at_amt|0x0073 (115)|int t|Sets the time at which time_at will trigger.}} | |||
{{User:Mddass/ECL_TABLE_ROW|time_at|0x0074 (116)|int func|Sets the function to call when timeout time reaches an amount determined by time_at_amt.}} | |||
{{User:Mddass/ECL_TABLE_ROW|invinc_set|0x0075 (117)|int a|Toggles enemy invincibility. Invincible enemies cannot be hurt, touched, cleared or targeted.}} | |||
{{User:Mddass/ECL_TABLE_ROW|eff_at|0x0076 (118)|int func, int amt, int col|Spawn a particle effect.}} | |||
{{User:Mddass/ECL_TABLE_ROW|item_drop|0x0077 (119)|int amt|Drops amt items around the enemy. Drops power items if not at max power, else drops point items.}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_rot_set|0x0078 (120)|int a|Toggles whether the enemy graphic will rotate according the enemy's angle.}} | |||
{{User:Mddass/ECL_TABLE_ROW|func_call|0x0079 (121)|int func, int param|Immediately calls a function from a set of hardcoded functions with parameter param.}} | |||
{{User:Mddass/ECL_TABLE_ROW|func_set|0x007A (122)|int func|Sets a function to call every frame from a set of hardcoded functions. Function -1 will disable this.}} | |||
{{User:Mddass/ECL_TABLE_ROW|func_time_set|0x007B (123)|int t|Sets the current time variable in this function to t.}} | |||
{{User:Mddass/ECL_TABLE_ROW|item_drop2|0x007C (124)|int item|Drops a specific item at the enemy's position.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x007D (125)|void|Unknown.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|boss_lives_set|0x007E (126)|int a|Sets the amount of "lives" a boss has. Not automatically decremented!}} | |||
{{User:Mddass/ECL_TABLE_ROW|debug_watch|0x007F (127)|int& a|Unavailable debug operation, but probably puts a specific variable in a watchlist.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_break|0x0080 (128)|int a|Terminates the current enemy graphic if a & 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW|anm_break2|0x0081 (129)|int slot, int a|Terminates the current enemy graphic in slot slot if a & 1.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x0082 (130)|int a|Unknown. Toggles a flag. Used by Patchouli.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|et_diff_set|0x0083 (131)|float sp_l, float sp_h, float am1_l, float am1_h, float am2_l, float am2_h|Sets the influence of difficulty (rank) on bullets. Default is et_diff_set(-0.5f, 0.5f, 0, 0, 0, 0). Resets to default when a spellcard begins.}} | |||
{{User:Mddass/ECL_TABLE_ROW|inv_set|0x0084 (132)|int a|Toggles enemy invisibility.}} | |||
{{User:Mddass/ECL_TABLE_ROW||0x0085 (133)|void|Unknown.|color={{User:Mddass/GAME_COLOR|text|6}}|bgcolor={{User:Mddass/GAME_COLOR|bg|6}}}} | |||
{{User:Mddass/ECL_TABLE_ROW|laser_clear|0x0086 (134)|void|Clears all 32 laser pointers.}} | |||
{{User:Mddass/ECL_TABLE_ROW|time_card_set|0x0087 (135)|int a|Toggles survival spellcard.}}--> | |||
|- | |- | ||
| | |} | ||
</div> | |||
==== Extra Bullet Functions (et_ex) ==== | |||
These are tables for the extra functions bullets can have, along with the variables that can be used with them and a description of them. Note that you can mix and match as many flags as you want in order to get multiple effects by ORing them together, though certain games might only allow you to set a certain number of attributes. | |||
<div style="font-family:monospace;font-size:14px;"> | |||
{| border="1" | |||
|- | |- | ||
| | ! style="background-color:papayawhip" rowspan="2"|Flag | ||
! style="background-color:papayawhip" colspan="4"|Variables | |||
| | ! style="background-color:papayawhip" rowspan="2"|Description | ||
| | |||
|- | |- | ||
| | ! style="background-color:papayawhip" |a | ||
| | ! style="background-color:papayawhip" |b | ||
| | ! style="background-color:papayawhip" |r | ||
! style="background-color:papayawhip" |s | |||
| | {{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0001 (1)|X|X|X|X|Deceleration effect at the beginning.}} | ||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0002 (2)|X|X|X|X|Spawn effect 1 (short).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0004 (4)|X|X|X|X|Spawn effect 2 (medium).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0008 (8)|X|X|X|X|Spawn effect 3 (long).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0010 (16)|O|X|O|O|Accelerate towards direction s (-999 for current direction) with speed r for a frames (negative for 99999 frames).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0020 (32)|O|X|O|O|Increase speed by s and direction by r for a frames (negative for 99999 frames).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0040 (64)|O|O|O|O|Stop in a frames, then change angle by r and set speed to s (negative to keep previous speed). Do this b times.}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0080 (128)|O|O|O|O|Stop in a frames, then aim at the player and change angle by r and set speed to s (negative to keep previous speed). Do this b times.}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0100 (256)|O|O|O|O|Stop in a frames, then set direction to r and speed to s (-999 to keep previous speed). Do this b times.}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0200 (512)|X|X|X|X|Play a sound when shot.}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0400 (1024)|O|X|O|X|Make bullet bounce on all 4 walls up to a times and set speed to r on contact (-999 to keep previous speed).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x0800 (2048)|O|X|O|X|Make bullet bounce on all non-bottom walls up to a times and set speed to r on contact (-999 to keep previous speed).}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x1000 (4096)|X|X|X|X|Unknown. Used by hardcoded function 4.}} | |||
{{User:Mddass/ECL_ET_EX_TABLE_ROW_SMALL|0x2000 (8192)|O|X|X|X|Set off-screen immunity for a frames.}} | |||
|- | |- | ||
| | |} | ||
</div> | |||
==== Hardcoded Functions (func_call and func_set) ==== | |||
These are tables for the hardcoded functions that can be used for each game. Note that functions that do not need "param" to be set can still be run through func_call. | |||
<div style="font-family:monospace;font-size:12px;"> | |||
{| border="1" | |||
| | |||
|- | |- | ||
!ID | |||
!Needs param? | |||
!Description | |||
|- | |- | ||
{{User:Mddass/ECL_FUNC_TABLE_ROW|-1|No|Null pointer. Used to reset func_set.}} | |||
<!--{{User:Mddass/ECL_FUNC_TABLE_ROW|0|Yes|If param is 0, then freeze all bullets in place and change their color to 15. If param is 1, then change every bullet's color to 15 and simulate et_ex(220, -1, -1, -1, 0.01f, -999.0f, -1.0f, -1.0f) with flag 0x10 set.}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|1|Yes|Casts param to float, sets bullet offset to a random point in a param x param area around the enemy and then shoots.}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|2|No|Used in Meiling's Yumekazura (2nd spell). Shoots every 6th frame in a star-shape and aims the bullets in a specific way, and spins every 30. I3 keeps track of the current duration (in frames) of the attack and I4 is the max duration. The hardcoded function is automatically disabled once it reaches the max duration.}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|3|No|Sets variables -10002, -10003 and -10004 respectively according to the shot type:<br/>- [0, 3, 1] if ReimuA.<br/>- [2, 3, 4] if ReimuB.<br/>- [1, 4, 0] if MarisaA.<br/>- [4, 2, 3] if MarisaB.}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|4||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|5||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|6||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|7||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|8||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|9||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|10||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|11||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|12||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|13||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|14||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|15||}} | |||
{{User:Mddass/ECL_FUNC_TABLE_ROW|16||}}--> | |||
|} | |} | ||
Revision as of 22:52, 20 October 2019
ECL/.ecl files (敵コントロール言語 teki-kontorōru gengo, enemy control language) are compiled scripts responsible for the control of the gameplay portions of stages in the Touhou games, ranging from stage enemy timings, bullet patterns, enemy movement to some background (3D) particle effects, boss setup, etc..
Versions
The ECL format changes constantly over the years, specially in regards to the functions that it executes. From MoF onwards (version 2), ECL is a stack-based compiled script language.
- ECL V1: Th06-Th095 - First version of ECL. Register based, and uses a separate section to control stage timing.
- ECL V2: Th10-Th16 - Complete revamp of the first version. Notably, it is now stack based instead of register based, and all of the functions are now named to enable dynamic linking of multiple ECL files.
Syntax (thtk)
TBD
Syntax (TSA)
TBD, there are enough screenshots to know.
Variables (V1)
These lists are incomplete and are subject to change over time.
Th06: EoSD
These are the variables that can be used in EoSD ECL. They're very few (just 25), even when compared to its immediate successor: PCB.
ID | Name | Description | Type |
---|---|---|---|
-10001 | I0 | Local variable (int) | Integer (0) |
-10002 | I1 | Local variable (int) | Integer (0) |
-10003 | I2 | Local variable (int) | Integer (0) |
-10004 | I3 | Local variable (int) | Integer (0) |
-10005 | F0 | Local variable (float) | Float (1) |
-10006 | F1 | Local variable (float) | Float (1) |
-10007 | F2 | Local variable (float) | Float (1) |
-10008 | F3 | Local variable (float) | Float (1) |
-10009 | I4 | Local variable (int) | Integer (0) |
-10010 | I5 | Local variable (int) | Integer (0) |
-10011 | I6 | Local variable (int) | Integer (0) |
-10012 | I7 | Local variable (int) | Integer (0) |
-10013 | RANK | Rank (Easy: 0; Lunatic: 3; Extra: 4) | Read-only (2) |
-10014 | DIFFICULTY | Difficulty | Read-only (2) |
-10015 | X | X-position | Float (1) |
-10016 | Y | Y-position | Float (1) |
-10017 | Z | Z-position | Float (1) |
-10018 | PLAYER_X | Player X-position | Read-only (2) |
-10019 | PLAYER_Y | Player Y-position | Read-only (2) |
-10020 | PLAYER_Z | Player Z-position | Read-only (2) |
-10021 | AIM | Angle to player | Read-only (2) |
-10022 | TIME | Current lifetime | Integer (0) |
-10023 | DIST | Distance to player | Read-only (2) |
-10024 | LIFE | Current life | Integer (0) |
-10025 | SHOT_TYPE | Current shot type Calculated as "player * 2 + type", where Reimu is player 0 and Marisa is player 1 |
Integer (0) (wtf?) |
Th07: PCB (Final)
The variables that can be used in PCB ECL are much more than that of EoSD ECL. Improvements include more local variables, inheritable variables, randomness variables, movement-related variables, and much more.
- [10000]: Local variable (32-bit integer).
- [10001]: Local variable (32-bit integer).
- [10002]: Local variable (32-bit integer).
- [10003]: Local variable (32-bit integer).
- [10004.0f]: Local variable (single-precision floating point).
- [10005.0f]: Local variable (single-precision floating point).
- [10006.0f]: Local variable (single-precision floating point).
- [10007.0f]: Local variable (single-precision floating point).
- [10008.0f]: Local variable (single-precision floating point).
- [10009.0f]: Local variable (single-precision floating point).
- [10010.0f]: Local variable (single-precision floating point).
- [10011.0f]: Local variable (single-precision floating point).
- [10012]: Local variable (32-bit integer).
- [10013]: Local variable (32-bit integer).
- [10014]: Local variable (32-bit integer).
- [10015]: Local variable (32-bit integer).
- [10016]: Rank (Easy: 0; Normal: 1; Hard: 2; Lunatic: 3; Extra: 4; Phantasm: 5)
- [10017]: Difficulty.
- [10018.0f]: Self X-position.
- [10019.0f]: Self Y-position.
- [10020.0f]: Self Z-position.
- [10021.0f]: Player X-position.
- [10022.0f]: Player Y-position.
- [10023.0f]: Player Z-position.
- [10024.0f]: Angle to player.
- [10025]: Current time.
- [10026.0f]: Distance from player.
- [10027]: Current life.
- [10028]: Shot-type. (ReimuA: 0; MarisaA: 2; SakuyaA: 4; etc.)
- [10029]: Function-wide integer.
- [10030]: Function-wide integer.
- [10031]: Function-wide integer.
- [10032]: Function-wide integer.
- [10033.0f]: Function-wide float.
- [10034.0f]: Function-wide float.
- [10035.0f]: Function-wide float.
- [10036.0f]: Function-wide float.
- [10037]: Function-wide integer. When a function is called from this, copied to the function's [-10029].
- [10038]: Function-wide integer. When a function is called from this, copied to the function's [-10030].
- [10039]: Function-wide integer. When a function is called from this, copied to the function's [-10031].
- [10040]: Function-wide integer. When a function is called from this, copied to the function's [-10032].
- [10041.0f]: Function-wide float. When a function is called from this, copied to the function's [-10033.0f].
- [10042.0f]: Function-wide float. When a function is called from this, copied to the function's [-10034.0f].
- [10043.0f]: Function-wide float. When a function is called from this, copied to the function's [-10035.0f].
- [10044.0f]: Function-wide float. When a function is called from this, copied to the function's [-10036.0f].
- [10045.0f]: Angle to origin point (orbital movement).
- [10046.0f]: Rotation speed (orbital movement).
- [10047.0f]
- [10048.0f]
- [10049.0f]: Distance from origin point (orbital movement).
- [10050.0f]: Origin point X-coord (orbital movement).
- [10051.0f]: Origin point Y-coord (orbital movement).
- [10052.0f]: Origin point Z-coord (orbital movement).
- [10053.0f]: Unknown float. Used by Yukari's last spell to store some angle. Angle to origin point + pi?
- [10054.0f]: Current angle.
- [10055.0f]: Returns a random value between
0.0f
and1.0f
. - [10056.0f]: Returns a random value between
[10034.0f]
and[10034.0f] + [10033.0f]
. - [10057.0f]: X-offset to target point.
- [10058.0f]: Y-offset to target point.
- [10059.0f]: Z-offset to target point.
- [10060.0f]: Returns a random radian value.
- [10061]: Unknown. Used by the Prismrivers.
- [10062]: Unknown byte. Seems to be some state byte. Used by the Prismrivers.
- [10063.0f]
- [10064.0f]
- [10065.0f]
- [10066]: Boss life threshold.
- [10067]: Boss life threshold. What's the difference from [10066]?
- [10068]: Minimum life. If the enemy life drops down to this, it will immediately be deleted.
- [10069]: Minimum life. If the enemy life drops down to this, it will immediately be deleted. What's the difference from [10068]?
- [10070]: Item reward on death.
- [10071]: Score reward on death.
- [10072.0f]: Local variable? Used by Yuyuko to store X-offset to spawn bullets from.
- [10073.0f]: Local variable? Used by Yuyuko to store Y-offset to spawn bullets from.
Variables (V2)
Note: All variables from MoF onwards carry over to the next games.
Missing variables are either unknown or unused.
Th10: MoF
- [-10000]: Random integer value.
- [-9999.0f]: Random float value from 0.0f to 1.0f.
- [-9998.0f]: Random value from -pi to pi.
- [-9997.0f]: Final X-coordinate.
- [-9996.0f]: Final Y-coordinate.
- [-9995.0f]: Absolute X-coordinate.
- [-9994.0f]: Abdolute Y-coordinate.
- [-9993.0f]: Relative X-coordinate.
- [-9992.0f]: Relative Y-coordinate.
- [-9991.0f]: Player X-pos.
- [-9990.0f]: Player Y-pos.
- [-9989.0f]: Angle to player (based on current position).
- [-9988]: Time elapsed (in current sub?)
- [-9987.0f]: Random float value from -1.0f to 1.0f.
- [-9986]: Becomes non-null when a timeout occurs.
- [-9985]: Local variable.
- [-9984]: Local variable.
- [-9983]: Local variable.
- [-9982]: Local variable.
- [-9981.0f]: Local variable.
- [-9980.0f]: Local variable.
- [-9979.0f]: Local variable.
- [-9978.0f]: Local variable.
- [-9977.0f]: Same as [-9997.0f].
- [-9976.0f]: Same as [-9996.0f].
- [-9975.0f]: Same as [-9995.0f].
- [-9974.0f]: Same as [-9994.0f].
- [-9973.0f]: Same as [-9993.0f].
- [-9972.0f]: Same as [-9992.0f].
- [-9971.0f]: Absolute current angular direction.
- [-9970.0f]: Relative current angular direction.
- [-9969.0f]: Absolute current movement speed.
- [-9968.0f]: Relative current movement speed.
- [-9967.0f]: Absolute radius from origin point.
- [-9966.0f]: Relative radius from origin point.
- [-9965.0f]: Same as [-9991.0f].
- [-9964.0f]: Same as [-9990.0f].
- [-9963.0f]: Boss 0 X-pos.
- [-9962.0f]: Boss 0 Y-pos.
- [-9961]: 未知 (地址1120)
- [-9960]: Game difficulty.
- [-9959]: Rank. E = 0; N = 1; H = 2; L = 3; X = 4; O = 5.
- [-9958]: Final angular direction.
- [-9957]: 1
- [-9954]: Current life.
- [-9953]: Easy mode flag.
- [-9952]: Normal mode flag.
- [-9951]: Hard mode flag.
- [-9950]: Lunatic mode flag.
Th11: SA
- [-9949]: Miss count
- [-9948]: Bomb count
- [-9947]: Becomes null on timeout, miss or bomb (or any other game-specific condition i.e. trance).
- [-9946]: Amount of units on-screen.
- [-9945]: Shot type.
- [-9944.0f]: Distance from player.
- [-9943]: Boss local variable.
- [-9942]: Boss local variable.
- [-9941]: Boss local variable.
- [-9940]: Boss local variable.
- [-9939.0f]: Boss local variable.
- [-9938.0f]: Boss local variable.
- [-9937.0f]: Boss local variable.
- [-9936.0f]: Boss local variable.
- [-9935.0f]: Local variable.
- [-9934.0f]: Local variable.
- [-9933.0f]: Local variable.
- [-9932.0f]: Local variable.
Th12: UFO
- [-9931]: 已经出现单位数量-1,包含main
- [-9930]: Power.
Th12.5: DS
- [-9926]: Global variable.
- [-9925]: Global variable.
- [-9924]: Global variable.
- [-9923]: Global variable.
- [-9922.0f]: Global variable.
- [-9921.0f]: Global variable.
- [-9920.0f]: Global variable.
- [-9919.0f]: Global variable.
- [-9918.0f]: Global variable.
- [-9917.0f]: Global variable.
- [-9916.0f]: Global variable.
- [-9915.0f]: Global variable.
- [-9914]: Unit ID.
- [-9913]: Photo count.
- [-9911.0f]: Current movement angle.
Th12.8: GFW
Th13: TD
- [-9908]: Killable unit count.
- [-9907]: Current spell practice spellcard ID.
Th16: HSiFS
- [-9903]: Current subseason.
Th17: WBaWC
- [-9902]: Graze last second?
ECL Instruction Tables (V1)
EoSD (th06)
This list below lists the opcode, a mnemonic/name, the format and a description for each main ECL instruction used in the subroutines section of the ECL file. This section may also contain some implementation details (irrelevant for most people).
Name | Opcode | Format | Description |
---|---|---|---|
nop | 0x0000 (0) | void | No operation. Technically, every invalid opcode is considered "nop", which includes 0. |
delete | 0x0001 (1) | int a | Stop script execution on this enemy and delete it if a == 1. Implementation detail: Returns -1. |
jmp | 0x0002 (2) | int t, int cp | Unconditionally sets current time to t and sets the current seek offset in this function to cp. |
loop | 0x0003 (3) | int t, int cp, int& var | If var != 0, sets current time to t, sets the current seek offset in this function to cp and decrements var by 1. |
iset | 0x0004 (4) | int &var, int a | Sets var to a. Equiv.: var = a. Interchangeable with fset. |
fset | 0x0005 (5) | int &var, float a | Sets var to a. Equiv.: var = a. Interchangeable with iset. |
iset_r | 0x0006 (6) | int &var, uint a | Sets var to a random value in the range [0, a). If a is 0, sets it to 0. Equiv.: var = rand()
% a |
iset_r2 | 0x0007 (6) | int &var, int min, int a | Sets var to a random value in the range [min, min+a). If a is 0, sets it to 0. Equiv.: var = rand()
% a + min |
fset_r | 0x0008 (8) | int &var, float a | Sets var to a random value in the range [0, a). |
fset_r2 | 0x0009 (9) | int &var, float min, float a | Sets var to a random value in the range [min, min+a). |
get_x | 0x000A (10) | int &var | Sets var to the enemy's x-position. |
get_y | 0x000B (11) | int &var | Sets var to the enemy's y-position. |
get_z | 0x000C (12) | int &var | Sets var to the enemy's z-position. |
iadd | 0x000D (13) | int &var, int l, int r | Sets var to the result of l + r. Equiv.: var = l + r. Interchangeable with fadd. |
isub | 0x000E (14) | int &var, int l, int r | Sets var to the result of l - r. Equiv.: var = l - r. Interchangeable with fsub. |
imul | 0x000F (15) | int &var, int l, int r | Sets var to the result of l * r. Equiv.: var = l * r. Interchangeable with fmul. |
idiv | 0x0010 (16) | int &var, int l, int r | Sets var to the result of l / r. Equiv.: var = l / r. Interchangeable with fdiv. |
imod | 0x0011 (17) | int &var, int l, int r | Sets var to the result of l % r. Equiv.: var = l % r. Interchangeable with fmod. |
inc | 0x0012 (18) | int &var | Increment var by 1. |
dec | 0x0013 (19) | int &var | Decrement var by 1. |
fadd | 0x0014 (20) | int &var, float l, float r | Sets var to the result of l + r. Equiv.: var = l + r. Interchangeable with iadd. |
fsub | 0x0015 (21) | int &var, float l, float r | Sets var to the result of l - r. Equiv.: var = l - r. Interchangeable with isub. |
fmul | 0x0016 (22) | int &var, float l, float r | Sets var to the result of l * r. Equiv.: var = l * r. Interchangeable with imul. |
fdiv | 0x0017 (23) | int &var, float l, float r | Sets var to the result of l / r. Equiv.: var = l / r. Interchangeable with idiv. |
fmod | 0x0018 (24) | int &var, float l, float r | Sets var to the result of l % r (IEEERemainder). Equiv.: var = IEEERemainder(l, r). Interchangeable with imod. |
atan2 | 0x0019 (25) | int &var, float ox, float oy, float tx, float ty | Sets var to the result of atan2(tx - ox, ty - oy). Effectively gives the angle towards tx,ty with ox,oy as the origin. |
norm_r | 0x001A (26) | int &var | Normalizes var into a value that's within the (-pi, pi) range. var will be reduced by 2*pi until it is within that range if it is greater than pi, or incresed by 2*pi until it is within that range if it is lower than pi. |
itest | 0x001B (27) | int a, int b | Compares a with b (integer values). The result will be stored in the enemy's comparison register. The result is -1 if a < b, 0 if a == b or 1 if a > b. |
ftest | 0x001C (28) | float a, float b | Compares a with b (floating-point values). The result will be stored in the enemy's comparison register. The result is -1 if a < b, 0 if a == b or 1 if a > b. |
jmp_l | 0x001D (29) | int t, int cp | If the comparison register is -1, sets current time to t and sets the current seek offset in this function to cp. |
jmp_le | 0x001E (30) | int t, int cp | If the comparison register is -1 or 0, sets current time to t and sets the current seek offset in this function to cp. |
jmp_e | 0x001F (31) | int t, int cp | If the comparison register is 0, sets current time to t and sets the current seek offset in this function to cp. |
jmp_g | 0x0020 (32) | int t, int cp | If the comparison register is 1, sets current time to t and sets the current seek offset in this function to cp. |
jmp_ge | 0x0021 (33) | int t, int cp | If the comparison register is 1 or 0, sets current time to t and sets the current seek offset in this function to cp. |
jmp_n | 0x0022 (34) | int t, int cp | If the comparison register is -1 or 1, sets current time to t and sets the current seek offset in this function to cp. |
call | 0x0023 (35) | int func, int iarg, float farg | Copies variables -10001 to -10012 to backup registers and calls function func. Also, -10001 is set to iarg and -10005 is set to farg. |
return | 0x0024 (36) | void | Returns to the parent function and copies variables -10001 to -10012 from the backup registers. Crashes the game if there is no parent function. |
call_l | 0x0025 (37) | int func, int iarg, float farg, int a, int b | Runs call(func, iarg, farg) if a < b. |
call_le | 0x0026 (38) | int func, int iarg, float farg, int a, int b | Runs call(func, iarg, farg) if a <= b. |
call_e | 0x0027 (39) | int func, int iarg, float farg, int a, int b | Runs call(func, iarg, farg) if a == b. |
call_g | 0x0028 (40) | int func, int iarg, float farg, int a, int b | Runs call(func, iarg, farg) if a > b. |
call_ge | 0x0029 (41) | int func, int iarg, float farg, int a, int b | Runs call(func, iarg, farg) if a >= b. |
call_n | 0x002A (42) | int func, int iarg, float farg, int a, int b | Runs call(func, iarg, farg) if a != b. |
pos | 0x002B (43) | float x, float y, float z | Sets the enemy position accordingly. |
0x002C (44) | float a, float b, float c | Unknown. Sets 3 values in the enemy. | |
dir | 0x002D (45) | float r, float s | Sets enemy movement direction to r and movement speed to s. |
rot | 0x002E (46) | float r | Sets enemy movement direction acceleration to r. |
spd | 0x002F (47) | float s | Sets enemy movement speed to s. |
acc | 0x0030 (48) | float s | Sets enemy movement speed acceleration to s. |
rot_r | 0x0031 (49) | float min, float max | Sets enemy movement direction to a value in the range [min, max). Does not read variables. |
rot_r2 | 0x0032 (50) | float min, float max | Sets enemy movement direction to a value in the range [min, max), according the enemy clip. Does not read variables. |
rot_aim | 0x0033 (51) | float r, float s, float t | Sets enemy movement direction towards the player (+ r) with speed s. |
it_dec | 0x0034 (52) | int t, float r, float s | Moves in a decelerating fashion with direction r, speed s and for t frames. |
it_dec2 | 0x0035 (53) | int t, float r, float s | Moves in a quickly-decelerating fashion with direction r, speed s and for t frames. |
it_acc | 0x0036 (54) | int t, float r, float s | Moves in a accelerating fashion with direction r, speed s and for t frames. |
it_acc2 | 0x0037 (55) | int t, float r, float s | Moves in a quickly-accelerating fashion with direction r, speed s and for t frames. |
it_pt_lin | 0x0038 (56) | int t, float x, float y, float z | Moves in a linear fashion towards x,y,z in t frames. |
it_pt_dec | 0x0039 (57) | int t, float x, float y, float z | Moves in a decelerating fashion towards x,y,z in t frames. |
it_pt_dec2 | 0x003A (58) | int t, float x, float y, float z | Moves in a quickly-decelerating fashion towards x,y,z in t frames. |
it_pt_acc | 0x003B (59) | int t, float x, float y, float z | Moves in a accelerating fashion towards x,y,z in t frames. |
it_pt_acc2 | 0x003C (60) | int t, float x, float y, float z | Moves in a quickly-accelerating fashion towards x,y,z in t frames. |
it_t_dec | 0x003D (61) | int t | Moves in a decelerating fashion for t frames. |
it_t_dec2 | 0x003E (62) | int t | Moves in a quickly-decelerating fashion for t frames. |
it_t_acc | 0x003F (63) | int t | Moves in a accelerating fashion for t frames. |
it_t_acc2 | 0x0040 (64) | int t | Moves in a quickly-accelerating fashion for t frames. |
clip | 0x0041 (65) | float x1, float y1, float x2, float y2 | Confines enemy movement to the defined rectangle. Does not read variables. |
unclip | 0x0042 (66) | void | Disables enemy movement boundaries. |
et_on_fan_aim | 0x0043 (67) | short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag | Sets bullet attributes. Sets type to 0 (aimed fan), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim offset to r1, aim variance per bullet to r2 and bullet flags to flag. |
et_on_fan | 0x0044 (68) | short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag | Sets bullet attributes. Sets type to 1 (unaimed fan), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim to r1, aim variance per bullet to r2 and bullet flags to flag. |
et_on_cir_aim | 0x0045 (69) | short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag | Sets bullet attributes. Sets type to 2 (aimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim offset to r1, aim variance per layer to r2 and bullet flags to flag. |
et_on_cir | 0x0046 (70) | short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag | Sets bullet attributes. Sets type to 3 (unaimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim to r1, aim variance per layer to r2 and bullet flags to flag. |
et_on_cir2_aim | 0x0047 (71) | short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag | Sets bullet attributes. Sets type to 4 (offset aimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim offset to r1, aim variance per layer to r2 and bullet flags to flag. |
et_on_cir2 | 0x0048 (72) | short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag | Sets bullet attributes. Sets type to 5 (offset unaimed circle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, aim to r1, aim variance per layer to r2 and bullet flags to flag. |
et_on_random_r | 0x0049 (73) | short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag | Sets bullet attributes. Sets type to 6 (random angle), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, base speed to sp1, minimum speed to sp2, maximum direction to r1, minimum direction to r2 and bullet flags to flag. |
et_on_random_sp | 0x004A (74) | short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag | Sets bullet attributes. Sets type to 7 (random speed), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, maximum speed to sp1, minimum speed to sp2, aim to r1, aim variance per layer to r2 and bullet flags to flag. |
et_on_random | 0x004B (75) | short spr, short col, int amt1, int amt2, float sp1, float sp2, float r1, float r2, int flag | Sets bullet attributes. Sets type to 8 (random angle speed), bullet sprite and type (hitbox) to spr, bullet color to col, amount per layer to amt1, amount of layers to amt2, maximum speed to sp1, minimum speed to sp2, maximum direction to r1, minimum direction to r2 and bullet flags to flag. |
et_auto | 0x004C (76) | int t | Sets the interval between automatic shooting to t. Zero disables automatic shooting. Does not read variables. Affected by difficulty (~0.8x delay at 32). |
et_auto_delay | 0x004D (77) | int t | Sets the interval between automatic shooting to t and delays the first shot by a random value in the range [0, t). Zero disables automatic shooting. Does not read variables. Affected by difficulty (~0.8x delay at 32). |
et_delay | 0x004E (78) | void | Sets it so setting bullet atributes does not automatically shoot. |
et_on | 0x004F (79) | void | Sets shoot flag. |
et_on2 | 0x0050 (80) | void | Unused. Immediately shoots. |
et_ofs | 0x0051 (81) | float x, float y, float z | Sets bullet shooting offset relative to self. |
et_ex | 0x0052 (82) | int a, int b, int c, int d, float r, float s, float m, float n | Sets extra bullet attributes, used in conjuction with bullet flags. |
et_clear | 0x0053 (83) | void | Clears all bullets and turns them into star items. |
et_se | 0x0054 (84) | int a | Sets bullet sound effect to a. Bullet flag 0x200 (512) must be set for this to work. Using a negative value will turn that flag off. |
laser_on | 0x0055 (85) | short spr, short col, float r, float sp, float start_ofs, float end_ofs, float start_len, float w, int start_t, int t, int stop_t, int graze_delay, int graze_tol, int unk | Shoots a laser with the specified attributes and stores it in a specified index (see laser_id). |
laser_on_aim | 0x0056 (86) | short spr, short col, float r, float sp, float start_ofs, float end_ofs, float start_len, float w, int start_t, int t, int stop_t, int graze_delay, int graze_tol, int unk | Shoots an aimed laser with the specified attributes and stores it in a specified index (see laser_id). |
laser_id | 0x0057 (87) | int i | Sets the index where shot lasers are stored. Defaults to 0. Valid values are 0 to 31. |
laser_rot | 0x0058 (88) | int i, float r | Rotates the specified laser by r. |
laser_aim | 0x0059 (89) | int i, float r | Aims the specified laser towards the player and further rotates it by r. |
laser_ofs | 0x005A (90) | int i, float x, float y, float z | Offsets the specified laser by x,y,z. |
laser_test | 0x005B (91) | int i | Checks if a specified laser is disabled and stores the result in the comparison register. |
laser_break | 0x005C (92) | int i | Instantly cancels out the specified laser and turns it into star bullets. |
card | 0x005D (93) | short face, short card_id, char* name | Begins a spellcard. Increases attempt count by 1, decodes name and sets it as the spellcard name, changes background, displays a portrait face, sets damage reduction to 8x, clears all bullets and calls et_diff_set(-0.5f, 0.5f, 0, 0, 0, 0). |
card_end | 0x005E (94) | void | Ends the spellcard. Clears all bullets, removes spellcard text, restores background, restores damage reduction and gives spellcard and cancel bonuses. |
enm_new | 0x005F (95) | int func, float x, float y, float z, short life, short item, int score | Spawns an enemy func at x,y,z. Sets its life to life, item reward on kill to item and score reward on kill to score. |
enm_clear | 0x0060 (96) | void | Kills all enemies, except for untargetable ones or bosses. |
anm_at | 0x0061 (97) | int id | Runs an anm script on the enemy. TBD |
anm_at_move | 0x0062 (98) | short default, short far_left, short far_right, short left, short right | Sets the various anm script IDs for varying stages of enemy movement. Note: Last 2 bytes go unused due to packing. |
anm_at2 | 0x0063 (99) | int slot, int id | Runs an anm script on the enemy in a separate slot. Only slots 0-7 are valid. TBD |
anm_at_dead | 0x0064 (100) | int id | Sets the anm script ID to run on death. TBD |
boss_set | 0x0065 (101) | int id | Sets the boss ID for this enemy. Will also enable boss health bar and other things when set to a value other than -1, which disables everything again. Defaults to -1. |
boss_card | 0x0066 (102) | int id, float x_rot, float y_rot, float z_rot, float dist | Creates a spinning card graphic around the enemy with the corresponding settings. |
hitbox_set | 0x0067 (103) | float w, float h, float d | Sets the enemy hitbox. |
hit_set | 0x0068 (104) | int a | Toggles enemy contact with the player. Only the LSB is checked! |
hurt_set | 0x0069 (105) | int a | Toggles enemy damage. Only the LSB is checked! |
se_play | 0x006A (106) | int se | Plays a sound effect. |
flag_death_set | 0x006B (107) | int flag | Sets death flags. 0-7 are valid values. |
death_at | 0x006C (108) | int func | Sets the function to call on death. |
var_set | 0x006D (109) | int a, int i | Writes a value into a variable the variable pool at index i. The pool is 4 integers followed by 4 floats. Anything else will over/underflow into other regions. |
0x006E (110) | int a | Unknown. Does various modifications to the enemy. | |
life | 0x006F (111) | int l | Sets the enemy life and max life. |
timeout | 0x0070 (112) | int t | Sets the current timeout time to t. |
life_at_amt | 0x0071 (113) | int l | Sets the life to trigger life_at at. |
life_at | 0x0072 (114) | int func | Sets the function to call when life reaches an amount determined by life_at_amt. |
time_at_amt | 0x0073 (115) | int t | Sets the time at which time_at will trigger. |
time_at | 0x0074 (116) | int func | Sets the function to call when timeout time reaches an amount determined by time_at_amt. |
invinc_set | 0x0075 (117) | int a | Toggles enemy invincibility. Invincible enemies cannot be hurt, touched, cleared or targeted. |
eff_at | 0x0076 (118) | int func, int amt, int col | Spawn a particle effect. |
item_drop | 0x0077 (119) | int amt | Drops amt items around the enemy. Drops power items if not at max power, else drops point items. |
anm_rot_set | 0x0078 (120) | int a | Toggles whether the enemy graphic will rotate according the enemy's angle. |
func_call | 0x0079 (121) | int func, int param | Immediately calls a function from a set of hardcoded functions with parameter param. |
func_set | 0x007A (122) | int func | Sets a function to call every frame from a set of hardcoded functions. Function -1 will disable this. |
func_time_set | 0x007B (123) | int t | Sets the current time variable in this function to t. |
item_drop2 | 0x007C (124) | int item | Drops a specific item at the enemy's position. |
0x007D (125) | void | Unknown. | |
boss_lives_set | 0x007E (126) | int a | Sets the amount of "lives" a boss has. Not automatically decremented! |
debug_watch | 0x007F (127) | int& a | Unavailable debug operation, but probably puts a specific variable in a watchlist. |
anm_break | 0x0080 (128) | int a | Terminates the current enemy graphic if a & 1. |
anm_break2 | 0x0081 (129) | int slot, int a | Terminates the current enemy graphic in slot slot if a & 1. |
0x0082 (130) | int a | Unknown. Toggles a flag. Used by Patchouli. | |
et_diff_set | 0x0083 (131) | float sp_l, float sp_h, float am1_l, float am1_h, float am2_l, float am2_h | Sets the influence of difficulty (rank) on bullets. Default is et_diff_set(-0.5f, 0.5f, 0, 0, 0, 0). Resets to default when a spellcard begins. |
inv_set | 0x0084 (132) | int a | Toggles enemy invisibility. |
0x0085 (133) | void | Unknown. | |
laser_clear | 0x0086 (134) | void | Clears all 32 laser pointers. |
time_card_set | 0x0087 (135) | int a | Toggles survival spellcard. |
Extra Bullet Functions (et_ex)
These are tables for the extra functions bullets can have, along with the variables that can be used with them and a description of them. Note that you can mix and match as many flags as you want in order to get multiple effects by ORing them together, though certain games might only allow you to set a certain number of attributes.
Flag | Variables | Description | |||
---|---|---|---|---|---|
a | b | r | s | ||
0x0001 (1) | X | X | X | X | Deceleration effect at the beginning. |
0x0002 (2) | X | X | X | X | Spawn effect 1 (short). |
0x0004 (4) | X | X | X | X | Spawn effect 2 (medium). |
0x0008 (8) | X | X | X | X | Spawn effect 3 (long). |
0x0010 (16) | O | X | O | O | Accelerate towards direction s (-999 for current direction) with speed r for a frames (negative for 99999 frames). |
0x0020 (32) | O | X | O | O | Increase speed by s and direction by r for a frames (negative for 99999 frames). |
0x0040 (64) | O | O | O | O | Stop in a frames, then change angle by r and set speed to s (negative to keep previous speed). Do this b times. |
0x0080 (128) | O | O | O | O | Stop in a frames, then aim at the player and change angle by r and set speed to s (negative to keep previous speed). Do this b times. |
0x0100 (256) | O | O | O | O | Stop in a frames, then set direction to r and speed to s (-999 to keep previous speed). Do this b times. |
0x0200 (512) | X | X | X | X | Play a sound when shot. |
0x0400 (1024) | O | X | O | X | Make bullet bounce on all 4 walls up to a times and set speed to r on contact (-999 to keep previous speed). |
0x0800 (2048) | O | X | O | X | Make bullet bounce on all non-bottom walls up to a times and set speed to r on contact (-999 to keep previous speed). |
The address of the ECL::RunInstruction function is located at Rx74A0 and return type is a byte type.
Hardcoded Functions (func_call and func_set)
These are tables for the hardcoded functions that can be used for each game. Note that functions that do not need "param" to be set can still be run through func_call.
ID | Needs param? | Description |
---|---|---|
-1 | No | Null pointer. Used to reset func_set. |
0 | Yes | If param is 0, then freeze all bullets in place and change their color to 15. If param is 1, then change every bullet's color to 15 and simulate et_ex(220, -1, -1, -1, 0.01f, -999.0f, -1.0f, -1.0f) with flag 0x10 set. |
1 | Yes | Casts param to float, sets bullet offset to a random point in a param x param area around the enemy and then shoots. |
2 | No | Used in Meiling's Yumekazura (2nd spell). Shoots every 6th frame in a star-shape and aims the bullets in a specific way, and spins every 30. I3 keeps track of the current duration (in frames) of the attack and I4 is the max duration. The hardcoded function is automatically disabled once it reaches the max duration. |
3 | No | Sets variables -10002, -10003 and -10004 respectively according to the shot type: - [0, 3, 1] if ReimuA. - [2, 3, 4] if ReimuB. - [1, 4, 0] if MarisaA. - [4, 2, 3] if MarisaB. |
4 | ||
5 | ||
6 | ||
7 | ||
8 | ||
9 | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 |
PCB (th07)
This list below lists the opcode, mnemonic/name, format and a description for each main ECL instruction used in the subroutines section of the ECL file. This section may also contain some implementation details (irrelevant for most people).
Name | Opcode | Format | Description |
---|---|---|---|
nop | 0x0000 (0) | void | No operation. Technically, every invalid opcode is considered "nop", which includes 0. |
delete | 0x0001 (1) | void | Stop script execution on this enemy and delete it. |
jmp | 0x0002 (2) | int t, int cp | Unconditionally sets current time to t and sets the current seek offset in this function to cp. |
loop | 0x0003 (3) | int t, int cp, int& var | If var != 0, sets current time to t, sets the current seek offset in this function to cp and decrements var by 1. |
iset | 0x0004 (4) | int &var, int a | Sets var to a. Equiv.: var = a. |
fset | 0x0005 (5) | float &var, float a | Sets var to a. Equiv.: var = a. |
Extra Bullet Functions (et_ex)
These are tables for the extra functions bullets can have, along with the variables that can be used with them and a description of them. Note that you can mix and match as many flags as you want in order to get multiple effects by ORing them together, though certain games might only allow you to set a certain number of attributes.
Flag | Variables | Description | |||
---|---|---|---|---|---|
a | b | r | s | ||
0x0001 (1) | X | X | X | X | Deceleration effect at the beginning. |
0x0002 (2) | X | X | X | X | Spawn effect 1 (short). |
0x0004 (4) | X | X | X | X | Spawn effect 2 (medium). |
0x0008 (8) | X | X | X | X | Spawn effect 3 (long). |
0x0010 (16) | O | X | O | O | Accelerate towards direction s (-999 for current direction) with speed r for a frames (negative for 99999 frames). |
0x0020 (32) | O | X | O | O | Increase speed by s and direction by r for a frames (negative for 99999 frames). |
0x0040 (64) | O | O | O | O | Stop in a frames, then change angle by r and set speed to s (negative to keep previous speed). Do this b times. |
0x0080 (128) | O | O | O | O | Stop in a frames, then aim at the player and change angle by r and set speed to s (negative to keep previous speed). Do this b times. |
0x0100 (256) | O | O | O | O | Stop in a frames, then set direction to r and speed to s (-999 to keep previous speed). Do this b times. |
0x0200 (512) | X | X | X | X | Play a sound when shot. |
0x0400 (1024) | O | X | O | X | Make bullet bounce on all 4 walls up to a times and set speed to r on contact (-999 to keep previous speed). |
0x0800 (2048) | O | X | O | X | Make bullet bounce on all non-bottom walls up to a times and set speed to r on contact (-999 to keep previous speed). |
0x1000 (4096) | X | X | X | X | Unknown. Used by hardcoded function 4. |
0x2000 (8192) | O | X | X | X | Set off-screen immunity for a frames. |
Hardcoded Functions (func_call and func_set)
These are tables for the hardcoded functions that can be used for each game. Note that functions that do not need "param" to be set can still be run through func_call.
ID | Needs param? | Description |
---|---|---|
-1 | No | Null pointer. Used to reset func_set. |