2020-01-01 21:29:24 +01:00
|
|
|
#include "Ent.h"
|
|
|
|
|
2020-07-19 21:05:41 +02:00
|
|
|
#include "Game.h"
|
|
|
|
#include "Graphics.h"
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
entclass::entclass()
|
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.
2020-12-27 07:11:34 +01:00
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void entclass::clear()
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
invis = false;
|
|
|
|
type = 0;
|
|
|
|
size = 0;
|
|
|
|
tile = 0;
|
|
|
|
rule = 0;
|
|
|
|
state = 0;
|
|
|
|
statedelay = 0;
|
|
|
|
life = 0;
|
|
|
|
colour = 0;
|
|
|
|
para = 0;
|
|
|
|
behave = 0;
|
|
|
|
animate = 0;
|
|
|
|
|
|
|
|
xp = 0;
|
|
|
|
yp = 0;
|
|
|
|
ax = 0;
|
|
|
|
ay = 0;
|
|
|
|
vx = 0;
|
|
|
|
vy = 0;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
cx = 0;
|
|
|
|
cy = 0;
|
|
|
|
newxp = 0;
|
|
|
|
newyp = 0;
|
2020-04-29 01:17:10 +02:00
|
|
|
oldxp = 0;
|
|
|
|
oldyp = 0;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
x1 = 0;
|
|
|
|
y1 = 0;
|
|
|
|
x2 = 320;
|
|
|
|
y2 = 240;
|
|
|
|
|
|
|
|
gravity = false;
|
|
|
|
onground = 0;
|
|
|
|
onroof = 0;
|
|
|
|
|
|
|
|
onentity = 0;
|
|
|
|
harmful = false;
|
|
|
|
onwall = 0;
|
|
|
|
onxwall = 0;
|
|
|
|
onywall = 0;
|
|
|
|
isplatform = false;
|
|
|
|
|
|
|
|
framedelay = 0;
|
|
|
|
drawframe = 0;
|
|
|
|
walkingframe = 0;
|
|
|
|
dir = 0;
|
|
|
|
actionframe = 0;
|
Fix, for in-GAMEMODE sprites, their colors updating too fast
Okay, so the problem here is that Graphics::setcol() is called right
before a sprite is drawn in a render function, but render functions are
done in deltatime, meaning that the color of a sprite keeps being
recalculated every time. This only affects sprites that use fRandom()
(the other thing that can dynamically determine a color is help.glow,
but that's only updated in the fixed-timestep loop), but is especially
noticeable for sprites that flash wildly, like the teleporter, trinket,
and elephant.
To fix this, we need to make the color be recalculated only in the
fixed-timestep loop. However, this means that we MUST store the color of
the sprite SOMEWHERE for the delta-timesteps to render it, otherwise the
color calculation will just be lost or something.
So each entity now has a new attribute, `realcol`, which is the actual
raw color used to render the sprite in render functions. This is not to
be confused with their `colour` attribute, which is more akin to a color
"ID" of sorts, but which isn't an actual color.
At the end of gamelogic(), as well as when an entity is first created,
the `colour` is given to Graphics::setcol() and then `realcol` gets set
to the actual color. Then when it comes time to render the entity,
`realcol` gets used instead.
Gravitron squares are a somewhat tricky case where there's technically
TWO colors for it - one is the actual sprite itself and the other is the
indicator. However, usually the indicator and the square aren't both
onscreen at the same time, so we can simply switch the realcol between
the two as needed.
However, we can't use this system for the sprite colors used on the
title and map screen, so we'll have to do something else for those.
2020-05-01 02:34:37 +02:00
|
|
|
|
|
|
|
realcol = 0;
|
Restore previous oldxp/oldyp variables in favor of lerpoldxp/lerpoldyp
I was investigating a desync in my Nova TAS, and it turns out that
the gravity line collision functions check for the `oldxp` and `oldyp`
of the player, i.e. their position on the previous frame, along with
their position on the current frame. So, if the player either collided
with the gravity line last frame or this frame, then the player collided
with the gravity line this frame.
Except, that's not actually true. It turns out that `oldxp` and `oldyp`
don't necessarily always correspond to the `xp` and `yp` of the player
on the previous frame. It turns out that your `oldyp` will be updated if
you stand on a vertically moving platform, before the gravity line
collision function gets ran. So, if you were colliding with a gravity
line on the previous frame, but you got moved out of there by a
vertically moving platform, then you just don't collide with the gravity
line at all.
However, this behavior changed in 2.3 after my over-30-FPS patch got
merged (#220). That patch took advantage of the existing `oldxp` and
`oldyp` entity attributes, and uses them to interpolate their positions
during rendering to make everything look real smooth.
Previously, `oldxp` and `oldyp` would both be updated in
`entityclass::updateentitylogic()`. However, I moved it in that patch to
update right before `gameinput()` in `main.cpp`.
As a result, `oldyp` no longer gets updated whenever the player stands
on a vertically moving platform. This ends up desyncing my TAS.
As expected, updating `oldyp` in `entityclass::movingplatformfix()` (the
function responsible for moving the player whenever they stand on a
vertically moving platform) makes it so that my TAS syncs, but the
visuals are glitchy when standing on a vertically moving platform. And
as much as I'd like to get rid of gravity lines checking for whether
you've collided with them on the previous frame, doing that desyncs my
TAS, too.
In the end, it seems like I should just leave `oldxp` and `oldyp` alone,
and switch to using dedicated variables that are never used in the
physics of the game. So I'm introducing `lerpoldxp` and `lerpoldyp`, and
replacing all instances of using `oldxp` and `oldyp` that my over-30-FPS
patch added, with `lerpoldxp` and `lerpoldyp` instead.
After doing this, and applying #503 as well, my Nova TAS syncs after
some minor but acceptable fixes with Viridian's walkingframe.
2020-10-10 05:58:58 +02:00
|
|
|
lerpoldxp = 0;
|
|
|
|
lerpoldyp = 0;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool entclass::outside()
|
|
|
|
{
|
|
|
|
// Returns true if any point of the entity is outside the map.
|
|
|
|
// Adjusts velocity for a clean collision.
|
|
|
|
if (xp < x1)
|
|
|
|
{
|
|
|
|
xp = x1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (yp < y1)
|
|
|
|
{
|
|
|
|
yp = y1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (xp + w > x2)
|
|
|
|
{
|
|
|
|
xp = x2 - w;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (yp + h > y2)
|
|
|
|
{
|
|
|
|
yp = y2 - h;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2020-04-03 21:29:57 +02:00
|
|
|
|
|
|
|
void entclass::setenemy( int t )
|
|
|
|
{
|
|
|
|
switch(t)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
//lies emitter
|
2020-04-29 01:20:59 +02:00
|
|
|
switch ((int) para)
|
2020-04-03 21:29:57 +02:00
|
|
|
{
|
2020-04-29 01:20:59 +02:00
|
|
|
case 0:
|
2020-04-03 21:29:57 +02:00
|
|
|
tile = 60;
|
|
|
|
animate = 2;
|
|
|
|
colour = 6;
|
|
|
|
behave = 10;
|
|
|
|
w = 32;
|
|
|
|
h = 32;
|
|
|
|
x1 = -200;
|
2020-04-29 01:20:59 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-03 21:29:57 +02:00
|
|
|
yp += 10;
|
2020-11-01 05:54:21 +01:00
|
|
|
lerpoldyp += 10;
|
2020-04-03 21:29:57 +02:00
|
|
|
tile = 63;
|
|
|
|
animate = 100; //LIES
|
|
|
|
colour = 6;
|
|
|
|
behave = 11;
|
|
|
|
para = 9; //destroyed when outside
|
|
|
|
x1 = -200;
|
|
|
|
x2 = 400;
|
|
|
|
w = 26;
|
|
|
|
h = 10;
|
|
|
|
cx = 1;
|
|
|
|
cy = 1;
|
2020-04-29 01:20:59 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-03 21:29:57 +02:00
|
|
|
tile = 62;
|
|
|
|
animate = 100;
|
|
|
|
colour = 6;
|
|
|
|
behave = -1;
|
|
|
|
w = 32;
|
|
|
|
h = 32;
|
2020-04-29 01:20:59 +02:00
|
|
|
break;
|
2020-04-03 21:29:57 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
//FACTORY emitter
|
2020-04-29 01:20:59 +02:00
|
|
|
switch ((int) para)
|
2020-04-03 21:29:57 +02:00
|
|
|
{
|
2020-04-29 01:20:59 +02:00
|
|
|
case 0:
|
2020-04-03 21:29:57 +02:00
|
|
|
tile = 72;
|
|
|
|
animate = 3;
|
|
|
|
size = 9;
|
|
|
|
colour = 6;
|
|
|
|
behave = 12;
|
|
|
|
w = 64;
|
|
|
|
h = 40;
|
|
|
|
cx = 0;
|
|
|
|
cy = 24;
|
2020-04-29 01:20:59 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-04-03 21:29:57 +02:00
|
|
|
xp += 4;
|
2020-11-01 05:54:21 +01:00
|
|
|
lerpoldxp += 4;
|
2020-04-03 21:29:57 +02:00
|
|
|
yp -= 4;
|
2020-11-01 05:54:21 +01:00
|
|
|
lerpoldyp -= 4;
|
2020-04-03 21:29:57 +02:00
|
|
|
tile = 76;
|
|
|
|
animate = 100; // Clouds
|
|
|
|
colour = 6;
|
|
|
|
behave = 13;
|
|
|
|
para = -6; //destroyed when outside
|
|
|
|
x2 = 400;
|
|
|
|
w = 32;
|
|
|
|
h = 12;
|
|
|
|
cx = 0;
|
|
|
|
cy = 6;
|
2020-04-29 01:20:59 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-04-03 21:29:57 +02:00
|
|
|
tile = 77;
|
|
|
|
animate = 100;
|
|
|
|
colour = 6;
|
|
|
|
behave = -1;
|
|
|
|
w = 32;
|
|
|
|
h = 16;
|
2020-04-29 01:20:59 +02:00
|
|
|
break;
|
2020-04-03 21:29:57 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-04-03 21:43:06 +02:00
|
|
|
|
|
|
|
void entclass::setenemyroom( int rx, int ry )
|
|
|
|
{
|
|
|
|
//Simple function to initilise simple enemies
|
|
|
|
rx -= 100;
|
|
|
|
ry -= 100;
|
|
|
|
switch(rn(rx, ry))
|
|
|
|
{
|
|
|
|
//Space Station 1
|
|
|
|
case rn(12, 3): //Security Drone
|
|
|
|
tile = 36;
|
|
|
|
colour = 8;
|
|
|
|
animate = 1;
|
|
|
|
break;
|
|
|
|
case rn(13, 3): //Wavelengths
|
|
|
|
tile = 32;
|
|
|
|
colour = 7;
|
|
|
|
animate = 1;
|
|
|
|
w = 32;
|
|
|
|
break;
|
|
|
|
case rn(15, 3): //Traffic
|
|
|
|
tile = 28;
|
|
|
|
colour = 6;
|
|
|
|
animate = 1;
|
|
|
|
w = 22;
|
|
|
|
h = 32;
|
|
|
|
break;
|
|
|
|
case rn(12, 5): //The Yes Men
|
|
|
|
tile = 40;
|
|
|
|
colour = 9;
|
|
|
|
animate = 1;
|
|
|
|
w = 20;
|
|
|
|
h = 20;
|
|
|
|
break;
|
|
|
|
case rn(13, 6): //Hunchbacked Guards
|
|
|
|
tile = 44;
|
|
|
|
colour = 8;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 20;
|
|
|
|
break;
|
|
|
|
case rn(13, 4): //Communication Station
|
|
|
|
harmful = false;
|
|
|
|
if (xp == 256)
|
|
|
|
{
|
|
|
|
//transmittor
|
|
|
|
tile = 104;
|
|
|
|
colour = 4;
|
|
|
|
animate = 7;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
xp -= 24;
|
2020-11-01 05:54:21 +01:00
|
|
|
lerpoldxp -= 24;
|
2020-04-03 21:43:06 +02:00
|
|
|
yp -= 16;
|
2020-11-01 05:54:21 +01:00
|
|
|
lerpoldyp -= 16;
|
2020-04-03 21:43:06 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//radar dish
|
|
|
|
tile =124;
|
|
|
|
colour = 4;
|
|
|
|
animate = 6;
|
|
|
|
w = 32;
|
|
|
|
h = 32;
|
|
|
|
cx = 4;
|
|
|
|
size = 9;
|
|
|
|
xp -= 4;
|
2020-11-01 05:54:21 +01:00
|
|
|
lerpoldxp -= 4;
|
2020-04-03 21:43:06 +02:00
|
|
|
yp -= 32;
|
2020-11-01 05:54:21 +01:00
|
|
|
lerpoldyp -= 32;
|
2020-04-03 21:43:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
//The Lab
|
|
|
|
case rn(4, 0):
|
|
|
|
tile = 78;
|
|
|
|
colour = 7;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(2, 0):
|
|
|
|
tile = 88;
|
|
|
|
colour = 11;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
//Space Station 2
|
|
|
|
case rn(14, 11):
|
|
|
|
colour = 17;
|
|
|
|
break; //Lies
|
|
|
|
case rn(16, 11):
|
|
|
|
colour = 8;
|
|
|
|
break; //Lies
|
|
|
|
case rn(13, 10):
|
|
|
|
colour = 11;
|
|
|
|
break; //Factory
|
|
|
|
case rn(13, 9):
|
|
|
|
colour = 9;
|
|
|
|
break; //Factory
|
|
|
|
case rn(13, 8):
|
|
|
|
colour = 8;
|
|
|
|
break; //Factory
|
|
|
|
case rn(11, 13): //Truth
|
|
|
|
tile = 64;
|
|
|
|
colour = 7;
|
|
|
|
animate = 100;
|
|
|
|
w = 44;
|
|
|
|
h = 10;
|
|
|
|
size = 10;
|
|
|
|
break;
|
|
|
|
case rn(17, 7): //Brass sent us under the top
|
|
|
|
tile =82;
|
|
|
|
colour = 8;
|
|
|
|
animate = 5;
|
|
|
|
w = 28;
|
|
|
|
h = 32;
|
|
|
|
cx = 4;
|
|
|
|
break;
|
|
|
|
case rn(10, 7): // (deception)
|
|
|
|
tile = 92;
|
|
|
|
colour = 6;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(14, 13): // (chose poorly)
|
|
|
|
tile = 56;
|
|
|
|
colour = 6;
|
|
|
|
animate = 1;
|
|
|
|
w = 15;
|
|
|
|
h = 24;
|
|
|
|
break;
|
|
|
|
case rn(13, 12): // (backsliders)
|
|
|
|
tile = 164;
|
|
|
|
colour = 7;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(14, 8): // (wheel of fortune room)
|
|
|
|
tile = 116;
|
|
|
|
colour = 12;
|
|
|
|
animate = 1;
|
|
|
|
w = 32;
|
|
|
|
h = 32;
|
|
|
|
break;
|
|
|
|
case rn(16, 9): // (seeing dollar signs)
|
|
|
|
tile = 68;
|
|
|
|
colour = 7;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(16, 7): // (tomb of mad carew)
|
|
|
|
tile = 106;
|
|
|
|
colour = 7;
|
|
|
|
animate = 2;
|
|
|
|
w = 24;
|
|
|
|
h = 25;
|
|
|
|
break;
|
|
|
|
//Warp Zone
|
|
|
|
case rn(15, 2): // (numbers)
|
|
|
|
tile = 100;
|
|
|
|
colour = 6;
|
|
|
|
animate = 1;
|
|
|
|
w = 32;
|
|
|
|
h = 14;
|
|
|
|
yp += 1;
|
2020-11-01 05:54:21 +01:00
|
|
|
lerpoldyp += 1;
|
2020-04-03 21:43:06 +02:00
|
|
|
break;
|
|
|
|
case rn(16, 2): // (Manequins)
|
|
|
|
tile = 52;
|
|
|
|
colour = 7;
|
|
|
|
animate = 5;
|
|
|
|
w = 16;
|
|
|
|
h = 25;
|
|
|
|
yp -= 4;
|
2020-11-01 05:54:21 +01:00
|
|
|
lerpoldyp -= 4;
|
2020-04-03 21:43:06 +02:00
|
|
|
break;
|
|
|
|
case rn(18, 0): // (Obey)
|
|
|
|
tile = 51;
|
|
|
|
colour = 11;
|
|
|
|
animate = 100;
|
|
|
|
w = 30;
|
|
|
|
h = 14;
|
|
|
|
break;
|
|
|
|
case rn(19, 1): // Ascending and Descending
|
|
|
|
tile = 48;
|
|
|
|
colour = 9;
|
|
|
|
animate = 5;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(19, 2): // Shockwave Rider
|
|
|
|
tile = 176;
|
|
|
|
colour = 6;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(18, 3): // Mind the gap
|
|
|
|
tile = 168;
|
|
|
|
colour = 7;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(17, 3): // Edge Games
|
|
|
|
if (yp ==96)
|
|
|
|
{
|
|
|
|
tile = 160;
|
|
|
|
colour = 8;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tile = 156;
|
|
|
|
colour = 8;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case rn(16, 0): // I love you
|
|
|
|
tile = 112;
|
|
|
|
colour = 8;
|
|
|
|
animate = 5;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(14, 2): // That's why I have to kill you
|
|
|
|
tile = 114;
|
|
|
|
colour = 6;
|
|
|
|
animate = 5;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(18, 2): // Thinking with Portals
|
|
|
|
//depends on direction
|
|
|
|
if (xp ==88)
|
|
|
|
{
|
|
|
|
tile = 54+12;
|
|
|
|
colour = 12;
|
|
|
|
animate = 100;
|
|
|
|
w = 60;
|
|
|
|
h = 16;
|
|
|
|
size = 10;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tile = 54;
|
|
|
|
colour = 12;
|
|
|
|
animate = 100;
|
|
|
|
w = 60;
|
|
|
|
h = 16;
|
|
|
|
size = 10;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
//Final level
|
|
|
|
case rn(50-100, 53-100): //The Yes Men
|
|
|
|
tile = 40;
|
|
|
|
colour = 9;
|
|
|
|
animate = 1;
|
|
|
|
w = 20;
|
|
|
|
h = 20;
|
|
|
|
break;
|
|
|
|
case rn(48-100, 51-100): //Wavelengths
|
|
|
|
tile = 32;
|
|
|
|
colour = 7;
|
|
|
|
animate = 1;
|
|
|
|
w = 32;
|
|
|
|
break;
|
|
|
|
case rn(43-100,52-100): // Ascending and Descending
|
|
|
|
tile = 48;
|
|
|
|
colour = 9;
|
|
|
|
animate = 5;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(46-100,51-100): //kids his age
|
|
|
|
tile = 88;
|
|
|
|
colour = 11;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(43-100,51-100): // Mind the gap
|
|
|
|
tile = 168;
|
|
|
|
colour = 7;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(44-100,51-100): // vertigo?
|
|
|
|
tile = 172;
|
|
|
|
colour = 7;
|
|
|
|
animate = 100;
|
|
|
|
w = 32;
|
|
|
|
h = 32;
|
|
|
|
break;
|
|
|
|
case rn(44-100,52-100): // (backsliders)
|
|
|
|
tile = 164;
|
|
|
|
colour = 7;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(43-100, 56-100): //Intermission 1
|
|
|
|
tile = 88;
|
|
|
|
colour = 21;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
case rn(45-100, 56-100): //Intermission 1
|
|
|
|
tile = 88;
|
|
|
|
colour = 21;
|
|
|
|
animate = 1;
|
|
|
|
w = 16;
|
|
|
|
h = 16;
|
|
|
|
break;
|
|
|
|
//The elephant
|
|
|
|
case rn(11, 9):
|
|
|
|
case rn(12, 9):
|
|
|
|
case rn(11, 8):
|
|
|
|
case rn(12, 8):
|
|
|
|
tile = 0;
|
|
|
|
colour = 102;
|
|
|
|
animate = 0;
|
|
|
|
w = 464;
|
|
|
|
h = 320;
|
|
|
|
size = 11;
|
|
|
|
harmful = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-04-03 21:47:38 +02:00
|
|
|
|
|
|
|
void entclass::settreadmillcolour( int rx, int ry )
|
|
|
|
{
|
|
|
|
rx -= 100;
|
|
|
|
ry -= 100;
|
|
|
|
rx += 50 - 12;
|
|
|
|
ry += 50 - 14; //Space Station
|
|
|
|
|
|
|
|
tile = 20; //default as blue
|
|
|
|
switch(rn(rx, ry))
|
|
|
|
{
|
|
|
|
case rn(52, 48):
|
|
|
|
tile = 791;
|
|
|
|
break; //Cyan
|
|
|
|
|
|
|
|
case rn(49, 47):
|
|
|
|
tile = 24;
|
|
|
|
break; //Yellow
|
|
|
|
case rn(56, 44):
|
|
|
|
tile = 24;
|
|
|
|
break; //Yellow
|
|
|
|
case rn(54, 49):
|
|
|
|
tile = 24;
|
|
|
|
break; //Yellow
|
|
|
|
|
|
|
|
case rn(49, 49):
|
|
|
|
tile = 36;
|
|
|
|
break; //Green
|
|
|
|
case rn(55, 44):
|
|
|
|
tile = 36;
|
|
|
|
break; //Green
|
|
|
|
case rn(54, 43):
|
|
|
|
tile = 36;
|
|
|
|
break; //Green
|
|
|
|
case rn(53, 49):
|
|
|
|
tile = 36;
|
|
|
|
break; //Green
|
|
|
|
case rn(54, 45):
|
|
|
|
tile = 711;
|
|
|
|
break; //Green (special)
|
|
|
|
case rn(51, 48):
|
|
|
|
tile = 711;
|
|
|
|
break; //Green (special)
|
|
|
|
|
|
|
|
case rn(50, 49):
|
|
|
|
tile = 28;
|
|
|
|
break; //Purple
|
|
|
|
case rn(54, 44):
|
|
|
|
tile = 28;
|
|
|
|
break; //Purple
|
|
|
|
case rn(49, 42):
|
|
|
|
tile = 28;
|
|
|
|
break; //Purple
|
|
|
|
case rn(55, 43):
|
|
|
|
tile = 28;
|
|
|
|
break; //Purple
|
|
|
|
case rn(54, 47):
|
|
|
|
tile = 28;
|
|
|
|
break; //Purple
|
|
|
|
case rn(53, 48):
|
|
|
|
tile = 28;
|
|
|
|
break; //Purple
|
|
|
|
|
|
|
|
case rn(51, 47):
|
|
|
|
tile = 32;
|
|
|
|
break; //Red
|
|
|
|
case rn(52, 49):
|
|
|
|
tile = 32;
|
|
|
|
break; //Red
|
|
|
|
case rn(48, 43):
|
|
|
|
tile = 32;
|
|
|
|
break; //Red
|
|
|
|
case rn(55, 47):
|
|
|
|
tile = 32;
|
|
|
|
break; //Red
|
|
|
|
case rn(54, 48):
|
|
|
|
tile = 32;
|
|
|
|
break; //Red
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
Fix, for in-GAMEMODE sprites, their colors updating too fast
Okay, so the problem here is that Graphics::setcol() is called right
before a sprite is drawn in a render function, but render functions are
done in deltatime, meaning that the color of a sprite keeps being
recalculated every time. This only affects sprites that use fRandom()
(the other thing that can dynamically determine a color is help.glow,
but that's only updated in the fixed-timestep loop), but is especially
noticeable for sprites that flash wildly, like the teleporter, trinket,
and elephant.
To fix this, we need to make the color be recalculated only in the
fixed-timestep loop. However, this means that we MUST store the color of
the sprite SOMEWHERE for the delta-timesteps to render it, otherwise the
color calculation will just be lost or something.
So each entity now has a new attribute, `realcol`, which is the actual
raw color used to render the sprite in render functions. This is not to
be confused with their `colour` attribute, which is more akin to a color
"ID" of sorts, but which isn't an actual color.
At the end of gamelogic(), as well as when an entity is first created,
the `colour` is given to Graphics::setcol() and then `realcol` gets set
to the actual color. Then when it comes time to render the entity,
`realcol` gets used instead.
Gravitron squares are a somewhat tricky case where there's technically
TWO colors for it - one is the actual sprite itself and the other is the
indicator. However, usually the indicator and the square aren't both
onscreen at the same time, so we can simply switch the realcol between
the two as needed.
However, we can't use this system for the sprite colors used on the
title and map screen, so we'll have to do something else for those.
2020-05-01 02:34:37 +02:00
|
|
|
|
|
|
|
void entclass::updatecolour()
|
|
|
|
{
|
|
|
|
switch (size)
|
|
|
|
{
|
|
|
|
case 0: // Sprites
|
|
|
|
case 7: // Teleporter
|
|
|
|
case 9: // Really Big Sprite! (2x2)
|
|
|
|
case 10: // 2x1 Sprite
|
|
|
|
case 13: // Special for epilogue: huge hero!
|
|
|
|
graphics.setcol(colour);
|
|
|
|
realcol = graphics.ct.colour;
|
|
|
|
break;
|
|
|
|
case 3: // Big chunky pixels!
|
|
|
|
realcol = graphics.bigchunkygetcol(colour);
|
|
|
|
break;
|
|
|
|
case 4: // Small pickups
|
|
|
|
graphics.huetilesetcol(colour);
|
|
|
|
realcol = graphics.ct.colour;
|
|
|
|
break;
|
|
|
|
case 11: // The fucking elephant
|
|
|
|
if (game.noflashingmode)
|
|
|
|
{
|
|
|
|
graphics.setcol(22);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
graphics.setcol(colour);
|
|
|
|
}
|
|
|
|
realcol = graphics.ct.colour;
|
|
|
|
break;
|
|
|
|
case 12: // Regular sprites that don't wrap
|
|
|
|
// if we're outside the screen, we need to draw indicators
|
|
|
|
if ((xp < -20 && vx > 0) || (xp > 340 && vx < 0))
|
|
|
|
{
|
|
|
|
graphics.setcol(23);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
graphics.setcol(colour);
|
|
|
|
}
|
|
|
|
realcol = graphics.ct.colour;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-10-20 08:10:18 +02:00
|
|
|
|
|
|
|
bool entclass::ishumanoid()
|
|
|
|
{
|
|
|
|
return type == 0
|
|
|
|
|| type == 12
|
|
|
|
|| type == 14
|
|
|
|
|| type == 55;
|
|
|
|
}
|