0% found this document useful (0 votes)
41 views13 pages

Lua If Statement in Sider Module Guide

pes 2019

Uploaded by

kibinov707
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views13 pages

Lua If Statement in Sider Module Guide

pes 2019

Uploaded by

kibinov707
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

Sider 5 Lua Module Programmers Guide

====================================
For [Link] version: 5.2.3
April 4, 2019

1. Introduction
~~~~~~~~~~~~~~~

The main idea here is to provide a safe and flexible way to


extend Sider functionality. It allows modders to alter many
aspects of game logic, and load all sorts of extra content.
Visual and gameplay tweaks are possible too.

Instead of offering a C interface, where the programmers would need


to write a DLL, i'm a taking a different approach here and trying to
design a system, where extension modules are written in Lua. A module
would typically initialize itself by registering for certain events,
and then Sider will call the module functions, when those events
occur later in the game.

Lua is by now a well-established language of choice for scripting


support in games, used all over the gaming industry. Most famous
example is probably WarCraft, but many modern games use it, including
Pro Evolution Soccer itself.

To boost the performance, Sider uses a just-in-time compiler for Lua


called LuaJIT, written by Mike Pall. LuaJIT is a truly brilliant piece
of software. It is 100% compatible with Lua 5.1, and it is super fast,
often approaching and sometimes exceeding the speed of C code.
( More information here: [Link] )

After reading this guide, the next step is to study the example (and
non-example) modules, which are provided with this release of Sider.
Find them in the "modules" directory.

2. Module structure
~~~~~~~~~~~~~~~~~~~

If you are familiar with Lua and how modules are typically organized
then this will make full sense to you. If are you new to Lua, i would
strongly recommend reading "Programming in Lua" by Roberto Ierusalimschy.
2nd edition covers Lua 5.1, which is the version of the language used
by Sider. However, any other edition of the book will be just as helpful.

In any case, the module organization is pretty simple:

a) Your need to create a new table


b) Provide an "init" function in that table, where you need to
do any initialization logic for the module and register for the events
your module is interested in.
c) Return that table as the last statement

Example module:

-----------------------------
local m = {}

function [Link](ctx)
log("Hello, world!")
end

return m
-----------------------------

As you have already guessed, this module doesn't really do much. But it
is a valid module, and can be loaded by Sider. For that you need to save
it as <something>.lua file in the "modules" folder, inside sider. Let's
assume that you named it: [Link]. Then, you must also enable it in
[Link], like this:

[Link] = "[Link]"

**************************************************************************
**************************************************************************
VERY IMPORTANT: File encoding must be UTF-8. This is vital, if you are
using non-latin characters in the strings in the module code - for example,
in paths. If you only have latin-1 chars, then ANSI is ok too.
**************************************************************************
**************************************************************************

If you now run the game, your module will get loaded by Sider, and then
the "init" function will be called, so you should see a "Hello, world!"
message in [Link].

If you made a mistake and your module has a syntax error, for example,
or some other problem, then you should see an error message in [Link],
explaining where (on which line of the script) the problem occurred.

Let's now see how you can make a more useful module. First step for that
is to understand the context object (ctx).

3. Context object
~~~~~~~~~~~~~~~~~

Context object is what Sider "knows" about the current state


of the game. As more scripts/modules are created by the community
the context object will probably also change, and include more and more
information about the game.

As of 5.2.2 release, the context object has the following:

ctx.home_team - id of the home team of the current match, after


it is selected in the exhibition match, or the next
match is determined in the league mode.

ctx.away_team - id of the away team of the current match, after


it is selected in the exhibition match, or the next
match is determined in the league mode.

ctx.tournament_id - numeric id of the current tournament. See


doc/[Link] file for the list
of ids for all of the game's tournaments.

ctx.match_id - some sort of number, which seems to indicate where


in the season you currently are. However, the exact
meaning of this id is unclear. Maybe you can figure
it out and tell me ;-)

ctx.match_leg - set to 1 or 2, if this is 1st leg or 2nd leg of


a two-legged knock-out match.

ctx.match_info - meaning of this field varies, depending on the type


of tournament:
league: number of league matches already played
cup/play-off:
46 - first round of play-off,
47 - second round of play-off,
51 - quaterfinal,
52 - semifinal,
53 - final
You can use this together with ctx.tournament_id to
identify a final match of a particular tournament.

[Link] - numeric id of the stadium that will be used (or was


last used, if the stadium for the next match hasn't
been chosen yet by the game logic)

ctx.stadium_choice - This field is set when the game is in one of the


exhibition modes, and the stadium is allowed to
be selected via the menu. Once the actual final
selection of the stadium is made (right after the
"set_stadium" event fires), the "stadium_choice"
field get removed from the context.
Special values:
253 - home stadium
254 - random stadium
255 - not chosen yet

[Link] - The values are: 0 - Day, 1 - Night. Same as with


stadium, it represents the time of day of the coming
match, or the last one, if the stadium isn't set yet
for the next match.

[Link] - The values are: 0 - Summer, 1 - Winter.

[Link] - The values are: 0 - Fine, 1 - Rainy, 2 - Snowy

ctx.weather_effects - The known values are:


2 - enforce weather effects (rain/snow falling)

ctx.match_time - Duration of the match in minutes.

The context object also contains a register function, which has the
following signature:

[Link](event_name, handler_function)

The event_name parameter is a string, which identifies a particular


event. The handler_function should be a function in your Lua module,
which will be called when the corresponding event happens. Parameters
vary depending on the event - see the next section for details on all
supported events and their handler signatures

The idea of the context object is that in your handler functions, your
code will make decisions on what to do, using the information in the
context.

4. Supported events
~~~~~~~~~~~~~~~~~~~

- Event name: "livecpk_make_key"


Handler function: f(ctx, filename)
Return value is expected to be a string or nil.

This event occurs when the game needs to find out some information
about the file, specified by relative filename. Maybe the game needs
to create a buffer, or it needs to determine the filesize, or something
else. Your handler function is expected to return a string key that
will be used for caching of "livecpk_get_filepath". You can just
return filename as the key, without any changes, or return nil -
which will result in the same outcome. But sometimes, you need to make
a different key, because the context has some additional information
that is important.

IMPORTANT: This event can fire a lot of times for a given filename,
so try to avoid doing expensive computations in the handler function
or logging anything, because it may affect your frame rate.

- Event name: "livecpk_get_filepath"


Handler function: f(ctx, filename, key)
Return value is expected to be a string or nil.

This event is related to "livecpk_make_key".


It works like this: after the key is returned by livecpk_make_key
handler, sider needs to know which actual file (absolute path) needs
to be loaded for this key. So your handler function is expected to
return a full absolute filename. Sider will cache this absolute filename
using the key returned by livecpk_make_key, and the next time this file
is needed, the livecpk_get_filepath event will NOT fire. (This is
again done for performance reasons so that we don't unnecessarily seek
the disk).

- Event name: "livecpk_rewrite"


Handler function: f(ctx, filename)
Return value is expected to be a string or nil.

Allows the filename to be rewritten to another. This is a very


powerful, but also quite dangerous function, if you are not careful.
If you rewrite the filename to something that does not exist in
LiveCPK roots or in download/data CPKs, and none of your modules
provide the content, then the game will be unable to load the file,
which can lead to different behaviours, depending on type of file being
loaded. If it's a DDS texture, then usually nothing bad happens -
you just get a white texture. But if it is a model file - you will
get an endless loop, where loading indicator will keep spinning
forever, or the game can just crash. So, be careful,
and don't rewrite blindly ;-)

See "[Link]" module for an example of rewrite usage: it is


loading a 2nd player kit instead of a 1st goalkeeper kit, so your
goalkeepers end up wearing 2nd kit of outfield players.

- Event name: "livecpk_read"


Handler function: f(ctx, filename, data, size, total_size, offset)
Return value: nil.

Provides a pointer to the buffer in memory ("data") that have just


been filled with data. The "size" parameter gives the number of
bytes that have just been read into that buffer. The other parameters
provide the additional context for the read:
- filename: the relative pathname of the file,
(For example, "common\pesdb\etc\[Link]")
- total_size: total size (in bytes) expected to be read
eventually for this file
- offset: offset in file before the read happened

See "[Link]" and "[Link]" modules for example usage of


this event. This is an advanced feature, which you will need if
you wanted to examine the data that the game is about to use.
Care must be taken to not leak memory. Also, be aware that some
large files are not read all-at-once, but instead in multiple
read operations. In such situation, use "offset" and "total_size"
parameters to check if the file has been fully read, like this:

if offset + size >= total_size then


-- last read: we now got all of the data
-- do something with it
...
end

See "[Link]" for complete example of handling both


multi-read and single-read files.

- Event name: "set_teams"


Handler function: f(ctx, home_team, away_team)
Return value expected: nil

This event fires after both home and away teams are determined -
either during the team selection in exhibition game, or when the next
match becomes known in a league or a cup mode (League, Master League,
UCL, Europa League, etc.)
The team ids are also set as "home_team" and "away_team" fields in
the context object so that they can be used later, if needed.

- Event name: "set_match_time"


Handler function: f(ctx, minutes)
Return value expected: nil or integer

This event occurs, when the game sets the mach duration. If your handler
function returns an integer, then this value will be used as the match
time in minutes. This way you can accelerate or slow down the matches
beyound the allowed 5-30 minute range. See [Link] - for an example
of such script.

- Event name: "set_stadium_choice"


Handler function: f(ctx, stadium_id)
Return value expected: nil or stadium_id

This event fires, when the game prepares to display the stadium image
or when it is entering pre-game menus of non-exhibition modes. In addition
to the actual id of the stadium chosen, the "stadium_id" parameter may have
the following special values:
253 : "home stadium"
254 : "random stadium"

You handler function can change it, if it returns an integer value instead of nil.
This integer value can either be a stadium id, or one of the following special
values, mentioned above.

NOTE: the final stadium selection isn't actually made, until after the
"set_stadium" event. So, if you want to change the stadium, or see what
was eventually chosen as random/home stadium, then you will need to also register
for the "set_stadium" event.

- Event name: "set_stadium"


Handler function: f(ctx, options)
Return value expected: nil or number or table

This event fires, when the stadium settings are chosen for the upcoming
match. The "options" parameter is a Lua table which contains the following
keys: "stadium", "timeofday", "weather", "weather_effects", "season".
Each of these has an integer value, as the game uses:
for stadium - it is the id of the stadium,
for timeofday: 0 - means Day, 1 - means Night;
for weather: 0 - Fine (sunny), 1 - Rain, 2 - Snow;
for weather_effects: 2 - means enforce falling rain/snow, other values - unknown
for season: 0 - Summer, 1 - Winter

You handler function can either return nil, which means that other modules
can receive the event and process it. Or, the handler can return an stadium
id - an integer - to switch the stadium to another one. Be careful though:
sider doesn't check for correctness of values, so if you switch to a
non-existent stadium, the game will probably crash or go into infinite
"loading" loop. For an example usage - see [Link] module.

( For backwards compatibility, returning a table like this:


{ stadium = <stadium-id> } is also supported. However, any other keys in
that table will be ignored. )

To change weather, timeofday and season - use a different event, called:


"set_conditions", which is documented further down in this document.

- Event name: "set_conditions"


Handler function: f(ctx, options)
Return value expected: nil or table
This event fires, when the stadium settings are chosen for the upcoming
match. The "options" parameter is a Lua table which contains the following
keys: "stadium", "timeofday", "weather", "weather_effects", "season".
Each of these has an integer value, as the game uses:
for stadium - it is the id of the stadium,
for timeofday: 0 - means Day, 1 - means Night;
for weather: 0 - Fine (sunny), 1 - Rain;
for weather_effects: 2 - means enforce rain falling, other values - unknown
for season: 0 - Summer, 1 - Winter

You handler function can either return nil, which means that other modules
can receive the event and process it. Or, the handler can return a table
of options, which are either modified or not. Returning a table of options
stops further propagation of the event. You cannot change the stadium id -
for that use "set_stadium" event. But you can change any of the other
three settings: just assign them different values.
For an example usage - see [Link] module.

- Event name: "after_set_conditions"


Handler function: f(ctx)
Return value expected: nil

This event fires after "set_conditions". It doesn't allow the handler


to change anything, but it does provide the context object so that the
modules can react in whatever way they want.

-- Event name: "get_ball_name"


Handler function: f(ctx, ballname)
Return value expected: nil or string

This event fires, when the game prepares to display the ball name.
Your handler function can change it, if it returns a string instead of nil.
The string needs to be in UTF-8 encoding to correctly render non-ASCII
characters.

-- Event name: "get_stadium_name"


Handler function: f(ctx, stadium_name, stadium_id)
Return value expected: nil or string

This event fires, when the game prepares to display the stadium name.
You handler function can change it, if it returns a string instead of nil.
(The "stadium_id" parameter is provided to handler function only as additional
information - for which stadium the name is being read/modified)
The string needs to be in UTF-8 encoding to correctly render non-ASCII
characters.

-- Event name: "trophy_rewrite"


Handler function: f(ctx, tournament_id)
Return value expected: nil or number

This event fires before the game checks if trophy scenes need to be shown
before (and after) the match. This is a specialized event, and is probably
not very useful for modules other than "[Link]". The "[Link]"
uses to enforce trophy scenes from specific tournaments. This makes it
possible to have trophy celebrations for tournaments that do not have
them in the original game content. (See [Link], if you are really
interested in how this works)

-- Event name: "overlay_on"


Handler function: f(ctx)
Return values expected: string, string, table

All return values can be nil, and also the handler may return three or two,
or one, or not return anything at all.
1st return value: text to display
2nd return value: full filename of the image to display
3rd return value: table with layout options

When the overlay is on, and the current Lua module is in control of the
overlay, this event fires once for each frame that is displayed by the game engine
(So, normally - 60 times per second). The returned string is what will be
displayed by the overlay. The logic that generates this string should not be
too heavy: too much processing may affect the frame rate.
See examples in modules: [Link] and [Link]

The text and image are displayed side by side: text - on the left,
image - on the right. The layout options table allows to specify some
formatting for the image. The following ones are supported:

"image_width" : sets the width of the image on screen


- values > 1 will be interpreted as desired width in pixels
- values < 1 will be interpreted as fraction of the total
screen width.
"image_height": sets the height of the image on screen
- values > 1 will be interpreted as desired height in pixels
- values < 1 will be interpreted as fraction of the total
screen height.
"image_aspect_ratio": a floating point number (width/height).
This options allows to enforce aspect ratio that is
different from the source image. This value is NOT
used if both image_width and image_height are specified.
"image_hmargin": whitespace margin in pixels to be placed to the left and to
the right of the image.
"image_vmargin": whitespace margin in pixels to be placed to the top and to
the bottom of the image.

Final dimensions of the image on screen are calculated using two of the three
options: "image_width", "image_height", "image_aspect_ratio" - in this order
of priority. If only 1 (or none of the three) are specified, then a default
width of 0.1 of total screen width is assumed, and the original aspect ratio
of the image is used to calculate the height.

Transparency of overlay images can be controlled by "[Link]-alpha-max"


settings in [Link]. This setting affects all modules and cannot be changed
at runtime. See [Link] for details on how this settings works.

-- Event name: "key_down"


Handler function: f(ctx, vkey)
Return value expected: nil

When the overlay is on, and the current Lua module is in control of the
overlay, this event fires when user presses down any key on the keyboard. The
so-called "virtual key code" will be passed as the value of "vkey" parameter.
Your function can that take appropriate action, if it wants to react to
such key events. A combination of "overlay_on" and "key_down" events can
be used to build simple UIs in the overlay itself.
See example of such UI in [Link]

-- Event name: "gamepad_input"


Handler function: f(ctx, inputs)
Return value expected: nil

When the overlay is on, and the current Lua module is in control of the
overlay, this event fires when user presses or releases a button, or moves
a stick or d-pad of the game controller. (If you have multiple controllers
attached, only one will generate these input events). The "inputs" parameter
is always a table containing at least one, but possibly more than one mapping
of: input-name --> input-value. The "input-name" is a symbolic name that
identifies the source of input: a button, stick, d-pad. See the following
table for all possible combinations:

input | input-name | input-values


--------------------+--------------+-----------------
Button 0 | A | 0,1
Button 1 | B | 0,1
Button 2 | X | 0,1
Button 3 | Y | 0,1
Button 4 | LB | 0,1
Button 5 | RB | 0,1
Button 6 | START | 0,1
Button 7 | BACK | 0,1
Button 8 | LT | 0,1
Button 9 | RT | 0,1
Button 10 (LS push) | LS | 0,1
Button 11 (RS push) | RS | 0,1
LS (left/right) | LSx | -1,0,1
LS (up/down) | LSy | -1,0,1
RS (left/right) | RSx | -1,0,1
RS (up/down) | RSy | -1,0,1
D-pad | DPAD | 0,1,9,8,10,2,6,4,5

For buttons, 0: pressed, 1: pressed.


For sticks, horizontal: -1: left, 0:middle, 1:right
vertical: -1: down, 0:middle, 1:up
For D-pad, 0: not pressed, 1:up, 2:down, 4:left, 8:right
5:up/left, 6:down/left, 10:down/right, 9:up/right

Best way to verify what names correspond to what buttons on your


controller, is to try the "[Link]" from the modules folder.
It uses overlay to display the last 20 input events - both from
keyboard and from gamepad.

If your module is registered for "key_down" event, but not for the
"gamepad_input" event, then sider will automatically map gamepad events
into keyboard events, and emit those, for such gamepad events that are
defined in the "global input mapping" configuration - in [Link].

If you do not want this automatic mapping, make sure to register for
the "gamepad_input" event in your module, and then do whatever is needed
with the inputs. (You may choose to completely ignore them too, if you
want. See example of that in [Link])

IMPORTANT NOTE: Some events can fire multiple times for the same "action".
That is normal, it's just how the game works internally. Make sure your
module logic can handle such situations correctly.

5. Logging
~~~~~~~~~~

Sider provides a function called "log". This can be used to print


out any information you want into the [Link] file.
You can use [Link] to format your message in a way similar
to what you would do with C printf:

log([Link]("My value is: %0.5f", [Link]))

In [Link] it will appear with a module name prefix, like as:

[<modulename>.lua] My value is: 3.14159

6. Module environment
~~~~~~~~~~~~~~~~~~~~~

Each module runs in its own environment. For detailed explanation


on what an environment is - read about Lua environments in the Lua
manual online, or in Programming in Lua book. What is important
here is that a module has access to a limited set of globals:

Standard Lua:
assert, ipairs, pairs, tostring, tonumber, table,
string, math, unpack, type, error, io, os, _VERSION, _G
Sider:
log, memory, _FILE

You can also enable "ffi" and "bit" modules, which are LuaJIT
extensions. By default, they are disabled. To enable, modify your
[Link] like this:

[Link] = 1

By the way, your module can "investigate" and find out what exactly
is available for it to use - this is not hard, and is left as an
exercise for the reader ;-) Or... you can cheat, and look at [Link]
module.

7. Memory library
~~~~~~~~~~~~~~~~~

The "memory" library provides a set of low-level functions that


may prove useful if you're doing some advanced modding.
For example, you need some game state info that is not available in
sider's context object and isn't communicated through events either.
Or you want to modify some bytes in memory, because you feel really
adventurous.

**********************************************************************
**********************************************************************
IMPORTANT WARNING: PLEASE USE THIS LIBRARY WITH CARE AND CAUTION,
AND IF AND ONLY IF YOU KNOW WHAT YOU'RE DOING. REALLY.

THESE ARE POWERFUL TOOLS, BUT THERE ARE ALSO DANGEROUS, BECAUSE
WRITING INTO A WRONG PLACE IN MEMORY CAN HAVE DISASTROUS CONSEQUENCES.
ALWAYS TRY TO HAVE A BACKUP COPY OF YOUR EDIT DATA AND SAVEGAME FILES.
**********************************************************************
**********************************************************************

[Link](addr, n)

This function reads (n) bytes at memory address (addr).


Return value: string of n bytes at given memory address

[Link](addr, str)

This function writes the string of bytes (str) at the address (addr).
Return value: nil

[Link](str, start_addr, end_addr)

This function searches for the string of bytes (str), in the range
of memory addresses between start_addr and end_addr.
Return value: address, at which the string of bytes was found
or nil, if the string was not found.

[Link](format, number)

This function converts a Lua number into one of the supported binary
formats (little endian). The "format" parameter is a string that should
have one of the following values:
"f" : 32-bit float,
"d" : 64-bit double-precision float,
"i64" : 64-bit signed integer,
"u64" : 64-bit unsigned integer,
"i32" : 32-bit signed integer,
"u32" : 32-bit unsigned integer,
"i16" : 16-bit signed integer,
"u16" : 16-bit unsigned integer
Return value: string of bytes, representing the number in the format
specified by the "format" parameter

[Link](format, str)

This function converts a string of bytes (str) into a Lua number, using
the format parameter to interpret the binary spec. The same values are
supported for "format" param as in [Link] function.
Return value: a Lua number, converted from binary representation

These last two functions ([Link]/[Link]) are useful, when


used together with [Link] and [Link], when you need to read
and modify values in RAM and you know what binary formats are used for
those values. See modules/[Link] - as the example module that
demonstrates the usage.

[Link](value)

Utility function to output value in hexadecimal format.


Depending on the type of value, the output differs slightly:

local s = 'Football'
log([Link](s)) --> prints "466f6f7462616c6c" in the log

local n = 12345
log([Link](n)) --> prints "0x3039" in the log

memory.get_process_info()

This function queries the game process ([Link]) for information


about where it is loaded in memory.
Return value: a table containing at least two keys:
"base" - base address of the main process in memory
"sections" - a table of tables, with each member table containing
at least these keys:
"name" - name of the section
"start" - starting address in memory
"finish" - first address beyond this section

memory.search_process(s)

This function searches for a string s in memory, but unlike [Link]


function, it does not take start and finish addresses. Instead, it searches
the game process sections, one at a time, until it finds the string, or
until all sections are examined.
Returns 2 values:
1) address of string s in memory, if found, or nil - otherwise
2) table with section info, in which the string was found.

8. Zlib library
~~~~~~~~~~~~~~~

This library contains a small set of utility functons to work with


compressed data. An example usage could be a combination of using a
"livecpk_read" event to get the data, as it is read by the game, and
then unpacking it, if it is compressed ("zlibbed").

[Link](data)
Takes the string of data and compresses it.
Returns 2 values:
1) string with compressed data, or nil - if an error occured
2) nil, or string with error message, if something went wrong

[Link](compressed_data, uncompressed_size)

Decompresses the give string of data. The second parameter is


optional: if you know the size of uncompressed data, then it is more
efficient to provide it. If not, then uncompress will try a big
enough buffer (3-times the size of compressed data)
Returns 2 values:
1) string with uncompressed data, or nil - if an error occured
2) nil, or string with error message, if something went wrong

[Link](data)

Creates a data structure that consists of "WESYS" header, used by


Konami in PES games, followed by raw compressed data. The size of
the WESYS header is 16 bytes, and its format is as follows:
bytes 0-2: magic bytes (version): 00 01 01
bytes 3-7: "WESYS"
bytes 8-11: compressed_size
bytes 12-15: uncompressed size
Returns 2 values:
1) string containing the data structure, or nil - if an error occured
2) nil, or string with error message, if something went wrong

[Link](data)

Checks if the input is in Konami format of WESYS header, followed


by the compressed data. If so, it will try to uncompress the data,
using the size information from the header. If the data is not in
the expected format, then it is returned as is - unmodified.
Returns 2 values:
1) string containing uncompressed bytes, or original data,
if the input is not in WESYS-format, or nil, if some
error occured
2) nil, or string with error message, if an error occured.

Common questions

Powered by AI

The "set_conditions" event handles match settings like time of day, weather, and season, which can be modified through a returned table of options, halting further event propagation if any changes occur . Conversely, "set_stadium" focuses on changing the stadium alone, wherein a stadium id can be returned to update the setting . This separation of concern allows for targeted modifications without overlap in responsibilities.

The "memory" library provides low-level functions for reading and writing bytes in memory, enabling advanced modding by allowing modifications to game state or data inaccessible via standard APIs . Functions like memory.read and memory.write are crucial for direct interaction with RAM, while memory.pack and memory.unpack facilitate conversion between Lua numbers and binary data. Potential uses include changing game dynamics or fixing in-game bugs, but caution is advised due to the risk of catastrophic memory errors .

The context object defines the time of day using two values: 0 for Day and 1 for Night. Similarly, weather conditions are coded as 0 for Fine, 1 for Rainy, and 2 for Snowy, with optional weather effects indicated by the value 2 to enforce rain or snow falling . These settings allow modders to simulate realistic match environments by altering in-game visuals and dynamics through Lua scripting.

The "overlay_on" event can be harnessed creatively to overlay text, images, and layout options onto the game interface, allowing for enhanced storytelling or dynamic UI modifications . By manipulating return values, a modder could introduce narrative elements, provide gameplay hints, or create interactive features that are only present under specific gameplay conditions, thus enriching the player's experience with personalized content.

The "get_ball_name" event allows customization of ball names by enabling a handler to return a new UTF-8 encoded string instead of nil, thereby altering what is displayed in the game . This provides a way for modders to personalize in-game elements, enhancing aesthetic and thematic consistency. Handlers must ensure strings are properly encoded to support non-ASCII characters, which is crucial for internationalization and customization.

A Lua module environment restricts access to a limited set of global functions, providing standard Lua functionalities like assert, ipairs, and tostring . It also includes Sider-specific functions like log and memory, enabling logging and memory manipulation. The choice to enable LuaJIT extensions further expands capabilities, allowing for advanced bit manipulation or FFI use. These constraints and extensions create a controlled yet flexible scripting environment conducive for game modding.

Developers should use "memory.write" with extreme caution, as writing to incorrect memory locations can lead to disastrous consequences, including data corruption or game crashes . It is recommended to have backup copies of edit data and savegame files and ensure thorough testing in controlled environments to prevent unintended side effects. Awareness of memory allocation and proper address calculation is also critical to avoid unexpected behaviors.

The "livecpk_make_key" handler is expected to return a string key used for caching, and since it can fire multiple times for a given filename, performance considerations are crucial. It is important to avoid expensive computations or logging in this handler to prevent negative impacts on frame rates, ensuring that the game runs smoothly . Efficient design here minimizes computational overhead and maintains high performance during gameplay.

A developer might use the "zlib" library to compress large datasets, such as graphics or custom gameplay data, reducing storage requirements and potentially improving load times . Benefits include efficient use of resources, quicker data transmission, and reduced latency when reading data in-game. This compression is also essential when dealing with file size limitations or requiring fast asset swaps during gameplay.

The "trophy_rewrite" event allows Lua scripts to enforce trophy scenes for specific tournaments within the game, providing the capability to introduce celebrations even for tournaments lacking them initially . Used primarily by the "trophy.lua" module, this event is significant for enhancing player experience by personalizing and enriching post-match commemorations.

You might also like