2020-01-01 21:29:24 +01:00
|
|
|
#ifndef SCRIPT_H
|
|
|
|
#define SCRIPT_H
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "Enums.h"
|
|
|
|
|
2020-05-18 19:37:00 +02:00
|
|
|
#define filllines(lines) commands.insert(commands.end(), lines, lines + sizeof(lines)/sizeof(lines[0]))
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
|
Refactor custom scripts to not be stored in one giant vector of lines
This commit refactors custom level scripts to no longer be stored in one
giant vector containing not only every single script name, but every
single script's contents as well. More specifically,
scriptclass::customscript has been converted to an std::vector<Script>
scriptclass::customscripts (note the extra S), and a Script is just a
struct with an std::string name and std::vector<std::string> contents.
This is an improvement in both performance and maintainability. The game
no longer has to look through script contents in case they're actually
script names, and then manually extract the script contents from there.
Instead, all it has to do is look for script names only. And the
contents are provided for free. This results in a performance gain.
Also, the old system resulted in lots of boilerplate everywhere anytime
scripts had to be handled or parsed. Now, the boilerplate is only done
when saving or loading a custom level. This makes code quality much,
much better.
To be sure I didn't actually change anything, I tested by first saving
Dimension Open in current 2.3 (because current 2.3 gets rid of the
awful edentity whitespace), and then resaved it on this patch. There is
absolutely no difference between the current-2.3-resave and
this-patch-resave.
2020-06-12 02:31:57 +02:00
|
|
|
struct Script
|
|
|
|
{
|
|
|
|
std::string name;
|
|
|
|
std::vector<std::string> contents;
|
|
|
|
};
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
class scriptclass
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
|
|
scriptclass();
|
|
|
|
|
2020-07-05 00:59:21 +02:00
|
|
|
void load(std::string name);
|
|
|
|
void loadother(const char* t);
|
|
|
|
void loadcustom(std::string t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
void inline add(std::string t)
|
|
|
|
{
|
Make `commands`, `sb`, and `hooklist` not use separate length-trackers
This is a refactor that turns the script-related arrays `ed.sb`, and
`ed.hooklist` into C++ vectors (`script.commands` was already a vector, it was
just misused). The code handling these vectors now looks more like idiomatic
C++ than sloppily-pasted pseudo-ActionScript. This removes the variables
`script.scriptlength`, `ed.sblength`, and `ed.numhooks`, too.
This reduces the amount of code needed to e.g. simply remove something from
any of these vectors. Previously the code had to manually shift the rest of
the elements down one-by-one, and doing it manually is definitely error-prone
and tedious.
But now we can just use fancy functions like `std::vector::erase()` and
`std::remove()` to do it all in one line!
Don't worry, I checked and `std::remove()` is in the C++ standard since at least
1998.
This patch makes it so the `commands` vector gets cleared when
`scriptclass::load()` is ran. Previously, the `commands` vector never actually
properly got cleared, so there could potentially be glitches that rely on the
game indexing past the bounds set by `scriptlength` but still in-bounds in the
eyes of C++, and people could potentially rely on such an exploit...
However, I checked, and I'm pretty sure that no such glitch previously existed
at all, because the only times the vector gets indexed are when `scriptlength`
is either being incremented after starting from 0 (`add()`) or when it's
underneath a `position < scriptlength` conditional.
Furthermore, I'm unaware of anyone who has actually found or used such an
exploit, and I've been in the custom level community for 6 years.
So I think it's fine.
2020-02-20 18:43:52 +01:00
|
|
|
commands.push_back(t);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void clearcustom();
|
|
|
|
|
|
|
|
void tokenize(std::string t);
|
|
|
|
|
2020-03-31 21:38:52 +02:00
|
|
|
void run();
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 21:38:52 +02:00
|
|
|
void resetgametomenu();
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 21:38:52 +02:00
|
|
|
void startgamemode(int t);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 21:38:52 +02:00
|
|
|
void teleport();
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-03-31 21:38:52 +02:00
|
|
|
void hardreset();
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
//Script contents
|
|
|
|
std::vector<std::string> commands;
|
2020-07-03 01:07:35 +02:00
|
|
|
std::string words[40];
|
2020-01-01 21:29:24 +01:00
|
|
|
std::vector<std::string> txt;
|
|
|
|
std::string scriptname;
|
Make `commands`, `sb`, and `hooklist` not use separate length-trackers
This is a refactor that turns the script-related arrays `ed.sb`, and
`ed.hooklist` into C++ vectors (`script.commands` was already a vector, it was
just misused). The code handling these vectors now looks more like idiomatic
C++ than sloppily-pasted pseudo-ActionScript. This removes the variables
`script.scriptlength`, `ed.sblength`, and `ed.numhooks`, too.
This reduces the amount of code needed to e.g. simply remove something from
any of these vectors. Previously the code had to manually shift the rest of
the elements down one-by-one, and doing it manually is definitely error-prone
and tedious.
But now we can just use fancy functions like `std::vector::erase()` and
`std::remove()` to do it all in one line!
Don't worry, I checked and `std::remove()` is in the C++ standard since at least
1998.
This patch makes it so the `commands` vector gets cleared when
`scriptclass::load()` is ran. Previously, the `commands` vector never actually
properly got cleared, so there could potentially be glitches that rely on the
game indexing past the bounds set by `scriptlength` but still in-bounds in the
eyes of C++, and people could potentially rely on such an exploit...
However, I checked, and I'm pretty sure that no such glitch previously existed
at all, because the only times the vector gets indexed are when `scriptlength`
is either being incremented after starting from 0 (`add()`) or when it's
underneath a `position < scriptlength` conditional.
Furthermore, I'm unaware of anyone who has actually found or used such an
exploit, and I've been in the custom level community for 6 years.
So I think it's fine.
2020-02-20 18:43:52 +01:00
|
|
|
int position;
|
2020-01-01 21:29:24 +01:00
|
|
|
int looppoint, loopcount;
|
|
|
|
|
|
|
|
int scriptdelay;
|
Fix the two-frame-delay when entering a room with an "init" script
This patch is very kludge-y, but at least it fixes a semi-noticeable
visual issue in custom levels that use internal scripts to spawn
entities when loading a room.
Basically, the problem here is that when the game checks for script
boxes and sets newscript, newscript has already been processed for that
frame, and when the game does load a script, script.run() has already
been processed for that frame.
That issue can be fixed, but it turns out that due to my over-30-FPS
game loop changes, there's now ANOTHER visible frame of delay between
room load and entity creation, because the render function gets called
in between the script being loaded at the end of gamelogic() and the
script actually getting run.
So... I have to temporary move script.run() to the end of gamelogic()
(in map.twoframedelayfix()), and make sure it doesn't get run next
frame, because double-evaluations are bad. To do that, I have to
introduce the kludge variable script.dontrunnextframe, which does
exactly as it says.
And with all that work, the two-frame (now three-frame) delay is fixed.
2020-06-28 02:08:57 +02:00
|
|
|
bool running, dontrunnextframe;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
//Textbox stuff
|
|
|
|
int textx;
|
|
|
|
int texty;
|
|
|
|
int r,g,b;
|
|
|
|
|
|
|
|
//Misc
|
|
|
|
int i, j, k;
|
|
|
|
|
|
|
|
//Custom level stuff
|
Refactor custom scripts to not be stored in one giant vector of lines
This commit refactors custom level scripts to no longer be stored in one
giant vector containing not only every single script name, but every
single script's contents as well. More specifically,
scriptclass::customscript has been converted to an std::vector<Script>
scriptclass::customscripts (note the extra S), and a Script is just a
struct with an std::string name and std::vector<std::string> contents.
This is an improvement in both performance and maintainability. The game
no longer has to look through script contents in case they're actually
script names, and then manually extract the script contents from there.
Instead, all it has to do is look for script names only. And the
contents are provided for free. This results in a performance gain.
Also, the old system resulted in lots of boilerplate everywhere anytime
scripts had to be handled or parsed. Now, the boilerplate is only done
when saving or loading a custom level. This makes code quality much,
much better.
To be sure I didn't actually change anything, I tested by first saving
Dimension Open in current 2.3 (because current 2.3 gets rid of the
awful edentity whitespace), and then resaved it on this patch. There is
absolutely no difference between the current-2.3-resave and
this-patch-resave.
2020-06-12 02:31:57 +02:00
|
|
|
std::vector<Script> customscripts;
|
2020-01-01 21:29:24 +01:00
|
|
|
};
|
|
|
|
|
2020-05-18 19:12:11 +02:00
|
|
|
extern scriptclass script;
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
#endif /* SCRIPT_H */
|