1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-11-10 13:09:43 +01:00
Commit graph

53 commits

Author SHA1 Message Date
Misa
c278f05397 Remove duplicate function musicclass::stopmusic()
It is an exact duplicate of musicclass::haltdasmusik(), so use that
function instead and update callers. Looks like
musicclass::haltdasmusik() came first, anyway (musicclass::stopmusic()
was only used in editor.cpp).
2020-04-03 19:19:45 -04:00
Misa
7b1388f85c Fix undefined behavior when backspacing in script list with 0 scripts
The problem is that it would index out-of-bounds if you did this, but
this UB hasn't caused an exception until my change to refactor
script-related vectors by removing their separate length-trackers.
2020-04-03 16:57:52 -04:00
Misa
04d14000ec Remove global 'temp' variable from titlerender.cpp
Just a miscellaneous code cleanup.

There's no glitches that take advantage of the previous situation,
namely that 'temp' was a global variable in Logic.cpp and editor.cpp.
Even if there were, it seems like it would easily lead to some undefined
behavior. So it's good to clean this up.
2020-04-03 10:40:50 -04:00
Misa
92544cbdbb Remove outdated comments from editor.cpp
A lot of these seem to be based on an earlier version of the C++ port,
but they left some Flash stuff (like the buffer lock/unlocking) in, too.
2020-04-03 10:40:50 -04:00
Misa
ff449a2c3a Remove game.test and game.teststring
It looks like this may have been used earlier in development, judging
from the name, obviously, but right now it seems like it's used as an
error message if a main game level is asked for an invalid room (well,
only two of them - the Lab and Warp Zone). It should probably be
formalized into an error system, if we want to keep teststring, and also
people would never see it anyway because I don't think there's a
reliable and consistent way to trigger loading a non-existent room.

I have seen someone manage to load a non-existent Warp Zone room only
one time, but even then this teststring didn't pop up. So this
teststring doesn't even trigger in the right circumstances.

Also, when it does pop up, as far as I can tell it will stay onscreen,
which is kinda annoying. So I'm just removing this ancient relic from
the code.
2020-04-03 10:40:50 -04:00
Misa
1310896191 Remove semi-useless function editorclass::weirdloadthing()
Looks like this function was created because editorclass::load() takes
in a string by reference, not by value, and thus mutates it afterwards,
so if you passed a string in when you didn't want it to be mutated, bad
things would happen.

However, a better workaround for the above issue would simply to
duplicate the string and pass that string instead, thus the original
string wouldn't be affected.
2020-04-03 10:40:50 -04:00
Misa
6c6b6c68ff Change all UtilityClass::something to help.something
This changes something like UtilityClass::String to help.String,
basically. It takes less typing this way, and is a neat effect of having
global args actually be global variables.
2020-04-03 10:40:50 -04:00
Misa
16c3966ace Remove unused argument from musicclass::playef()
Apparently the 'offset' argument did something in the 1.x Flash
versions, but now it does nothing.
2020-04-03 10:40:50 -04:00
Misa
6a28c5de30 Remove unused arguments from Graphics::drawtile2()
The 'r', 'g', and 'b' arguments do absolutely nothing. Except unlike
Graphics::drawtile(), there's only one version of Graphics::drawtile2(),
so just remove those args and update callers.
2020-04-03 10:40:50 -04:00
Misa
5c60b8df5f Remove unused arguments from Graphics::drawtile()
The 'r', 'g', and 'b' arguments do absolutely nothing, even though
they're used in the version of Graphics::drawtile() that's more used. So
delete the other version without those extra arguments, and then remove
the extra arguments from the remaining version. And then update callers.
2020-04-03 10:40:50 -04:00
Misa
9bc45c586e Remove global args from editorclass
This removes global arg passing from all functions on editorclass.
Callers have been updated correspondingly. Additionally, all 'dwgfx' has
been replaced with 'graphics' in editor.cpp.
2020-04-03 10:40:50 -04:00
Misa
ea3c778b84 Remove global args from scriptclass
This commit removes all global args from the parameters of each function
on the scriptclass object, and updates all places they are called
accordingly. It also changes all instances of 'dwgfx' to 'graphics' in
Script.cpp.

Interestingly enough, it looks like editor.h depended on Script.h's
class define of the musicclass. I've temporarily placed the class define
in editor.h, but by the end of this patchset it'll be gone.
2020-04-03 10:40:50 -04:00
Misa
2826bd828c Remove global args from Graphics
This removes global args from all functions on the Graphics class.
Callers of those functions in other files have been updated accordingly.

Of course, since Graphics.cpp is already in the Graphics namespace,
I do not need to change all 'dwgfx' to 'graphics' in Graphics.cpp.
2020-04-03 10:40:50 -04:00
Misa
1be398319c 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-03-24 20:20:53 -04:00
Misa
5a25cad74b Don't draw text outline for roomtext in the editor
Text outline is not drawn on roomtext when you're actually playing the
game, so don't draw the outline in the editor, either.

FIQ mistakenly added text outline to roomtext in
ca9f577fc4.
2020-03-04 15:50:52 -05:00
Misa
b82a8a0925 Fix undefined behavior with left-click logic in editor
There's an if-else chain that first deals with figuring out if there's
an entity where your left-click happened, and to do this it uses
edentat(), which returns a sentinel value of -1 if there is NOT an
entity where your cursor is.

It's very important to check that the value returned ISN'T -1 before you
start indexing the 'edentity' vector, since if you DO index it with that
-1, it'll result in Undefined Behavior because you're doing an
out-of-bounds array access.

Now, here's what the if-else chain looked like before:

    if(tmp==-1 && ed.free(ed.tilex,ed.tiley)==0)
    {
        ...
    }
    else if(edentity[tmp].t==1)

The bug here is very subtle but it was an easy oversight. Basically, if
'ed.free' ended up not being zero, control flow would jump to the next
"else if" over, which then ends up asking for the -1th index of
'edentity', which is Undefined Behavior.

This undefined behavior has now resulted in a crash on my system after
TerryCavanagh/VVVVVV#172, due it shuffling things around juuuuust enough
such that this UB would end up resulting in a segfault instead of
chugging along and working fine. For me and my system, this meant that
if my first left-click in the editor upon opening the game was me
placing down a tile and not placing down an entity, the game would
crash. But, it would be fine if I first placed down an entity and then
afterwards placed down tiles, because it's UB.

And I'm almost certain this was the cause of the very strange bug where
you couldn't hold down left-click for the foreground-placing tool (but
you COULD for the background-placing tool) that seemed to occur most
often on Windows (TerryCavanagh/VVVVVV#25).

The solution to this is to stick in another conditional in the tree
before any indexing occurs, such that there's no way any other
conditionals with the indexing in the conditional tree could end up
being hit. In summary, the if-else chain looks like this now:

    if(tmp==-1 && ed.free(ed.tilex,ed.tiley)==0)
    {
        ...
    }
    else if(tmp == -1)
    {
        //Important! Do nothing, or else Undefined Behavior will happen
    }
    else if(edentity[tmp].t==1)
2020-03-02 08:22:08 -05:00
Misa
8d44d9387b Refactor edentities to not use separate length-trackers
This turns the array 'edentity' into a proper vector, and removes the need to
use a separate length-tracking variable and manually keep track of the actual
amount of edentities in the level by using the long-winded
'EditorData::GetInstance().numedentities'. This manual tracking was more
error-prone and much less maintainable.

editorclass::naddedentity() has been removed due to now functionally being the
same as editorclass::addedentity() (there's no more
'EditorData::GetInstance().numedentities' to not increment) and for also being
unused in the first place.

editorclass::copyedentity() has been removed because it was only used to shift
the rest of the edentities up manually, but now that we let C++ do all the
hard work it's no longer necessary.
2020-03-01 15:47:01 -05:00
Misa
f7e71bd668 Fix left-clicking on script boxes
You can now left-click on script boxes in order to change their script.
2020-02-21 18:15:26 -05:00
Misa
e18dd195ba Fix typo: "quiting" (one T) to "quitting" (two Ts) 2020-02-17 13:17:36 -05:00
Matt Penny
e7252888b6 Support pre-C++11 compilers 2020-02-11 06:02:35 -05:00
Misa
9b125ad8df Prevent removing line if there is only one line
This fixes another way you could end up typing on a non-existent line in
the script editor.

In a script with only 1 line, which is empty, the game would let you
press backspace on it, removing the line. This results in you typing on
a non-existent line.

You will keep typing on it until you either close the script or press
Up. If you press Up, you will be unable to get back to the non-existent
line, for it doesn't exist - but the text you typed on the non-existent
line will still be there, until you close the script and re-open it.
2020-02-10 22:57:00 -05:00
Terry Cavanagh
172ab9195d
Merge pull request #158 from AllyTally/entertoreturn
Make "[Press ENTER to return to editor]" fade out after a bit
2020-02-10 18:41:13 +01:00
Matt Penny
1b00d12600 Add option to allow custom levels when the editor is disabled 2020-02-09 23:31:44 -05:00
Matt Penny
7d35c5ce4e Add option to compile without the level editor 2020-02-09 23:31:44 -05:00
AllyTally
6b1a7ebce6 Make "[Press ENTER to return to editor]" fade out after a bit
This makes the "[Press ENTER to return to editor]" fade out after a few frames, allowing screenshots of custom levels to be cleaner and to make sure nothing is obscured while the user is editing their level.
This commit also adds alpha support in BlitSurfaceColoured, where it takes into account the alpha of the pixel *and* the alpha of the color.
`graphics::getRGBA(r,g,b,a)` was added to help with this.
2020-02-09 22:31:33 -04:00
AllyTally
ca0bfcfa80 Fix undefined behavior while loading scripts
In `editor.cpp`, there's a few sections of code that try and index stuff using `string.length()-1`.
This causes issues where if the string is empty, the result is -1, causing undefined behavior.
Flibit fixed a few of these cases, like on line `375` of editor.cpp:
`if((int) tstring.length() - 1 >= 0) // FIXME: This is sketchy. -flibit`
It turns out that one of these weren't caught, over at line `471`.
`tstring=tstring[tstring.length()-1];`
This causes builds compiled on Windows to segfault if you load more than one level in the editor.
I added a quick `if` around it, setting `tstring` to an empty string, which seems to fix the problem.
2020-02-07 23:30:49 -05:00
leo60228
6a17625727
Add support for Unicode rendering (#47)
This uses utfcpp combined with a custom font, in the form of a PNG and text file. By default, the game acts exactly as it did before; custom fonts can be provided by third parties.
2020-01-31 13:25:37 -05:00
Info Teddy
4be6d58b82 Reset warp directions when exiting playtesting
This fixes a bug where if warpdir() was used during in-editor
playtesting, the changed warp direction would persist even when leaving
playtesting.

This would be very annoying to correct back every time you playtested
and warpdir() was used, so I've added some kludge to store the actual
warp direction of each room when entering playtesting, and then set the
warp directions back when leaving playtesting.
2020-01-30 22:15:45 -05:00
Fredrik Ljungdahl
3cfa7b0c60 Fix and improve handling of cancelling roomtext/scripttext input
First, two bug fixes. Room text input mode wasn't properly unset
upon pressing Esc, making the prompt get stuck, requiring you to
add roomtext again and finish it to make it go away. Secondly,
escaping script text input would remove the wrong entity.

I also tweaked the handling slightly so that instead of deleting
the entity if it already existed if escaping from text input,
it merely reverts the change in script name/roomtext to what it
was previously.

I considered refactoring the editor text input handler entirely,
but figured such a change would be a bit too extensive for the
purpose of this repository.
2020-01-27 11:15:25 +01:00
Fredrik Ljungdahl
757fd49283 Draw editor entities according to ingame order
Ingame entities are drawn backwards, probably to draw the player on top,
being entity 0 (usually, at least). Make the level editor draw entities
in the same order.
2020-01-26 22:22:10 -05:00
Info Teddy
b79f0daa5f Move y-position assignment into its most intended branch
This is a code style fix.
2020-01-25 23:29:37 -05:00
Info Teddy
2709de9cf0 Make fast path using FillRect() when opaque
FillRect() is similar enough to memset when blending isn't used, so the
game will take a fast path drawing the roomname background when the
background is opaque.
2020-01-25 23:29:37 -05:00
Info Teddy
2f85c2a8dc Draw room names with text outline
This makes it easier to see if you have a translucent room name
background.
2020-01-25 23:29:37 -05:00
Info Teddy
df83c2d494 Add an accessibility option to be able to see through the roomname
This is the variable dwgfx.translucentroomname and <translucentroomname>
in unlock.vvv.

This lets you see through the black background of the roomname at the
bottom of the screen, i.e. it makes the roomname background translucent.
So you can see if someone decides to hide pesky spikes there.
2020-01-25 23:29:37 -05:00
Info Teddy
c49ae404af Convert roomname background to a surface, then draw that
The roomname background used to just be a simple SDL_Rect that was drawn
using SDL_FillRect with a color of 0. Unfortunately, it seems that you
cannot use transparent colors with SDL_FillRect, it just defaults to
being fully opaque. However, you CAN draw surfaces with translucency,
which seems like the easiest thing to do. But the first step is to
convert the roomname background to an SDL_Surface.

This replaces the FillRect()s with SDL_BlitSurface() in the three places
roomnames are drawn: in towerrender, in gamerender, and in editorrender.
2020-01-25 23:29:37 -05:00
Info Teddy
f6fa8dd84c De-duplicate the roomname printing code in the editor
For some reason, there are two lines that have been copy-pasted the
exact same way and in the exact same place, namely being at the end of
each branch of the if-else conditional, which makes them be executed no
matter what. If they're going to be executed no matter what, we might as
well make it clearer and take those two lines out of each branch.
2020-01-25 23:29:37 -05:00
Fredrik Ljungdahl
2ec1106741 Fix level editor not using LoadTiXmlDocument 2020-01-24 16:45:18 -05:00
Dav999-v
3dee27db7b Remove superfluous whitespace in entity XML data in level files (#119)
An earlier change caused TinyXml to prettyprint specifically the
contents of entities (script names and roomtext) a bit more than
before in level files, and added an unusually high amount of whitespace
(particularly, it added an empty line to every entity). This happens
because, for some reason, an empty string is explicitly being added
when creating an entity XML element. The line is so mysterious it feels
like it probably somehow solved a nasty bug long ago and shouldn't be
touched, but it was probably just a mistake, and with all that
whitespace it doesn't look good.
2020-01-24 14:25:21 -05:00
Info Teddy
cd7cc317b5 Up the trinkets/crewmates limit to 100
2.2 will handle this just fine, because there are 100 slots allocated
for trinkets and crewmates, and it will save and load all 100 slots just
fine. Except, it only resets the first 20 slots when starting a level
from the beginning, but that's minor and already fixed in 2.3 anyway.

This commit makes it so you can now place up to one hundred trinkets and
crewmates in the editor.
2020-01-23 10:00:26 -05:00
Terry Cavanagh
782ce95d11
Merge pull request #115 from FredrIQ/master
Make the level editor use font outlines
2020-01-23 14:59:53 +01:00
Fredrik Ljungdahl
76792e652a Don't outline entity directions (looks odd and can never be hard to see) 2020-01-23 14:53:35 +01:00
Info Teddy
e8fd134a43 Fix X and Y coordinates getting reversed in editorclass::reset()
When editorclass::reset() was resetting the contents of the level
previously, it was mixing up the X and Y bounds. The Y bound was
supposed to be 30*maxheight, and the X bound was supposed to be
40*maxwidth. Instead, it took 30*maxwidth as its Y bound and
40*maxheight as its X bound.

Then, when it actually indexes the contents vector to set each tile to
0, it used 30*maxwidth instead of 40*maxwidth.

The difference between width and height is a bit hard to spot, but one
thing you can do to remember the difference is to remember the fact that
X corresponds with width, and Y corresponds with height. Also, rooms are
40 by 30 tiles, and so X (and therefore width) should correspond with
40, and Y (and therefore height) should correspond with 30.

As a result of mixing up the variables, whenever you played a 20x20 map,
quit the level and then started making a new 20x20 map, the tiles of the
last four rows of the previous map would persist, from y=16 (1-indexed)
all the way to y=20 (1-indexed).

I don't recall anyone ever running into this bug before, which is a bit
strange. But if no one truly has ever ran into this bug before, then I'm
genuinely surprised.

While working on the patch to fix the enemy type room property of each
room not getting reset, and testing the fix, I noticed that for some
reason some contents of the previous level I played in order to test the
enemy type property persisting was ALSO persisting alongside the enemy
type property.

Then I read the code and when I realized that the X and Y bounds were
getting mixed up I groaned. Very loudly.
2020-01-23 08:42:35 -05:00
Info Teddy
8e9970d619 Reset enemy type in editorclass::reset()
This fixes a bug where if you loaded a level, then started making a new
level in the editor, the enemy types from the previous level would
persist.

While working on VVVVVV: Community Edition and adding a new room
property for enemy speed, I noticed that enemy type was not getting
reset at all. After some testing, I confirmed that this was the case. So
this bug is fixed now.
2020-01-23 08:39:55 -05:00
Fredrik Ljungdahl
ca9f577fc4 Make the level editor use font outlines for text appropriately 2020-01-23 14:23:56 +01:00
Info Teddy
31efc9b3ce Fix out-of-bounds array access in findstartpoint()
Out-of-bounds array access is Undefined Behavior, which means Bad
Things.

In this particular case, it was indexing an array by using the
`testeditor` variable. Which is fine, except it was indexing that array
*in a conditional that only happens if `testeditor` is -1*. So it was
indexing an array at position -1, which is Out of Bounds and is Not
Good.
2020-01-22 07:46:46 -05:00
Info Teddy
2c2acc93e6 Reset Direct Mode in editorclass::reset()
There's a long-standing issue where the Direct Mode status of the loaded
custom map in memory never resets properly. So if you load a level with
a certain layout of Direct Mode rooms, that same layout will be
preserved if you start making a new level in the editor. This commit
fixes that issue.
2020-01-19 21:46:52 -08:00
Info Teddy
916f182ce6 Set ed.keydelay when backspacing an empty line
Similar to 2ebccbc3e9, there's also a
long-standing bug where if you backspace an empty line (and this time,
the line IS actually already empty, not merely
emptied-earlier-in-the-frame), the game will quickly delete more blank
lines if there are any above the blank line you deleted. Again, this is
annoying too, if you so happen to need to use lots of blank lines.

To fix this, it's simple - just set ed.keydelay to 6 when the game
backspaces an empty line. Then it won't be so trigger-happy in deleting
blank lines.
2020-01-19 08:37:14 -05:00
Info Teddy
2687090ac2 Fix frame-ordering backspacing empty line bug in script editor
There is a long-standing bug with the script editor where if you delete
the last character of a line, it IMMEDIATELY deletes the line you're on,
and then moves your cursor back to the previous line. This is annoying,
to say the least.

The reason for this is that, in the sequence of events that happens in
one frame (known as frame ordering), the code that backspaces one
character from the line when you press Backspace is ran BEFORE the code
to remove an empty line if you backspace it is ran. The former is
located in key.Poll(), and the latter is located in editorinput().

Thus, when you press Backspace, the game first runs key.Poll(), sees
that you've pressed Backspace, and dutifully removes the last character
from a line. The line is now empty. Then, when the game gets around to
the "Are you pressing Backspace on an empty line?" check in
editorinput(), it thinks that you're pressing Backspace on an empty
line, and then does the usual line-removing stuff.

And actually, when it does the check in editorinput(), it ACTUALLY asks
"Are you pressing Backspace on THIS frame and was the line empty LAST
frame?" because it's checking against its own copy of the input buffer,
before copying the input buffer to its own local copy. So the problem
only happens if you press and hold Backspace for more than 1 frame.
It's a small consolation prize for this annoyance, getting to
tap-tap-tap Backspace in the hopes that you only press it for 1 frame,
while in the middle of something more important to do like, oh I don't
know, writing a script.

So there are two potential solutions here:

 (1) Just change the frame ordering around.

     This is risky to say the least, because I'm not sure what behavior
     depends on exactly which frame order. It's not like it's key.Poll()
     and then IMMEDIATELY afterwards editorinput() is run, it's more
     like key.Poll(), some things that obviously depend on key.Poll()
     running before them, and THEN editorinput(). Also, editorinput() is
     only one possible thing that could be ran afterwards, on the next
     frame we could be running something else entirely instead.

 (2) Add a kludge variable to signal when the line is ALREADY empty so
     the game doesn't re-check the already-empty line and conclude that
     you're already immediately backspacing an empty line.

I went with (2) for this commit, and I've added the kludge variable
key.linealreadyemptykludge.

However, that by itself isn't enough to fix it. It only adds about a
frame or so of delay before the game goes right back to saying "Oh,
you're ALREADY somehow pressing backspace again? I'll just delete this
line real quick" and the behavior is basically the same as before,
except now you have to hit Backspace for TWO frames or less instead of
one in order to not have it happen.

What we need is to have a delay set as well, when the game deletes the
last line of a char. So I set ed.keydelay to 6 as well if editorinput()
sses that key.linealreadyemptykludge is on.
2020-01-19 08:37:14 -05:00
Info Teddy
b1d6b7f395 Fix off-by-one in script editor letting you type on a nonexistent line
For a long time, the script editor has had a bug where it would let you
put the cursor on a nonexistent script line, which would APPEAR to be
the last line of the script... but in reality, it WASN'T the last line
of the script, and in fact, the ACTUAL last line was the line ABOVE the
script.

So, if you typed anything on this nonexistent line, it would appear to
get erased when exiting the script. Thus, people have (erroneously)
misdiagnosed this as the script editor somehow being trigger-happy and
erasing lines when it shouldn't be, when in reality it should've have
let you gone onto that line in the first place!
2020-01-19 00:33:20 -05:00
Info Teddy
3247d3be41 Correct capitalization of song names
This corrects things like "Passion for exploring" and "Passion For
Exploring" to be "Passion for Exploring".
2020-01-15 22:05:37 -08:00