Skip to content

Support Maniac Patch (Metabug for all releases) #1818

Open

Description

@Ghabry

Website: https://bingshan1024.github.io/steam2003_maniacs/

Because Maniac Patch is a moving target I decided to close the old issues and just update this one issue here when new features are added, otherwise this slowly becomes messy.

Old issues: #1424, #1557, #1608
Some of these old issues contain more information not moved here yet.

New commands

This command retrieves the same information that is displayed on the default load screen.
It stores the date, time, level and HP in variables and the face graphic in a picture.
Character names are not currently supported.

If the save data does not exist, the date variable will be set to 0.

The face graphic is treated as a 4*4 sprite sheet.
So if you have a file with more than 16 patterns, it will not be displayed correctly.
On the other hand, it doesn't matter if the file is out of the standard as long as it can be divided into 4 parts.

The original picture settings are used, except for the file and sprite sheet related items.
Please use the appropriate picture number to make the picture off-screen or transparent beforehand.

The order of the date (YYMMDD) is the same in the English version.

Numeric Arguments:

  • 00: How to specify the save number (0: constant 1: variable)
  • 01: Save number
  • 02: Variable to receive the save date (YYMMDD)
  • 03: Variable to receive the save time (HHMMSS)
  • 04: Variable that receives the first character's level
  • 05: Variable that receives the first character's HP
  • 06: Reserved items (fixed at 0)
  • 07: How to specify the picture number (0: constant 1: variable)
  • 08: Picture number to receive the face graphic of member 1 (first character)
  • 09: Picture number to receive the face graphic of member 2.
  • 10: Picture number to receive the face graphic of member 3
  • 11: Picture number to receive the face graphic of member 4

This command performs the same operation as the default save function.
It is not possible to use a save number less than 0.

You can optionally store the result of the execution in a variable.
The value is 1 on success and 0 on failure.
Note that the assignment to the variable is done after the save has been executed.

Numeric arguments:

  • 00: How to specify the save number (0: constant 1: variable)
  • 01: Save number
  • 02: Whether to receive the success or failure of the save (0: not received 1: received)
  • 03: Variable to receive success or failure

Not implemented: Black screen with fade-in

This command is equivalent to the default load function.
Save numbers less than 0 cannot be used (the operation is ignored).

Optionally, it checks the file before execution and aborts the load if the result is invalid.
The check is equivalent to the "Get Save Information" command.
If you are sure you have the right file, you can disable it, but it is not recommended. -The

Numeric arguments:

  • 00: How to specify the save number (0: constant 1: variable)
  • 01: Save number
  • 02: Whether or not to check before execution (0:Enable 1:Disable)

  • End Load Process, Code: 3004

Not used anymore

This command cancels the dark state after loading.
It is not available in the new game. The darkness will disappear naturally after 1 frame.


This command gets the relative position of the mouse in the window.
It is based on the resolution of 320*240.

The value will not work correctly if the window is full screen and DirectDraw is specified as the rendering method. (This is probably not a problem, as few machines currently have this setting in effect.

Numeric arguments:

  • 00: Variable to receive X-coordinates
  • 01: Variable to receive Y-coordinates

  • Set Mouse Position, Code: 3006. No support planned: System specific, not exposed by SDL

This command sets the relative position of the mouse in the window.
It is based on a resolution of 320*240.
The x-coordinate is rounded to 0-319 and the y-coordinate is rounded to 0-239 to avoid inducing false clicks.

The values are not correctly handled when the machine is in full screen and DirectDraw is specified as the rendering method.
(This is probably not a problem as few machines currently have this setting enabled.

Numeric arguments:

  • 00: How to specify the coordinates (0:constant 1:variable)
  • 01: X coordinate
  • 02: Y coordinate

Supported but the implementation is not perfect ;)

Generates a picture from the specified string.
Once generated, it can be treated like a normal picture.
Disabling the background, border, gradient and shadow will reduce the cost of generation.

Control characters:

There are several control characters available in the string.
Some control characters are available in the string, e.g. the value in [] can be referenced by \V

  • $a-zA-Z: Draws a special character.
  • \: \ alone is drawn.
  • \C[n]: Change the character colour to the nth character.
  • \D[n]: Aligns the variable value with at least n digits (zero filled).
  • \N[n]: Draws the name of the nth character.
  • \T[n]: Not implemented at the moment.
  • \V[n]: Draws the value of the variable numbered n.

Display position-> coordinates: Specifies the meaning of the position value.
(Traditional pictures are fixed at center coordinates.)

Picture size:
Specify the size of the picture to be generated.
If the value type is set to "Automatic" or the value is set to 0, the picture will be adjusted to the appropriate size.

Font name:
Specify the font to use for drawing.
If this field is left blank, the system settings of the database will be used.

Font size:
The size of the font used for drawing.
Valid values are 1-255, default is 12.

Character spacing:
This specifies the amount of space to be left between each character.
Valid values are 0-255, default is 0.

Line spacing:
The number of spaces per line.
Valid values are 0-255, default is 4.

Bold:
Applies Bold to the font.

System graphics: Specify the graphics to use for drawing.
Specifies the graphics used for drawing.
<Select to refer to the system settings of the database.

Wallpaper:
Specifies the background type for the window.

Draw border: specifies whether the window should have a border or not.
Specifies whether the window should have a frame or not.
If either the height or width is less than 8px, the frame will not be drawn, regardless of the setting.

Enable outside margins:
This specifies whether or not the border area is taken into account when calculating the picture size and text drawing position.
If enabled, the area is 8px on each side and 10px on the top and bottom.

Enabling text gradients:
Enables or disables text gradients, as used in other features such as text display.
If disabled, the text will be drawn from the top left corner (0, 0) of each 16*16px colour.

Enable text shadow:
Enables or disables text shadows, as used in other features such as text display.

Preview restrictions:
Position: Fixed at top left coordinate (0, 0).
Size: - automatically calculated unless specified as a constant.
Magnification: - fixed at 100% (the preview itself can be doubled).
Transparency: Fixed at 0%.
Effects: All effects are disabled.
Font size: 12 unless specified as a constant.

String arguments: (Delimited by 0x01 byte)

  • *1 String to display *1 File name *1 Font name
  • *1...A prefix of type byte indicating the type of value to follow. Currently only 0x01 is valid.

Numeric arguments:

  • 00: Type of value
    • 00~03: How to specify the picture ID (constant=0, variable, variable number variable)
    • 04~07: How to specify the display position (constant=0, variable, variable number)
    • 08~11: How to specify the magnification ratio (Constant=0, Variable, Variable)
    • 12~15: How to set the transparency (Constant=0, Variable, Variable)
    • 16~19: How to specify the picture size (Constant=0, Variable, Variable)
    • 20~23: How to specify the font size (Constant=0, Variable, Variable)
    • 24~27: How to specify the coordinate type (center=0, top-left, bottom-left, top-right, bottom-right, top, bottom-left, left, right)
  • 01: Picture ID
  • 02: Position X
  • 03: Position Y
  • 04: Zoom factor
  • 05: Transparency
  • 06: Red hue
  • 07: Green tones
  • 08: Blue tones
  • 09: Saturation
  • 10: Types of special effects
  • 11: Levels of the special effect
  • 12: Additional effects
    • 00~03: Blend mode (None=0, Multiply, Add, Overlay)
    • 04 : Flip horizontally
    • 05 : Vertical flip
  • 13: Option 1
    • 00~07: Scroll with map
    • 08~11: Background type (none=0, enlarge, tile)
    • 12 : Border not drawn
    • 13 : Gradient disabled
    • 14 : Shadows disabled
    • 15 : Bold text
    • 16 : Margins disabled
    • 24~27: Type with value 1 (in case of angle)
    • 28~31: type of value 2 (if angle is specified)
  • 14: Option 2
    • 00~07: Enable transparent colour
    • 08~15: Character spacing
    • 16~23: Line spacing
  • 15: Layers on the map
  • 16: Layers in battle
  • 17: Delete condition / Screen effect to apply
  • 18: Picture width
  • 19: Picture height
  • 20: Font size
  • 21: Value 2 (if angle is specified)

This command retrieves the position and size of the picture being displayed.
Special effects such as rotation will not be reflected.

Numeric arguments:

  • 00: How to specify the picture ID (constant=0, variable, variable number variable)
  • 01: Stage of the picture (Original image=0, During move, After move)
  • 02: Type of value (centre[xy]wh=0, xywh, ltrb)
  • 03: picture id
  • 04: Variable 1 to receive values
  • 05: Variable 2 to receive values
  • 06: Variable 3 to receive values
  • 07: Variable 4 to receive values

This command allows the user to control some of the defensive battle processes.
This command is only valid for use during the battle, and is deactivated (without all control) at the end of the battle.
It should be used in conjunction with a common event that is conditional on the start of the battle.
Also, weighted commands should not be used within a common event that is being processed.

There are currently five different actions to choose from

ATB Gauge Increase:
This controls the natural increase in the gauge of characters, including enemies, every frame.
The following four variables are used to get or set the value

  1. unit type (get): friendly = 0, enemy = 1
  2. unit number (get) : index (not ID) for both friendly and enemy
  3. current gauge(get) : over 300000 can act
  4. amount of gauge to be increased (get/set)

Damage Pop:
Controls the notation when some damage or recovery occurs.
If you specify a common event for this, the default notation will not be drawn.
There are six variables that can be used to get or set the value

  1. type of unit (get) : friendly=0, enemy=1
  2. unit number (get): index (not ID) for both friend and foe
  3. display position X (get)
  4. display position Y (get)
  5. type of value (get) : damage=0, heal=1, evade=2
  6. value (get)

Targeting:
This is called just before a character's action to control the target of the action.
There are six variables that can be used to get or set values

  1. type of unit (get): friendly=0, enemy=1
  2. unit number (get): index (not ID) for both friend and foe
  3. type of action (get) : *1
  4. value of action (get) : *2
  5. type of target(get) : opponent=0, opponent=1, own=2, own=3
  6. target's number (get/set): index (not ID) for both friend and foe *3

*1:

  • 0: Basic action
  • 1: Special skill
  • 2: Transformation
  • 3: Use item

*2:

  • For Basic Actions: Normal = 0, Continuous = 1, Defensive = 2, Watchful = 3, Forceful = 4, Self-Destruct = 5, Escape = 6, Do Nothing = 7
  • For Special Skills: Special Skill ID
  • For Transfiguration: Enemy Character ID
  • For item use: Item ID

*3:

  • If the target is yourself or the whole group, the setting is invalid.

State Granting
This function is called when a character is granted a state.
The following three variables are used to get or set the value. 1.

  1. unit type (get): friendly=0, enemy=1
  2. unit number (get) : index (not ID) for both friend and foe
  3. state ID (get)

Value change other than damage
This is called when values other than HP change.
The arguments are aligned so that they can be handled in the same event as the damage pop.
The following 6 variables are used to get or set the value

  1. unit type (get): friendly=0, enemy=1
  2. unit number (get): index (not ID) for both friend and foe
  3. display position X (get)
  4. display position Y (get)
  5. type of value (get) : MP=3, Attack=4, Defense=5, Mental=6, Agility=7
  6. value (get)

Numeric arguments:

  • 00: Type of process to control (ATB=0, pop, target)
  • 01: How to specify the Common Event ID (constant=0, variable, variable number variable)
  • 02: Common event ID to use for control
  • 03: Beginning of the variable used to get/set the value

This command is used to control the gauge of characters, including enemies and allies.
The effective range of the gauge is 0~300000.

Numeric Arguments:

  • 00: Type of target (protagonist ID=0, member, party, enemy character, whole enemy)
  • 01: How to specify the target (constant=0, variable, variable number variable)
  • 02: Value of the target
  • 03: Operation (set=0, add, subtract)
  • 04: Type of gauge value (value=0, percentage)
  • 05: How to specify a gauge value (constant=0, variable, variable number)
  • 06: Gauge value

This command is used to enable/disable the change of formation item in the battle command and to edit the party command.

(1) Combat commands

This command can only be used during a battle and will be deactivated after the battle is over.
It should be used in conjunction with the Common Event, which requires the start of combat.

This command can be used to create a situation where there are no combat commands at all. In that case, the game will switch to AI action when you try to choose an action.

Added in 190220: When there are no commands, selecting a transparent item will change the formation

Party Commands:
You can choose any 4 commands from "Fight", "Auto", "Run", "Win" and "Defeat".
Victory" and "Defeat" will literally force you to win or lose the battle.
If you choose all five, the first four will be used, if you choose none, the default three will be used.
If you select only one of them, the screen transition itself will disappear.

Numeric arguments:

  • 00: Whether or not to use the change formation command (enable=0, disable)
  • 01: Flag for party command
    • 00: "Fight" command
    • 01: "Auto" command
    • 02: "Run" command
    • 03: "Win" command
    • 04: "Defeat" command

Retrieves various values that appear during combat.
It does not do anything when not in combat.

The information is output consecutively, starting with the specified variable number.
Character ID/Member/Enemy Character

Ability Correction Value
Gets the value of the character's ability to move up and down during combat, in order of attack, defense, mental strength, and agility.

State:
The total number of all conditions and the number of turns elapsed since the condition was inflicted.
The number of turns is 1 when the condition is inflicted and 0 when it is not.
For example, if the database contains three conditions (1: death, 2: poison, 3: darkness), and you want to get the character's state immediately after the darkness
v[specified variable] = 3
v[variable+1] = 0
v[variable+2] = 0
v[variable+3] = 1
The result is

Attributes:
Gets the total number of values for the current attribute resistance and the status of each resistance.
The values are 2 for increased resistance, 1 for normal resistance and 0 for decreased resistance.
The value of each resistance may be omitted, in which case it is treated as the default value (1).
For example, if you have three attributes in the database (1: sword, 2: spear, 3: strike) and you want to get the character attributes for reduced sword resistance and increased strike resistance
v[specified variable] = 3
v[variable +1] = 0
v[variable +2] = 1
v[variable+3] = 2
The result will be

Other:
The following information about the specified character is obtained in order.
Image centre coordinates X
Image centre coordinates Y
Actionable state (disabled=0, possible)
Defensive state (None=0, Yes)
charge state (none=0, yes)
Appearance state (none=0, yes)

Numerical arguments:

  • 00: Target type (Protagonist ID=0, Member, Party, Enemy character, Enemy as a whole)
  • 01: Type of information. Protagonist ID/Member/Enemy Character: (Ability Correction=0, State, Attribute, Other). Party/enemy: (total number=0, survivors, active).
  • 02: How to specify the target (constant=0, variable, variable number).
  • 03: value of target
  • 04: beginning of variable to receive value

An array of consecutively numbered variables can be manipulated.
It is also possible to operate on a single variable by setting the length of the array to 1.

  • Copy: The value is copied from target 1 to target 2.
  • Exchange: The contents of target 1 and target 2 are exchanged.
  • Sort (ascending order)
  • Sort (descending order): Sort object 1 in ascending or descending order.
  • Shuffle: Subject 1 is sorted randomly.
  • Enumeration: The value for the size is stored in object 1 while adding it by 1 from an initial value.
  • Addition~Shr: It is similar to the operation command of the variable. The difference is that "operand" is also an array.

Numeric arguments:

  • 00: Operation (Copy=0, Exchange, Sort Ascending, Sort Descending, Shuffle, Enumerate, Add, Subtract, Multiply, Divide, Surplus, Or, And, Xor, Shl, Shr)
  • 01: Type of each value
    • 00~03: Object 1 (variable=0, variable number)
    • 04~07: Size (constant=0, variable, variable number)
    • 08~11: Object 2
      • For enumeration (constant=0, variable, variable number)
      • Other (variable=0, variable number)
  • 02: Value of object 1
  • 03: Value of size
  • 04: Value of object 2

The Joypad part is not supported by EasyRPG Player as we provide our own remapping in the configuration scene

This command cannot wait for a key to be pressed.
If you assign keys to the joypad, it will be possible to include the pad when getting the keyboard status.

Get keyboard status list:
Get the status of keys in the keyboard list of the form at once.

Get Keyboard Status List (Disable Assignment):
Get the status of all keys in the keyboard list of the form.
Even if the joypad is assigned, this is ignored.

Get status by key code (allocation disabled):
You can get the status of keys by specifying the key code (0-255) directly.
Use this function when you want to get the status of a key that is not in the list.

Get joypad status list:
Get the status of buttons in the joypad list of the form at once.

Get Joypad Assignment:
Get the current joypad assignment status.
If the button is not assigned, -1 is returned.

Setting joypad assignments:
Assign a joypad button to one of the keys in the key list.

Numeric arguments:

  • 00: Operation details (from 0 to 5 in the order listed above)
  • 01: Start of the variable array used to get or set the value
  • 02: (*only when key code is specified) How to specify the code
    (constant = 0, variable, variable number variable)
  • 03: (*only when keycode is specified) Code

This command rewrites the tiles on the map where the hero is.
Changes made by this command are not reflected in the save and will disappear when you move the map.

Numeric arguments:

  • 00: Type of each value
    • 00~03: Tile ID
      - When single (constant=0, variable, variable number variable)
      - For a range (variable=0, variable number)
    • 04~07: Left end of change range (constant=0, variable, variable number)
    • 0811: Top of change range (Constant=0, Variable, Variable)
      - 12
      15: Width of change range (Constant=0, Variable, Variable)
      - 16~19: Changed range height (Constant=0, Variable, Variable)
  • 01: How to specify a tile (ID=0, Range ID)
  • 02: Layer (lower layer=0, upper layer)
  • 03: Value of tile ID or beginning of variable array
  • 04: Value of the left end of the change range
  • 05: Top value of the modified range
  • 06: Value of the width of the modified range
  • 07: Value of the height of the modified range
  • 08: Auto tile (enable=0, disable=1)

This command deals with the common save data that can be read and written from each save data.
Currently, only switches and variables are supported.
The file name is fixed to "Save.lgs".

Open:
Loads the shared save data from a file.
This operation is ignored when the file is loaded.

Close:
Release the loaded shared save data.
This operation is ignored if the file is not loaded.
Note that this operation does not save the changes.

Save:
Saves the contents of the loaded shared save data to a file.
This operation will be ignored if the file is not loaded.

Save and close: After "Save", "Close" will be executed.

Copy from shared save:
Loads the specified values from a loaded shared save into your own save.
If you do this when the save is not loaded, it will execute 'Open' before processing.

Copy to shared save:
Writes the specified value from your own save data to the loaded shared save data.
If you do this when the save is not loaded, it will execute "Open" before processing.

Numerical arguments

  • 00: Operation details (from 0 to 5 in the above order)

For copy operations only:

  • 01: Type of each value
    • 00~03: First number of the current save (constant=0, see variable)
    • 04~07: First number of shared save (constant=0, see variable)
    • 08~11: Size (constant=0, variable, variable number variable)
  • 02: Type of data (Switch=0, Variable)
  • 03: Value of current save
  • 04: Value of shared save
  • 05: Value of size

As the name suggests, this command changes the ID of the picture.

If you use the "Ignore out-of-range errors" setting, moving from/to an out-of-range ID will be replaced by a simple delete operation.

Move:
Change the picture ID of (size) from (target1) to (target2).
If (Target2) is in use, it will be erased.

Exchange:
The picture ID of (size) from (target1) is replaced with (target2).

Slide:
Move the picture ID of (size) from (target1) by (distance).

Numeric arguments

  • 00: Operation (Move=0, Swap, Slide)
  • 01: Type of each value
    • 00~03: Target 1 (constant=0, variable, variable number variable)
    • 04~07: Size (constant=0, variable, variable number)
    • 08~11: Object 2 (Constant=0, Variable, Variable number)
  • 02: Value of object 1
  • 03: Value of size
  • 04: Value of target 2 or distance
  • 05: Ignore out-of-range errors (enable=0, disable)

This command is used to set the overall behaviour of the game.

Inactivity behaviour:
Whether or not to pause the game when a window becomes inactive.
The default is wait. This setting is reflected in the save data.

Fatal Mix:
This is mainly for debugging purposes.

FPS:
The speed at which the game will run, cannot be less than 1.
This setting is not reflected in the save data.

Test Play:
This is the same as the "TestPlay" start-up option.
This setting will be reflected in the saved data.

Right Shift to skip messages:
While holding down the right shift key, all messages will be displayed momentarily and will close automatically.
This setting is reflected in the save data.

Maximum number of pictures:
This is the maximum number of pictures you can have.
This number has a significant effect on the speed of the game and the load time of saved data.
This setting will be reflected in the saved data.

Frame skipping:
Changes the default drawing process from every frame to once every n frames.
This setting is reflected in the save data.

Numeric arguments:

  • 00: Type of value for argument 02 (constant = 0, variable, variable number variable)
  • 01: Type (Inactive=0, Fatal, Picture, Frame skip)
  • 02:
    • Inactive: Action (Weight=0, Run)
    • Fatal: FPS value
    • Picture: maximum value
    • Skip: value (none=0, 1/5, 1/3, 1/2)
  • 03: Fatal:
    • 00~03: Test play (Do not change=0, Disable, Enable)
    • 04~04: Sentence skip

Note: Unsupported are extensions to this command from later Maniac Versions: Battle Origin, Anim Limit and Face Size


EasyRPG implementation difference: Instead of invoking the command directly it pushes a new frame with a single new command and invokes it (is like a CallEvent with a single command).

This command is intended for advanced users. Please make sure you fully understand the command specifications before using it.

Invokes any command (with exceptions) with any argument.
If a non-existent code is specified, the behaviour depends on the value.

Unavailable commands:

  • Calling a command

Commands that do not work:

  • Set label

Commands that do not work properly:

  • Show choices
  • Handling of battles *only if branching
  • Shop Handling" *only when branching
  • Handling of the inn.
  • Conditional branching
  • Repetition
  • Display of text from the second line onwards
  • Annotations from the second line onwards

String arguments: Code dependent
Numeric Arguments: Code dependent

  • 00: Type of each value
    • 00~03: Code (constant=0, variable, variable number variable)
    • 04~07: First numerical argument (constant=0, variable, variable number)
    • 08~11: Number of numerical arguments (constant=0, variable, variable number)
  • 01: Code
  • 02: Leading number of numerical arguments
  • 03: Number of numerical arguments

Modified commands

Recycles the now unused "bottom transparency" (arg 14) setting as a bit field (seriously...) but the bit field starts at 256 which means it can't be confused with the transparency where the maximum value that makes sense is 255.

  • Blend Mode: Multiple: Bit 9 (256)
  • Blend Mode: Add: Bit 10 (512)
  • Blend Mode: Overlay: Bit 9 + 10 (768)
  • Flip H: Bit 13 (4096)
  • Flip V: Bit 14 (8192)

The origin uses the upper bits of arg 1 which is the "ValueOrVariable" indicator for X/Y.

Rotation:

  • Arg 12 (effect) set to 3
  • Arg 13 & Arg 15: Angle1 / Angle2
  • Arg 16 encodes ValueOrVariable in a bitmask: 0 Constant, 1 Variable, 2 Variable ID. Shifted by 4 for 2nd option.


see #1818 (comment)


  • Conditional Branch Maniac Patch: Final contribution #2797 (Condition "Just Loaded" is not implemented yet!)
  • The method of specifying it by the variable reference was added to the switch.
  • The method of specifying it by the variable of the variable number to the left side value of the variable is added.
  • The method specified by the variable of the variable number was added to the right side value of the variable. Supported
  • Judgment of whether it is just after loading was added.
  • Judgment of whether the joypad is active or not was added.
  • Added judgement whether the window is active or not

Added support for mouse input (left/right centre click, wheel up/down scroll).
Wheel scroll is only valid under the condition of "wait until pressed" because there is no push down state.

The way how the Key input is encoded is a bit strange because it recycles other parameters but by looking at the ones it uses I see some logic.
When the original checkbox is ticked the value becomes 3 (which means it's a bitfield)

Wheel down: Arg 10 = 2 (check_down)
Wheel up: Arg 13 = 2 (check_up)
Mouse left: Arg 3 = 2 (check_decision)
Mouse right: Arg 4 = 2 (check_cancel)
Mouse middle: Arg 9 = 2 (check_shift)


  • Control Variables Maniac Patch: Final contribution #2797 Limited support for the Expression format. Rest is fully supported
  • A range of variable values has been added to the operation target.
  • When a > b in a batch operation, the result is now treated as b~a.
  • Logical OR (or), logical product (and), exclusive logical OR (xor), and logical left-right shift (shl, shr) are added to the operation contents. Proper overflow handling #2734
  • added ID and ATB gauge entries for each character in "operand" (hero and enemy)
  • added items for current date, time and elapsed frame in "operand" section
  • added a switch in "operand" which will be treated as 1 when ON and 0 when OFF
  • added variables for each of "operand" items, hero, event, and enemy character
  • added a party member to "operand". Same as the main character, except that they are specified by an index in the party.
  • added a maths function to "operand".
  • get current event id Support game Ipomoea #3032

In the following explanation, argument 1 is a, argument 2 is b, and multiplier is c.

  • Add, Sub, Mul, Div, Mod, Or, And, Xor, Shl, Shr Proper overflow handling #2734
  • a (operator) b performs the same operation as in "Description".
  • Pow: Calculates a to the b power.
  • Sqrt: Calculates the square root of a * c. Decimal points are rounded down.
  • Sin: Calculates the sine of (a / b) degrees * c. Decimal points are rounded down.
  • Cos: Calculates the cosine * c in (a / b) degrees. Decimal points are truncated.
  • Atan2: Calculates the inverse tangent * c of a(y-coordinates), b(x-coordinates). Decimal points are truncated.
  • Min: Returns the smaller of a, b.
  • Max: Returns the greater of a and b.
  • Abs: Returns the absolute value of a.
  • Random: returns a random number in the range a~b. Same as "random" in "operand".
  • adds ternary operation to "operand".
  • adds patch version to "operand".
  • date in lower 20bit (YYMMDD).
  • The most significant bit represents im/pf (im=0, pf).
  • The rest is reserved space.
  • This item was implemented in 190920, so all bits will be 0 in earlier versions.

How to get the value of a date

  • @> Manipulation of variables: [0001] Assignment, Maniacs version
  • @> Variable manipulation: [0001] And, -1 >> 12

How to get the im/pf value

  • @> Manipulation of Variables: [0001] Assignment, Maniacs' Version
  • @> Manipulation of Variables: [0001] Shr, 31

Add expression format to target and operand


Added method to specify common event by variable number variable.


Added the ability to specify conditions. The switch is treated as a number with 1 for ON and 0 for OFF.
The number of iterations and the index will not be set correctly if a label jump brings you inside the loop.

Infinity: Conventional infinite loop.
Number of times:

  • X Times:
    • Repeats for a specified number of times. You can optionally print an index starting from 0 to a variable.
  • Count up
    • Iterate through the range a to b, adding indices by 1.
    • For example, 2~5 would be a loop of 4 times: 2, 3, 4, 5.
    • You can optionally output the current index to a variable.
  • Count Down:
    • Iterates over the range a to b, decrementing the index by 1.
    • For example, 3~1 would be a loop of 3, 2, 1.
    • You can optionally output the current index to a variable.

While:

  • Repeats as long as the condition is true. Each loop is checked before execution.
  • Comparisons can be specified in the same way as for variable conditionals.
  • You can optionally print an index starting from 0 to the variable.

Do While:

  • Repeats as long as the condition is true. This is done after each loop.
  • Comparisons can be specified in the same way as for variable conditionals.
  • You can optionally print an index starting from 0 to the variable.

see #1818 (comment)


Fixes behaviour when running inside a multiple loop.


  • Battle Processing

Added option to disable flashing before battle starts.

Additional features supported from newer releases

Activity

  1. Ghabry commented on Jul 3, 2019

    @Ghabry
    MemberAuthor

    New versions 190625 and 190630 released. No new features, just unspecified fixes for the new commands.

  2. Ghabry commented on Sep 4, 2019

    @Ghabry
    MemberAuthor

    New version 190904. There is now a website for the patch: https://bingshan1024.github.io/steam2003_maniacs/

    Just a quick summary of notable changes as my time is limited right now:

    • 32 bit framebuffer (files still limited to 8bit)
    • KeyInputProcEx: Can read the keyboard and joypad, does not support "wait for input" (guess this was too difficult to write ;))
    • Rewrite Map: Change tiles, they are not saved and lost when the map scrolls. Sounds quite... experimental o.O
    • Global Save: Allows writing of switches and variables in a "shared savefile"
  3. Ghabry commented on Apr 15, 2020

    @Ghabry
    MemberAuthor

    For later: There is some Command dispatch table in the CHERRY segment (guess this was relocated from the normal Code segment, havn't analyzed RPG_RT that much yet).

    CHERRY:004F40F8 eventDispatchTable dd offset CmdOpenLoadMenu
    CHERRY:004F40F8
    CHERRY:004F40FC dd offset CmdExitGame
    CHERRY:004F4100 dd offset CmdToggleATBWaitMode
    CHERRY:004F4104 dd offset CmdToggleFullscreen
    CHERRY:004F4108 dd offset CmdOpenVideoOptions
    [...] Normal commands here [...]
    Starting at 0x78
    CHERRY:004F42D8 dd offset CmdManiacGetSaveInfo
    CHERRY:004F42DC dd offset CmdManiacSave
    CHERRY:004F42E0 dd offset CmdManiacLoad
    CHERRY:004F42E4 dd offset CmdManiacEndLoadProcess
    CHERRY:004F42E8 dd offset CmdManiacGetMousePos
    CHERRY:004F42EC dd offset CmdManiacSetMousePos
    CHERRY:004F42F0 dd offset CmdManiacShowStringPic
    CHERRY:004F42F4 dd offset CmdManiacGetPicInfo
    CHERRY:004F42F8 dd offset CmdManiacCtrlBattle
    CHERRY:004F42FC dd offset CmdManiacCtrlAtbGauge
    CHERRY:004F4300 dd offset CmdManiacBattleCmdEx
    CHERRY:004F4304 dd offset CmdManiacGetBattleInfo
    CHERRY:004F4308 dd offset CmdManiacCtrlVarArray
    CHERRY:004F430C dd offset CmdManiacKeyInputEx
    CHERRY:004F4310 dd offset CmdManiacRewriteMap
    CHERRY:004F4314 dd offset CmdManiacCtrlGlobalSave
    CHERRY:004F4318 dd offset CmdManiacChangePicID
    CHERRY:004F431C dd offset CmdManiacSetGameOption
    CHERRY:004F4320 dd offset CmdManiacCallCommand
    CHERRY:004F4324 dd offset sub_4FE970 <- No idea what that is
    
  4. Ghabry commented on Mar 12, 2021

    @Ghabry
    MemberAuthor

    About the savedata:
    GetSaveInfo simply uses "..\FaceSet" to point to the Face and ShowStringPicture encodes the string parameter list via \x01: &#xe001;aaaa&#xe001;SystemC&#xe001;RPG2000G&#xe000;. This looks ugly but one has to admit that it makes sense. Event commands only support single text arguments and this is a good short-term workaround when you do not have sourcecode access.

  5. Ghabry commented on Mar 12, 2021

    @Ghabry
    MemberAuthor

    I asked BingShan months ago about a documentation for the "Variable Expression" feature. The expression is compiled to an op code list by the editor and these opcodes are interpreted by the engine:

    @> command arguments:
    Composition of numeric arguments when the target and "operand" are expressions in a variable operation
    
    arg0: fixed value 4, meaning that the target is an expression
    arg1: the starting index of the target expression (in this case argX+1)
    arg2: not used
    arg3: operation content
    arg4: fixed value meaning that "operand" is an expression21
    arg5: length of the "operand" expression
    arg6 ... argX: "operand" expression
    argX+1: length of the target expression
    argX+2 ... argY: target expression
    
    
    
    @> expression: 
    At the moment an expression consists of a single node
    
    
    
    @> node: 
    A node consists of one ID (1 byte) and zero or more arguments immediately following it.
    The number and type of arguments depends on the ID
    
    
    
    @> Node ID list: 
    [ID] name (number of arguments): description
    
    
    [00] null(0): 
        Default node to be used if the required arguments are missing.
        Evaluation value is 0
    
    [01] decimal integer(1): 
        arg0: 1-byte (0 ... 255) integer 255) integer
    
    [02] Decimal integer(1): 
        arg0: integer with 2 bytes (0 .. 65535) integer
    
    [03] Decimal integer(1): 
        arg0: integer with 4byte(-2147483648 ... 2147483647) integer
    
    [04] Hexadecimal integer (1): 
        arg0: integer with 1byte(0 ... 255) integer
    
    [05] Hexadecimal integer (1): 
        arg0: integer with 2 bytes (0 .. 65535) integer
    
    [06] Hexadecimal integer(1): 
        arg0: integer with 4byte(-2147483648 ... 2147483647) integer
    
    [07] (?) : reserved
    
    [08] variable reference (1): 
        arg0: node v[arg0].
    
    [09] switch reference(1): 
        arg0: node s[arg0].
    
    [10] (?) : reserved
    [11] (?) : reserved
    [12] (?) : reserved
    
    [13] Variable number variable reference(1): 
        arg0: node v[v[arg0]]
    
    [14] Variable number switch reference(1): 
        arg0: node s[v[arg0]]
        
    [15] (?) : reserved
    [16] (?) : reserved
    [17] (?) : reserved
    [18] (?) : reserved
    
    [19] Pseudo-array(*):  
        arg0: Number of 1-byte elements. However, if the most significant bit of this value (0x80) stands, the next 4 bytes are used as the number of elements.
        arg1... : Node Element
        
    [20] (?) : reserved
    [21] (?) : reserved
    [22] (?) : reserved
    [23] (?) : reserved
    
    [24] Sign reversal(1): 
        arg0: node (-arg0)
    
    [25] Negation(1):
        arg0: node (!arg0)
    
    [26] Bit-flip(1): 
        arg0: node (~arg0)
        
    [27] (?) : reserved
    [28] (?) : reserved : reserved
    [29] (?) : reserved
    [30] (?) : reserved
    [31] (?) : reserved
    [32] (?) : reserved
    [33] (?) : reserved
    
    [34] Assignment(2): 
        arg0: 
        arg1: node (arg0 = arg1)
        
    [35] In-place addition (2): 
        arg0:
        arg1: node (arg0 += arg1)
        
    [36] In-place subtraction (2): 
        arg0:
        arg1: node (arg0 -= arg1)
    
    [37] In-place multiplication(2): 
        arg0: 
        arg1: node (arg0 *= arg1)
    
    [38] In-place division(2): 
        arg0: 
        arg1: node (arg0 /= arg1)
    
    [39] In-place remainder (2): 
        arg0: 
        arg1: node (arg0 %= arg1)
    
    [40] In-place bitwise disjunction(2): 
        arg0: 
        arg1: node (arg0 |= arg1)
    
    [41] In-place bitwise disjunction (2): 
        arg0: 
        arg1: node (arg0 &= arg1)
    
    [42] In-place bitwise exclusive or (2): 
        arg0: 
        arg1: node (arg0 ^= arg1)
    
    [43] In-place left bit shift(2): 
        arg0: 
        arg1: node (arg0 <<= arg1)
    
    [44] In-place right bit shift (2): 
        arg0: 
        arg1: node (arg0 >>= arg1)
    
    [45] (?) : reserved
    [46] (?) : reserved : reserved
    [47] (?) : reserved
    
    [48] Addition (2): 
        arg0: 
        arg1: node (arg0 + arg1)
    
    [49] Subtraction(2): 
        arg0: 
        arg1: node (arg0 - arg1)
    
    [50] Multiplication(2): 
        arg0: 
        arg1: node (arg0 * arg1)
    
    [51] division(2): 
        arg0: 
        arg1: node (arg0 / arg1)
    
    [52] Surplus(2): 
        arg0: 
        arg1: node (arg0 % arg1)
    
    [53] Bitwise OR (2): 
        arg0: 
        arg1: node (arg0 | arg1)
    
    [54] Bitwise conjunction (2): 
        arg0: 
        arg1: node (arg0 & arg1)
    
    [55] Bitwise exclusive disjunction(2): 
        arg0: 
        arg1: node (arg0 ^ arg1)
    
    [56] Left bit shift(2): 
        arg0: 
        arg1: node (arg0 << arg1)
    
    [57] Right bit shift (2): 
        arg0: 
        arg1: node (arg0 >> arg1)
    
    [58] Compare Same as ~(2): 
        arg0: 
        arg1: Node (arg0 == arg1)
    
    [59] Compare Same as (2): 
        arg0: 
        arg1: node (arg0 >= arg1)
    
    [60] Comparison - Less than or equal to (2): 
        arg0: 
        arg1: node (arg0 <= arg1)
    
    [61] Compare - Greater than (2): 
        arg0: 
        arg1: node (arg0 > arg1)
    
    [62] Compare - Less than (2): 
        arg0: 
        arg1: node (arg0 < arg1)
    
    [63] Compare - other than (2): 
        arg0: 
        arg1: node (arg0 ! = arg1)
    
    [64] Logical OR (2): 
        arg0: 
        arg1: node (arg0 || arg1)
    
    [65] Logical product (2): 
        arg0: 
        arg1: node (arg0 && arg1)
    
    [66] Range (2): 
        arg0: 
        arg1: node (arg0 ... arg1)
    
    [67] Subscript access(2): 
        arg0:
        arg1: node arg0[arg1].
    
    [68] (?) : reserved
    [69] (?) : reserved
    [70] (?) : reserved
    [71] (?) : reserved
    
    [72] Ternary operation(3):  
        arg0:
        arg1:
        arg2: node (arg0 ? arg1 : arg2)
    
    [73] (?) : reserved
    [74] (?) : reserved
    [75] (?) : reserved
    [76] (?) : reserved
    [77] (?) : reserved
    
    [78] Built-in functions (*): 
        See below.
    
    
        
    @> Arguments for built-in functions:
    arg0: 1-byte type of function (ID).
    arg1: 1byte Number of arguments. However, if the most significant bit of this value (0x80) stands, the next 4 bytes are used as the number of arguments.
    arg2... : node Arguments given to the function to call
    
    
    
    @> Type of built-in function:
    [ID] name (number of arguments)
    
    [00] rnd(2)
    [01] item(2)
    [02] event(2) 
    [03] actor(2) 
    [04] member(2) 
    [05] enemy(2) 
    [06] misc(1) 
    [07] pow(2) 
    [08] sqrt(2) 
    [09] sin(3) 
    [10] cos(3)
    [11] atan2(3) 
    [12] min(2) 
    [13] max(2) 
    [14] abs(1)
    [15] clamp(3) 
    [16] muldiv(3) 
    [17] divmul(3) 
    [18] between(3)
    
    Translated with www.DeepL.com/Translator (free version)
    
  6. Ghabry commented on Mar 16, 2021

    @Ghabry
    MemberAuthor

    Chunk information:

    SaveSystem:

    Set by command "Set Game Option":

    88: FrameSkip (kinda useless)

    • 0 = None
    • 1 = 1/5
    • 2 = 1/3
    • 3 = 1/2

    89: Picture limit (useless, ours is dynamic)

    8A: Fatal Mix stuff 4 Byte:

    XX XB XC XD

    B:

    • 0 = Off
    • 4 = Skip message with RShift

    C:

    • 0 = TestPlay Retain
    • 2 = TestPlay OFF
    • 4 = TestPlay ON

    D:

    • 1 = Inactive Run
    • 0 = Wait

    8B: Unknown
    16 Bytes of FF

    SaveEventExecFrame:
    0E: Unknown
    10: Unknown

    12: 2x Little Endian Int32 (-_-) Modified by Loop command

      1. Current Loop Value
      1. Loop End (the loop end is already evaluated when the loop begins)
        For While/Do While the values are undefined (makes sense, as these are not counting loops)
  7. Ghabry commented on Mar 26, 2021

    @Ghabry
    MemberAuthor

    About the new common event things:

    • The "Battle Start" condition is imo useful and also not really dangerous (executes before the Turn 0 battle page)
    • "Battle (Parallel) is unsurprisingly totally unsafe. Took me minutes to find a way to crash it with a null pointer read.
  8. CherryDT commented on May 14, 2021

    @CherryDT

    For later: There is some Command dispatch table in the CHERRY segment (guess this was relocated from the normal Code segment, havn't analyzed RPG_RT that much yet).

    This makes sense because I left an area dedicated for patching in the CHERRY segment (with a note embedded in the segment that says patches should go here). :)

  9. Ghabry commented on May 30, 2021

    @Ghabry
    MemberAuthor

    I redid the entire initial post via DeepL (was a Google Translate before) and improved the formating. Also updated to the latest version before the recompile approach (this is 210414).

    I see no reason in supporting anything post 210414 because this was reverse-compiled allowing huge changes to the engine.


    Good news: I was able to find an older branch where I worked on Maniacs again. Thought I lost it but was just on a different PC :)

    https://github.com/Ghabry/easyrpg-player/tree/maniac-events

    That branch implements:

    • New command: GetSaveInfo
    • New command: Save (not compatible, yields back to the Update loop and uses the Async feature for saving)
    • New command: Load (also via Async yield)
    • New command: Control Var Array
    • Modifed command: Control Variables: Added Date, Time, Frames and Patch-Version (210414)
    • Planned: Modified command: Read Mouse state via Key Input Proc
  10. Ghabry commented on Aug 30, 2021

    @Ghabry
    MemberAuthor

    Also interesting are the new loop commands that can do more than just "endless loop". It also adds Count up/down and (do) while. Pretty useful if you ask me. The commands completely replace the old ones, here are the function addresses:

    • Begin Loop: 4FF870
    • Repeat Loop: 4FF9E0 (thats the event at the bottom of a loop)
    • Break Loop: 4FF710

    And here what they do (not motivated to code right now, so just documenting it for later)

    Loop

    Param 0 is the loop type. 0 (or no argument) is a normal, endless loop.

    For all other cases when too short it allocates "8 * (depth + 1)" byte for maniac_loop_info and sets maniac_loop_info_size to "depth + 1". (This was already known and is in liblcf). These loop info contain a current and a end value for each depth (this allows having loops inside loops properly).

    • Arg 1: Type (Value, Variable, etc.)
    • Arg 2: Index for Arg1

    For "X Times"

    • Current = 0
    • End = Result of Arg1/2 lookup

    Count Up

    • Current = Result of 1/2
    • End = Result of (1 >> 4)/3 (so the type parameter is for whatever reason used to define both types)

    This is like "X Times" but the Begin value can be set.

    Count Down

    Like count up, but the values Current and End receive are swapped

    While

    Assignment like Count Up

    When Current == End, Current = End = 0, also Skips shared logic, except for Arg4

    Do While

    Current = 0, End is kept as is
    Skips shared logic, except for Arg4

    Shared logic

    When Current <= End: Arg 4 is a Variable that receives "Current "
    Otherwise: Loop is skipped

    Repeat Loop

    The arguments from Loop are duplicated in here (makes sense, otherwise it would be necessary to scan for the loop command)

    When Param 0 is 0 or missing it is the normal endless loop

    In the other cases: It allocates as above if too short (likely safety reasons to prevent crashes)

    "X Times" and "Count Up"

    Increment Current by 1.
    When Current > End: Ends the loop

    Count Down

    Decrements Current
    When End > Current: Ends the loop

    "While" and "Do While"

    (not sure how the operator is encoded, easiest way here is just changing stuff and looking in lcf2xml output)

    Contrary to the X Times and Count Up/Down where the value is resolved in the Loop command here the values are resolved everytime "Repeat Loop" is reached.

    When the condition for the two checked values is true (depending on the operator) then "current" is incremented by 1. End is never touched.

    When the condition is false the loop is aborted.

    Shared logic

    When the loop is continued then the variable specified by arg4 received "current".

    Break Loop

    This doesn't touch the loop_info stuff, also no cleanup. It just fixed the bug that break does not break the correct loop when there are multiple loops active.

  11. Ghabry commented on Aug 30, 2021

    @Ghabry
    MemberAuthor

    Erase Picture

    at 4FD16C

    Okay, no surprises here but better to take a look ;)

    • Arg 0: Value
    • Arg 1: Type of operation

    Before 2k3E this only supported "Arg 0 = Picture ID"

    Cherry added:

    • "Arg 1 = 1", then Arg 0 is Variable resolved to Picture ID
    • "Arg 1 = 2", then this is a range from [Arg0, Arg2]

    BingShan added:

    • "Arg 1 = 3", Like the range, but Arg0 and Arg2 are Variables resolved to Values
    • "Arg 1 = 4", Variable indirect (V[V[Arg0]])
    • "Arg 1 = 5", Erase all pictures via a loop
  12. Ghabry commented on Aug 30, 2021

    @Ghabry
    MemberAuthor

    New command: Control Var Array

    The arguments are already documented by BingShan (see top comment)

    tl;dr: Nothing surprising here (good)

    This basicly operates on two slices in the variables array.

    When the resolved value of "slice1" is < 1 or the lengh of the slice is <= 0: Abort the command.

    Note:
    In all cases, even when aborting without write the Map events are refreshed
    I omit notes about resizing the array.

    Copy

    When target (slice2) < 1: Abort.
    Otherwise: memcpy from slice2 into slice1

    Exchange

    When target (slice2) < 1: Abort.
    This swaps the values in the two slices (loop goes backward but this is irrelevant)

    Sort (Ascending) & Sort (Descending)

    Does a numeric sort
    Slice2 is ignored

    Shuffle

    This loops backwards. For each element pick a random number from the slice and then swap current with the picked one.
    Slice 2 is ignored

    Enumerate

    This loops backwards again (maybe is a compiler optimisation...)
    Slice 2 is just a constant here.
    This fills Slice 1 with incrementing numbers until len.

    E.g. The constant is 2 and len is 3, then the result in the slice is 2, 3, 4.

    Everything else (Math operations from Add to Shr)

    This shares code:
    The result is in slice2 (so different to "Copy" where the result is in slice1)

    For Div and Mod: In the 0-case a 1 is assumed.

    Operation order, relevant for Div, Mod, SHL, SHR: slice1_val OP slice2_val.

  13. 18 remaining items

  14. Ghabry commented on Oct 22, 2023

    @Ghabry
    MemberAuthor

    With #3051 there is support for String Variables added.

    Implementation differences:

    1. Bing Shan must have reimplemented the Message Box command parser. It behaves now completely different to vanilla:
    • An unprocessed/unknown command, is now rendered as \a[1] instead of [1].
    • The way how e.g. speed \s[1] is escaped/rendered changed

    This shouldn't be a huge problem because unprocessed command codes are likely a game bug.

    1. We use UTF-8 as the internal encoding instead of the local codepage (e.g. shift-jis or 1252), this changes how the string length is calculated. In general the string length in a bytes is pretty worthless so I don't think this is a big deal. Counting codepoints gives a result that matches Maniac Patch due to luck String Variables: Operate on Codepoints #3303

    2. We use the C++ regex library. It could be that the implementation differs. This wasn't tested alot yet.

    3. Reading of binary files behaves different but this shouldn't be a problem as you are not supposed to access binary files with the text API.

  15. CherryDT commented on Oct 22, 2023

    @CherryDT

    Hm, as many issues in this repo showed, what is "not supposed to" be done is often used in creative ways, especially in Japanese games......

  16. deleted a comment from XPMilkChan on Oct 22, 2023
  17. ToolMan2k commented on Dec 19, 2023

    @ToolMan2k
    Contributor

    I was playing around with pictures, especially the ".scale2" argument. It allows to stretch a picture using width and height parameters. Using TPC, it looks like this:

    pic[10].show {
        "TestStone"
        .pos v[1], v[2] .center
        .chromakey 1
        .scale2 v[3], v[4] // width, height
        .trans 0
        .rgbs 100, 100, 100, 100
        .mapLayer 7
        .eraseWhenTransfer
        .affectedByFlash
        .affectedByShake
    }
    

    I made a test project for testing interactions between various settings.
    Do whatever you want with it. :)

    PictureTest.zip

    Here's my observations:

    • Normal, Static picture: Works as intended

    • Effects: (wave, rotation, angle): Width works as regular magnify, Height is ignored

    • Blending: Works as intended

    • Flip (H/V): Works as intended

    • Spritesheet, Static, Normal: Works as intended

    • SpriteSheet, Static, Effects: Works the same as Normal, Effects picture

    • Spritesheet, Loop, Normal: (this gets interesting)

      • If Width AND Height == 100: works as intended
      • If Width AND Height != 100: works as intended
      • If Width OR Height == 100: picture isn't properly cropped based on the current frame coordinates and size.
        For example, on a 8x8 sprite sheet with 32x32 resolution
        • If Width is set to 100: sprite is stretched horizontally based on its current x frame coordinate (32 * x)
        • If Height is set to 100: sprite is stretched vertically based on its current y frame coordinate (32 * y)
    • SpriteSheet, Loop, Effects: works the same as Normal, Effects picture

    • Display Position (from topLeft to bottomRight):
      Sprite is placed at the correct position as if Magnify was set to 100%
      However, from its current position, it scales from the center (as shown by the cursor)
      I tried setting both Width and Height to 200%, but the same thing happens.

    So here's the kicker:

    • Scaling works as intended when not using Wave/Rotation effects
    • When using these effects, Width is used as the Magnify value
    • When using a looping SpriteSheet, if only one of Width or Height is different from 100, it gets funky.
    • Picture doesn't align properly when using Display Position

    Bonus: I also managed to crash EasyRPG when moving a picture with Display Position set.

  18. ToolMan2k commented on Dec 28, 2023

    @ToolMan2k
    Contributor

    I managed to implement separate Width/Height values for drawing pictures, it can even Save and Load as required!
    #3180

    There's still work to do, for instance saves from ManiacPatch and EasyRPG aren't Byte-identical, when saving/loading between versions, it skips a few unknown chunks:

    Skipped Chunk 86 (1 byte) in lcf at 1F9 (SaveSystem)
    01 
    Skipped Chunk 87 (1 byte) in lcf at 1FD (SaveSystem)
    04 
    Reading Primitive of incorrect size 4 (expected 1) at 29D
    SavePicture: Corrupted Chunk 0x06 (size: 4, pos: 0x29d): fixed_to_map : Read 7 bytes! Reseting...
    Reading Primitive of incorrect size 3 (expected 1) at 2AD
    SavePicture: Corrupted Chunk 0x09 (size: 3, pos: 0x2ad): use_transparent_color : Read 5 bytes! Reseting...
    Skipped Chunk 0A (8 byte) in lcf at 2B2 (SavePicture)
    00 00 00 00 00 60 73 40 
    Skipped Chunk 24 (2 byte) in lcf at 2D0 (SavePicture)
    82 36 
    Skipped Chunk 0A (8 byte) in lcf at 345 (SavePicture)
    00 00 00 00 00 60 73 40 
    Skipped Chunk 1E (2 byte) in lcf at 362 (SavePicture)
    82 20 
    Skipped Chunk 24 (2 byte) in lcf at 37E (SavePicture)
    82 36 
    Debug: Loading Save Save01.lsd
    Skipped Chunk 86 (1 byte) in lcf at 1F9 (SaveSystem)
    01 
    Skipped Chunk 87 (1 byte) in lcf at 1FD (SaveSystem)
    04 
    Reading Primitive of incorrect size 4 (expected 1) at 29D
    SavePicture: Corrupted Chunk 0x06 (size: 4, pos: 0x29d): fixed_to_map : Read 7 bytes! Reseting...
    Reading Primitive of incorrect size 3 (expected 1) at 2AD
    SavePicture: Corrupted Chunk 0x09 (size: 3, pos: 0x2ad): use_transparent_color : Read 5 bytes! Reseting...
    Skipped Chunk 0A (8 byte) in lcf at 2B2 (SavePicture)
    00 00 00 00 00 60 73 40 
    Skipped Chunk 24 (2 byte) in lcf at 2D0 (SavePicture)
    82 36 
    Skipped Chunk 0A (8 byte) in lcf at 345 (SavePicture)
    00 00 00 00 00 60 73 40 
    Skipped Chunk 1E (2 byte) in lcf at 362 (SavePicture)
    82 20 
    Skipped Chunk 24 (2 byte) in lcf at 37E (SavePicture)
    82 36 
    Debug: Savegame version 0 (RPG_RT or EasyRPG Player Pre-0.6.0)
    Debug: Loaded Map Map0001.lmu
    Debug: Tree: MAP0001
    
    

    For everything else, it works as expected.

  19. ToolMan2k commented on Jan 7, 2024

    @ToolMan2k
    Contributor

    Just discovered that using the command ShowPicture with a StringVar crashes the game by showing picture ID -1.
    Looking into the code, seems that parameter 17 is set like this:

         256        0
    000000xx 000000xx
           ^        ^
           |        |
    StringVar    PicID
    
    

    EasyRPG does a ValueOrVariable check on this value, however it does not check if it's equal or higher than 256 (bitfield that Maniac Uses).

    I've made this quick change in game_interpreter.cpp, for CommandShowPicture:

    if (com.parameters[17 >= 256 && Player::IsPatchManiac()]) {
        pic_id = ValueOrVariableBitfield(com.parameters[17], 0, pic_id);
        params.name = ToString(CommandStringOrVariableBitfield(com, 17, 2, 30));
    } else {
        pic_id = ValueOrVariable(com.parameters[17], pic_id);
    }
    

    Now it just works!

    Edit: Pull request right there #3182

  20. Ghabry commented on Nov 27, 2024

    @Ghabry
    MemberAuthor

    We are really close to fully support legacy Maniac Patch :)

    Only missing are:

    • A and B autotiles for Rewrite Map
    • Command Change Picture ID
    • Command Set Game Option
    • Parallel interpreters running in battle (ugh!)
    • For Battle Processing the option that disables the flash before the battle starts
  21. Ghabry commented on Dec 1, 2024

    @Ghabry
    MemberAuthor

    Strange behaviour with Maniac Patch while in the battle system:

    Showing a message box (doesn't matter how) freezes the entire battle system:

    CBA idle animations stop playing and do not even continue when you close the message box. Fixes itself after doing any action.


    This can also be observed when a message box opens because of a damage callback: The enemy flickers for one frame, then everything hangs until the message box is closed. 🤔

  22. florianessl commented on Mar 27, 2025

    @florianessl
    Member

    I'm not sure if this ever came up before, but it may cause issues in some very rare cases:

    On Maniacs official website (https://bingshan1024.github.io/steam2003_maniacs/ -> section "im version and pf version") it is stated that the upper limit for number of executed commands per frame has been increased from 10,000 to 200,000.

    Google Translated:

    Additionally, as of 5/26/19, the upper limit on the number of commands that can be executed per event per frame has been increased from the standard 10,000 to 200,000.

    But it isn't clear to me, if this change affects both im & pf versions, or just the pf one.

  23. Ghabry commented on Mar 27, 2025

    @Ghabry
    MemberAuthor

    This is a general change and no idea why you want this because 10000 can already lag 😅

  24. Mimigris commented on Jun 16, 2025

    @Mimigris
    Contributor

    Maniac 211010 seems to badly handle having a panorama doing a 1x1 size. While on RPG_RT and EasyRPG, the pixel will be assigned on the whole panorama, Maniac seems to do something more akin to a tileset, displaying black outside of the areas where the 1x1 pixel would be displayed

    EasyRPG on the left, Maniac on the right.
    Image

    Haven't checked other versions of Maniac, so not sure where it started/if it was fixed at some point or not.

    Panorama used:
    green_pixel.zip

  25. Mimigris commented on Jun 29, 2025

    @Mimigris
    Contributor

    Maniac also seems to handle invalid actors referenced in text as actor 1, rather than crashing (RPG_RT behaviour)/displaying a warning (EasyRPG behaviour).
    Image

    Image

  26. Ghabry commented on Apr 16, 2026

    @Ghabry
    MemberAuthor

    Figured out how the values for Show String Picture when Font and/or System Name are a variable are encoded.

    We already knew that the \x01, \x02, \x03 delimiter is the mode (Direct, Var, VarIndirect).

    For Var(Indirect) it writes a string into the component which looks like some random garbage data. But the garbage data is actually the number. It's a 5 bit encoding and honestly: wtf is this? Instead of just putting the number into an additional parameter they invented a custom encoding (and why a custom encoding and not simply use base32 or base64?).


    For the rightmost character c it is:

    c - A + 1

    For all other characters c with index i it is:

    (c - a + 1) << (i * 5)

    The string has a max length of 6 characters (due to integer overflow).

    No idea why it changes from A to a. There is no obvious reason why its done that way.


    Assuming we have biI:

    idx  210
    char biI
    

    Then the calculation is:

    (b - a + 1) << (2 * 5) = 2048
    (i - a + 1) << (1 * 5) =  288
    (I - A + 1)            =    9
                             ----
                             2345
    

    For e~wpp@:

    (e - a + 1) << (5 * 5) = 167772160
    (~ - a + 1) << (4 * 5) =  31457280
    (w - a + 1) << (3 * 5) =    753664
    (p - a + 1) << (2 * 5) =     16384
    (p - a + 1) << (1 * 5) =       512
    (@ - A + 1)            =         0
                             ---------
                             200000000
    

    The largest possible number is a 30 bit unsigned integer:

    2^30 - 1 = 1073741823


    Sanity check:

    the rightmost character must be in range [@, _] or in other words when you do the computation the result must be [0, 31].

    All other character must be in range [a, \x7F]. \x7F is control character DEL. Yes they invented a custom encoding and it isn't even 100% printable text 🤦 . Same rule: It must fall in [0, 31].

  27. CherryDT commented on Apr 16, 2026

    @CherryDT

    You could also ask BingShan directly about it, for example on the Maniac patch Discord server.

  28. Ghabry commented on Apr 16, 2026

    @Ghabry
    MemberAuthor

    On first glance the problem didn't look hard enough to ask about it 😅 (in the end only needed ~1h to figure it out)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions