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

68 commits

Author SHA1 Message Date
Misa
c177f456f4 Unexport getgridpoint
It's a method of entityclass even though it doesn't use anything on the
class and it's not used outside of Entity.cpp.
2022-12-11 12:40:45 -08:00
Misa
7347975cc5 Unexport yline
It's a method of entityclass, even though it doesn't use anything on the
class and it's not used outside of Entity.cpp.
2022-12-11 12:37:55 -08:00
Misa
52e29b68bc Unexport gridmatch
It's a method of entityclass, but it has no reason to be because it
doesn't use anything on entityclass and it's not used outside of
Entity.cpp.
2022-12-11 12:37:43 -08:00
Misa
ec520838df Retype testwallsy's tx and ty to be ints, not floats
I have no idea why they were floats in the first place. They are
coordinates, and coordinates are integer positions in this game. They
get converted to float only to be explicitly `static_cast`ed back to
ints in `testwallsy`.
2022-12-11 11:00:20 -08:00
Misa
12820473db Retype dr to be int instead of float
This variable passes along the rule of the entity, which is an int. No
idea why it was converted to a float. Thankfully this is only used for
an unused block type, so it doesn't really matter.
2022-12-11 10:55:25 -08:00
Misa
babcadc99f Remove unnecessary consts from Entity.h
`const`s don't mean anything in a prototype declaration unless it's a
pointer or a reference. Remove them to make the header a bit more
readable.
2022-12-11 10:52:12 -08:00
Misa
f0aa1a8cae Don't treat spikes as solid for non-humanoid entities
There's always been a bit of an inconsistency in the game where enabling
invincibility would make spikes so solid that enemies and moving
platforms would treat spikes as solid and bounces off of them.

This fixes that by adding an `invincible` parameter to collision
functions, so the functions will only treat spikes as solid if that
parameter is true, and the parameter passed will only be true if it's
called for an entity that is a humanoid and invincibility mode is
enabled.

Also, for clarity, `spikecollide` is renamed to `towerspikecollide`
because it's only used for tower spikes. And as a small optimization,
`checktowerspikes` returns early if invincibility mode is enabled.
2022-06-05 20:21:51 -07:00
Ally
f3786a8e3f
Add setactivityposition(x,y), add new textbox color transparent (#847)
* Add `setactivityposition(x,y)`, add new textbox color `transparent`

This commit adds a new internal command as a part of the visual activity zone changes I've been making.
This one allows the user to reposition the activity zone to anywhere on the screen.
In addition, this commit adds the textbox color `transparent`, which just sets r, g and b to 0.
rgb(0, 0, 0) normally creates the color black, however in VVVVVV textboxes, it makes the background
of them invisible, and makes the text the off-white color which the game uses elsewhere.

* add new variables to hardreset

* Fix unwanted text centering; offset position by 16, 4

It makes sense for `setactivityposition(0, 0)` to place the activity zone in the default position,
so the x has been offset by 16, and the y has been offset by 4.

Text was being automatically centered, meaning any activity zone which wasn't centered had misplaced text.
This has been fixed by calculating the center manually, and offsetting it by the passed value.
2021-10-13 15:38:51 -07:00
Ally
64be7dbd53
Refactor colors in internal commands
Originally this started as a "deduplicate a bunch of duplicated code in script commands" PR,
but as I was working on that, I discovered there's a lot more that needs to be done than
just deduplication.
Anything which needs a crewmate entity now calls `getcrewmanfromname(name)`, and anything which
just needs the crewmate's color calls `getcolorfromname(name)`. This was done to make sure that
everything works consistently and no copy/pasting is required. Next is the fallback; instead of
giving up and doing various things when it can't find a specific color, it now attempts to treat
the color name as an ID, and if it can't then it returns -1, where each individual command handles
that return value. This means we can keep around AEM -- a bug used in custom levels -- by not
doing anything with the return value if it's -1.

Also, for some reason, there were two `crewcolour` functions, so I stripped out the one in
entityclass and left (and modified) the one in the graphics class, since the graphics class also
has the `crewcolourreal` function.
2021-08-31 15:09:51 -07:00
AllyTally
b15e25f106 Add setactivitycolour(colour) and setactivitytext() commands
These commands will change the colour and text of the next
activity zone that gets spawned. `setactivitycolour` takes all
textbox colors, and `setactivitytext` will take the text on
the next line. These commands were designed this way
to avoid breaking forwards compatibility.
2021-08-31 11:17:00 -07:00
AllyTally
0685cade69 Change the text of custom activity zones
When an activity zone is spawned through the
use of `createactivityzone`, and `i` is 35,
then it'll change the activity zone text to
"Press ENTER to interact".
2021-08-31 11:17:00 -07:00
Misa
75ed9f9631 Move linecrosskludge off of entityclass
This is a temporary vector that only gets used in mapclass::gotoroom().
It's always guaranteed to be cleared, so it's safe to move it off.

I'm fine with using references here because, like, it's a C++ STL vector
anyway - when we switch away from the STL (which is a precondition for
moving to C), we'll be passing around raw pointers here instead, and
won't be using references here anyway.
2021-08-31 09:25:47 -07:00
Misa
3ca7b09012 Fix regression: quick stopping changing drawframe
This fixes a regression that desyncs my Nova TAS after re-removing the
1-frame input delay.

Quick stopping is simply holding left/right but for less than 5 frames.
Viridian doesn't decelerate when you let go and they immediately stop in
place. (The code calls this tapping, but "quick stopping" is a better
name because you can immediately counter-strafe to stop yourself from
decelrating in the first place, and that works because of this same
code.)

So, the sequence of events in 2.2 and previous looks like this:

- gameinput()
  - If quick stopping, set vx to 0
- gamerender()
  - Change drawframe depending on vx
- gamelogic()
  - Use drawframe for collision (whyyyyyyyyyyyyyyyyyyyyyyyyyyy)

And now (ignoring the intermediate period where the whole loop order was
wrong), the sequence of events in 2.3 looks like this:

- gamerenderfixed()
  - Change drawframe depending on vx
- gamerender()
- gameinput()
  - If quick stopping, set vx to 0
- gamelogic()
  - Use drawframe for collision (my mind has become numb to pain)

So, this means that all the player movement stuff is completely the
same. Except their drawframe is going to be different.

Unfortunately, I had overlooked that gameinput() sets vx and that
animateentities() (in gamerenderfixed()) checks vx. Although, to be
fair, it's a pretty dumb decision to make collision detection be based
on the actual sprites' pixels themselves, instead of a hitbox, in the
first place, so you'd expect THAT to be the end of the dumb parade. Or
maybe you shouldn't, I don't know.

So, what's the solution?

What I've done here is added duplicates of framedelay, drawframe, and
walkingframe, for collision use only. They get updated in gamelogic(),
after gameinput(), which is after when vx could be set to 0.

I've kept the original framedelay, drawframe, and walkingframe around,
to keep the same visuals as closely as possible.

However, due to the removal of the input delay, whenever you quick stop,
your sprite will be wrong for just 1 frame - because when you let go of
the direction key, the game will set your vx to 0 and the logical
drawframe will update to reflect that, but the previous frame cannot
know in advance that you'll release the key on the next frame, and so
the visual drawframe will assume that you keep holding the key.

Whereas in 2.2 and below, when you release a direction key, the player's
position will only update to reflect that on the next frame, but the
current frame can immediately recognize that and update the drawframe
now, instead of retconning it later.

Basically the visual drawframe assumes that you keep holding the key,
and if you don't, then it takes on the value of the collision drawframe
anyway, so it's okay. And it's only visual, anyway - the collision
drawframe of the next frame (when you release the key) will be the same
as the drawframe of the frame you release the key in 2.2 and below.

But I really don't care to try and fix this for if you re-enable the
input delay because it's minor and it'd be more complicated.
2021-07-28 20:11:16 -04:00
Misa
c84d7ebf08 Rename vx/vy createentity args to meta1/meta2
vx/vy mean x-velocity and y-velocity... except here, where it seems like
they're used as extra parameters that do different things depending on
the entity. But it seems like at one point they were actually meant to
be the speed of the entity (this is the case for the unused decorative
particle entities), and then just never got renamed when they weren't.

The custom levels community named these two parameters meta1 and meta2
in the reference list of entities for the createentity() script command,
so that's what I'm naming them here. This will avoid confusion (I know
that some people reading this function have genuinely mistaken the vx/vy
for actually meaning x-velocity and y-velocity, simply because they were
named that way).
2021-04-17 18:29:17 -04:00
Misa
9ba30caeb3 Remove default function args from createentity()
I have spelled out each overloaded version instead, and only the
overloads that are actually used - which just happens to be everything
except the 8-argument one. I don't want to deal with callers right now
(there are too many of them), so I'm not going to change the names that
the callers use, nor do I want to change the amount of arguments any
existing callers use right now - but we will have to deal with them in
one way or another when we move to C.
2021-04-17 18:29:17 -04:00
Misa
7d223db211 Change all createentity args to be ints
The script command createentity() is always an int. But not only that,
every time createentity() is used, its arguments are always treated like
ints. Always. I knew that vx/vy were floats because of the int casts in
the function, but I didn't even realize that xp/yp were floats, too,
until I checked just now! That's how much they're treated like ints.

All int casts in createentity() have also been removed, due to being
unnecessary (either because of us suppressing MSVC implicit conversion
warnings, or because there are now no longer any conversions happening).
2021-04-17 18:29:17 -04:00
Misa
6a3a1fe147
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.

This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.

I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 17:23:59 -05:00
Misa
3927bb9713 Fix entity and block indices after destroying them
This patch restores some 2.2 behavior, fixing a regression caused by the
refactor of properly using std::vectors.

In 2.2, the game allocated 200 items in obj.entities, but used a system
where each entity had an `active` attribute to signify if the entity
actually existed or not. When dealing with entities, you would have to
check this `active` flag, or else you'd be dealing with an entity that
didn't actually exist. (By the way, what I'm saying applies to blocks
and obj.blocks as well, except for some small differing details like the
game allocating 500 block slots versus obj.entities's 200.)

As a consequence, the game had to use a separate tracking variable,
obj.nentity, because obj.entities.size() would just report 200, instead
of the actual amount of entities. Needless to say, having to check for
`active` and use `obj.nentity` is a bit error-prone, and it's messier
than simply using the std::vector the way it was intended. Also, this
resulted in a hard limit of 200 entities, which custom level makers ran
into surprisingly quite often.

2.3 comes along, and removes the whole system. Now, std::vectors are
properly being used, and obj.entities.size() reports the actual number
of entities in the vector; you no longer have to check for `active` when
dealing with entities of any sort.

But there was one previous behavior of 2.2 that this system kind of
forgets about - namely, the ability to have holes in between entities.
You see, when an entity got disabled in 2.2 (which just meant turning
its `active` off), the indices of all other entities stayed the same;
the indice of the entity that got disabled stays there as a hole in the
array. But when an entity gets removed in 2.3 (previous to this patch),
the indices of every entity afterwards in the array get shifted down by
one. std::vector isn't really meant to be able to contain holes.

Do the indices of entities and blocks matter? Yes; they determine the
order in which entities and blocks get evaluated (the highest indice
gets evaluated first), and I had to fix some block evaluation order
stuff in previous PRs.

And in the case of entities, they matter hugely when using the
recently-discovered Arbitrary Entity Manipulation glitch (where crewmate
script commands are used on arbitrary entities by setting the `i`
attribute of `scriptclass` and passing invalid crewmate identifiers to
the commands). If you use Arbitrary Entity Manipulation after destroying
some entities, there is a chance that your script won't work between 2.2
and 2.3.

The indices also still determine the rendering order of entities
(highest indice gets drawn first, which means lowest indice gets drawn
in front of other entities). As an example: let's say we have the player
at 0, a gravity line at 1, and a checkpoint at 2; then we destroy the
gravity line and create a crewmate (let's do Violet).

If we're able to have holes, then after removing the gravity line, none
of the other indices shift. Then Violet will be created at indice 1, and
will be drawn in front of the checkpoint.

But if we can't have holes, then removing the gravity line results in
the indice of the checkpoint shifting down to indice 1. Then Violet is
created at indice 2, and gets drawn behind the checkpoint! This is a
clear illustration of changing the behavior that existed in 2.2.

However, I also don't want to go back to the `active` system of having
to check an attribute before operating on an entity. So... what do we
do to restore the holes?

Well, we don't need to have an `active` attribute, or modify any
existing code that operates on entities. Instead, we can just set the
attributes of the entities so that they naturally get ignored by
everything that comes into contact with it. For entities, we set their
invis to true, and their size, type, and rule to -1 (the game never uses
a size, type, or rule of -1 anywhere); for blocks, we set their type to
-1, and their width and height to 0.

obj.entities.size() will no longer necessarily equal the amount of
entities in the room; rather, it will be the amount of entity SLOTS that
have been allocated. But nothing that uses obj.entities.size() needs to
actually know the amount of entities; it's mostly used for iterating
over every entity in the vector.

Excess entity slots get cleaned up upon every call of
mapclass::gotoroom(), which will now deallocate entity slots starting
from the end until it hits a player, at which point it will switch to
disabling entity slots instead of removing them entirely.

The entclass::clear() and blockclass::clear() functions have been
restored because we need to call their initialization functions when
reusing a block/entity slot; it's possible to create an entity with an
invalid type number (it creates a glitchy Viridian), and without calling
the initialization function again, it would simply not create anything.

After this patch is applied, entity and block indices will be restored
to how they behaved in 2.2.
2021-02-16 19:31:23 -05:00
Misa
ad34e95128 Remove unused function entityclass::fixfriction()
This function was marked as unused by cppcheck.
2021-01-02 09:06:42 -05:00
Misa
e8084fe699 Remove now-unused entityclass::hormovingplatformfix()
This function is no longer used after I removed it in favor of using
`entityclass::moveblockto()`.
2020-10-11 16:18:30 -04:00
Misa
c83132f4fa Add entityclass::moveblockto()
This function will restore a block's hitbox after it has been disabled
by `entityclass::nocollisionat()`.
2020-10-11 16:18:30 -04:00
Misa
d8cee4866e Add entityclass::nocollisionat()
This function will disable a block instead of removing it entirely,
mimicking the previous `active` system of 2.2.
2020-10-11 16:18:30 -04:00
Misa
cbceeccf78 Clean up and prevent unnecessary qualifiers to self
By "unnecessary qualifiers to self", I mean something like using the
'game.' qualifier for a variable on the Game class when you're inside a
function on the Game class itself. This patch is to enforce consistency
as most of the code doesn't have these unnecessary qualifiers.

To prevent further unnecessary qualifiers to self, I made it so the
extern in each header file can be omitted by using a define. That way,
if someone writes something referring to 'game.' on a Game function,
there will be a compile error.

However, if you really need to have a reference to the global name, and
you're within the same .cpp file as the implementation of that object,
you can just do the extern at the function-level. A good example of this
is editorinput()/editorrender()/editorlogic() in editor.cpp. In my
opinion, they should probably be split off into their own separate file
because editor.cpp is getting way too big, but this will do for now.
2020-09-28 01:34:40 -04:00
Misa
571ad1f7d8 Move all temporary variables off of entityclass
This is a refactor that simply moves all temporary variables off of
entityclass, and makes it so they are no longer global variables. This
makes the resulting code easier to understand as it is less entangled
with global state.

These attributes were:
 - colpoint1
 - colpoint2
 - tempx
 - tempy
 - tempw
 - temph
 - temp
 - temp2
 - tpx1
 - tpy1
 - tpx2
 - tpy2
 - temprect
 - temprect2
 - x (actually unused)
 - dx
 - dy
 - dr
 - px
 - py
 - linetemp
 - activetrigger
 - skipblocks
 - skipdirblocks

Most of these attributes were assigned before any of the times they were
used, so it's easy to prove that ungloballing them won't change any
behaviors. However, dx, dy, dr, and skipblocks are a bit more tricky to
analyze. They relate to blocks, with dx, dy, and dr more specifically
relating to one-way tiles. So after some testing with the quirks of
one-way tiles, it seems that the jankiness of one-way tiles haven't
changed at all, either.

Unfortunately, the attribute k is clearly used without being assigned
beforehand, so I can't move it off of entityclass. It's the same story
with the attribute k that Graphics has, too.
2020-09-27 19:08:37 -04:00
Misa
fae14f4e98 De-duplicate stuck prevention for the player/SCM
Stuck prevention (pushing the player/supercrewmate out if they are
inside a wall) has been factored out into its own function, so it's no
longer copy-pasted but slightly tweaked just for the supercrewmate.
2020-09-25 13:37:38 -04:00
Misa
b5806c8bb0 De-duplicate entity collision checks for player/SCM
The entity collision check routine has been factored out into its own
function, so it no longer needs to be copy-pasted for the supercrewmate.
2020-09-25 13:37:38 -04:00
Misa
ceaee392e5 De-duplicate vertical moving platform fix for player/SCM
Instead of having two separate functions to move entities along vertical
moving platforms, one for the player and one for the supercrewmate, they
have been consolidated into one function.
2020-09-25 13:37:38 -04:00
Misa
1c5b72410a De-duplicate spike hitbox checks for player/SCM
The spike hitbox check is now one function for both the player and the
supercrewmate, instead of being two separate functions.
2020-09-25 13:37:38 -04:00
Misa
52f7a587fe Separate includes into sections and alphabetize them
Okay, so basically here's the include layout that this game now
consistently uses:

[The "main" header file, if any (e.g. Graphics.h for Graphics.cpp)]
[blank line]
[All system includes, such as tinyxml2/physfs/utfcpp/SDL]
[blank line]
[All project includes, such as Game.h/Entity.h/etc.]

And if applicable, another blank line, and then some special-case
include screwy stuff (take a look at editor.cpp or FileSystemUtils.cpp,
for example, they have ifdefs and defines with their includes).
2020-07-19 21:37:40 -04:00
Misa
b5ff65c84e Remove unnecessary includes from header files
Including a header file inside another header file means a bunch of
files are going to be unnecessarily recompiled whenever that inner
header file is changed. So I minimized the amount of header files
included in a header file, and only included the ones that were
necessary (system includes don't count, I'm only talking about includes
from within this project). Then the includes are only in the .cpp files
themselves.

This also minimizes problems such as a NO_CUSTOM_LEVELS build failing
because some file depended on an include that got included in editor.h,
which is another benefit of removing unnecessary includes from header
files.
2020-07-19 21:37:40 -04:00
Misa
2506127a17 Directly execute scripts if script boxes have a non-empty script field
Instead of using gamestates, just directly use the 'script' attribute of
a script box if it is non-empty.

This is accomplished by having to return the index of the block that the
player collides with, so callers can inspect the 'script' attribute of
the block themselves, and do their logic accordingly.
2020-07-15 11:24:25 -04:00
Misa
8c42f82317 Set script attribute of custom level script boxes
To avoid going through gamestates, we'll need to carry the name of the
script on the script box itself. And to do that, we'll need to set the
'script' attribute of script boxes when translating edentities into real
entities in custom levels.
2020-07-15 11:24:25 -04:00
Misa
0664eac7fc Turn obj.collect and obj.customcollect into plain arrays
Since they're always fixed-size, there's no need for them to be vectors.

Also added an INBOUNDS_ARR() macro to do bounds checks with plain
arrays.
2020-07-06 11:19:24 -04:00
Misa
62203efb2c Turn obj.flags into an array instead of a vector
Since it's always fixed-size, there's no reason for it to be a vector.
2020-07-06 11:19:24 -04:00
Misa
1258eb7bf4 Turn crew rescued/mood vectors into arrays
Since they're always fixed-size, they don't need to be dynamically-sized
vectors.

entityclass::customcrewmoods is now a proper bool instead of an int now,
and I replaced the hardcoded constant 6 with a static const int Game
attribute to make it easier to change.
2020-07-06 11:19:24 -04:00
Misa
dcc9520d8f Interpolate trophy text
Just to make sure it's extra smooth. Not that it will be noticeable, and
you can't access the Secret Lab in slowmode without modifying the game,
but it's nice to have this.
2020-06-19 09:05:48 -04:00
Misa
4f50883d58 Prevent removing the player entity
Removing the player entity has all sorts of nasty effects, such as
softlocking the game because many inputs require there to be a player
present, such as opening the quit menu.

The most infamous glitch to remove the player entity is the Gravitron
Fling, where the game doesn't see a gravity line at a specific
y-position in the current room, and when it moves the bottom gravity
line it moves the player instead. When the gravity line gets outside the
room, it gets destroyed, so if the player gets dragged outside the room,
they get destroyed, too. (Don't misinterpret this as saying anytime the
player gets dragged outside the room, they get destroyed - it's only the
Gravitron logic that destroys them.)

Also, there are many places in the code that use entity-getting
functions that have a fallback value of 0. If it was possible to remove
the player, then it's possible for this fallback value of 0 to index
obj.entities out-of-bounds, which is not good.

To fix this, entityclass::removeentity() is now a bool that signifies if
the entity was successfully removed or not. If the entity given is the
player (meaning it first checks if it's rule 0, just so in 99% of cases
it'll short-circuit and won't do the next check, which is if
entityclass::getplayer() says the indice to be removed is the player),
then it'll refuse to remove the entity, and return false.

This is a change in behavior where callers might expect
entityclass::removeentity() to always succeed, so I changed the
removeentity_iter() macro to only decrement if removing the entity
succeeded. I also changed entityclass::updateentities() from
'removeentity(i); return true;' to 'return removeentity(i);'.
2020-06-13 15:41:44 -04:00
Misa
ce1e212317 Prevent updating an entity if updateentities() removed it
Otherwise, this would result in the game updating an entity twice, which
isn't good. This is most noticeable in the Gravitron, where many
Gravitron squares are created and destroyed at a time, and it's
especially noticeable during the part near the end of the Gravitron
where the pattern is two Gravitron squares, one at the top and bottom,
and then two Gravitron squares in the middle afterwards. The timing is
just right such that the top one of the two middle ones would be
misaligned with the bottom one of the two when a Gravitron square gets
outside the screen.

To do this, I changed entityclass::updateentities() into a bool, and
made every single caller check its return value. I only needed to do
this for the ones preceding updateentitylogic() and
entitymapcollision(), but I wanted to play it safe and be defensive, so
I did it for the disappearing platform kludge, as well as the
updateentities() within the updateentities() function.
2020-05-05 17:22:47 -04:00
Misa
5fdbaa0076 Remove unused function entityclass::cblocks()
Just noticed this was unused, so I'm removing it.
2020-04-14 22:54:16 -04:00
Misa
17a64aee7a Make obj.customcollect a vector of bools
It's already treated as a vector of bools, so might as well formally
declare it as that.
2020-04-09 19:20:31 -04:00
Misa
8507bdc65d Change obj.collect into a vector of bools
It's already treated like a bunch of bools anyway, so might as well just
formalize it.
2020-04-09 19:20:31 -04:00
Misa
7493129044 Remove unused function entityclass::confirmflags()
Same as before, flags can never be the number 2, and never could be even
before I changed all flags to be bools. Also this function is unused.
2020-04-09 19:20:31 -04:00
Misa
ee5f8dce78 Remove unused function entityclass::resetflags()
This looks like a weird hack, but there's no way a flag will ever end up
being 2, not even before I changed all flags to be bools instead.
2020-04-09 19:20:31 -04:00
Misa
0648d6bb0f Remove unused function entityclass::changecustomcollect()
Looks like all accesses on obj.customcollect are done manually, so this
function is unused.
2020-04-09 19:20:31 -04:00
Misa
a6340f356e Remove unused function entityclass::changecollect()
Looks like all access on obj.collect are done manually, so this function
is unused.
2020-04-09 19:20:31 -04:00
Misa
c24e2abfad Remove now-unused function entityclass::changeflag()
It's now unused after I changed it so that every obj.flags access is
done directly, instead of going through this function.
2020-04-09 19:20:31 -04:00
Misa
abfae6b4d7 Declare obj.flags a vector of bools instead of ints
It's treated like a bool anyway, so might as well make it one.

This also necessitates updating every single instance where it or an
element inside it is used, too.
2020-04-09 19:20:31 -04:00
Misa
f10ac88c1a Refactor blocks to not use the 'active' system
This removes the variables obj.nblocks, as well as removing the 'active'
attribute from the block object. Now every block is guaranteed to be
real without having to check the 'active' variable.

Removing a block while iterating now uses the removeblock_iter() macro.
2020-04-03 23:28:47 -04:00
Misa
7689241d3a Add macro removeblock_iter()
When we switch blocks to not use 'active', we'll need this macro to
remove blocks while iterating through the vector, one at a time,
forwards.
2020-04-03 23:28:47 -04:00
Misa
7edbebac92 Move entityclass::setblockcolour() to blockclass::setblockcolour()
This moves the function setblockcolour(), so I can directly call it on a
particular block without having to have it be inside obj.blocks.
2020-04-03 23:28:47 -04:00