mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-22 17:49:43 +01:00
Reimplement coins as a usable feature
- Make coins use their own ID array in save files, instead of sharing the trinket ID array - Add coin editor entities to allow external tools to use coins, and help the game figure out when it should render the coin display - Unlimits the coin amount and stores it differently than other collectibles - Add `ifcoins` logic command to match trinkets - Add editor tool
This commit is contained in:
parent
880c7ad8e6
commit
ed125b1735
11 changed files with 124 additions and 5 deletions
|
@ -966,6 +966,23 @@ int customlevelclass::findtrinket(int t)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int customlevelclass::findcoin(int t)
|
||||
{
|
||||
int coins = 0;
|
||||
for (int i = 0; i < (int) customentities.size(); i++)
|
||||
{
|
||||
if (i == t)
|
||||
{
|
||||
return coins;
|
||||
}
|
||||
if (customentities[i].t == 8)
|
||||
{
|
||||
coins++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int customlevelclass::findcrewmate(int t)
|
||||
{
|
||||
int ttrinket=0;
|
||||
|
@ -1961,6 +1978,19 @@ int customlevelclass::numtrinkets(void)
|
|||
return temp;
|
||||
}
|
||||
|
||||
int customlevelclass::numcoins(void)
|
||||
{
|
||||
int temp = 0;
|
||||
for (size_t i = 0; i < customentities.size(); i++)
|
||||
{
|
||||
if (customentities[i].t == 8 && inbounds(&customentities[i]))
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
int customlevelclass::numcrewmates(void)
|
||||
{
|
||||
int temp = 0;
|
||||
|
|
|
@ -144,6 +144,7 @@ public:
|
|||
void generatecustomminimap(void);
|
||||
|
||||
int findtrinket(int t);
|
||||
int findcoin(int t);
|
||||
int findcrewmate(int t);
|
||||
int findwarptoken(int t);
|
||||
void findstartpoint(void);
|
||||
|
@ -157,6 +158,7 @@ public:
|
|||
static const int numrooms = maxwidth * maxheight;
|
||||
int contents[40 * 30 * numrooms];
|
||||
int numtrinkets(void);
|
||||
int numcoins(void);
|
||||
int numcrewmates(void);
|
||||
RoomProperty roomproperties[numrooms]; //Maxwidth*maxheight
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ editorclass::editorclass(void)
|
|||
register_tool(EditorTool_WARP_LINES, "Warp Lines", "I", SDLK_i, false);
|
||||
register_tool(EditorTool_CREWMATES, "Crewmates", "O", SDLK_o, false);
|
||||
register_tool(EditorTool_START_POINT, "Start Point", "P", SDLK_p, false);
|
||||
register_tool(EditorTool_COINS, "Coins", "^2", SDLK_2, true);
|
||||
|
||||
static const short basic[] = {
|
||||
121, 121, 121, 121, 121, 121, 121, 160, 121, 121, 121, 121, 121, 121, 121,
|
||||
|
@ -951,6 +952,10 @@ static void draw_entities(void)
|
|||
font::print(PR_FONT_8X8, x, y, "////", 255 - help.glow, 255 - help.glow, 255 - help.glow);
|
||||
graphics.draw_rect(x, y, 32, 8, graphics.getRGB(255, 255, 255));
|
||||
break;
|
||||
case 8: // Coins
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, x, y, 8, 8, graphics.huetilegetcol());
|
||||
graphics.draw_rect(x, y, 8, 8, graphics.getRGB(255, 164, 164));
|
||||
break;
|
||||
case 9: // Shiny Trinkets
|
||||
graphics.draw_sprite(x, y, 22, 196, 196, 196);
|
||||
graphics.draw_rect(x, y, 16, 16, graphics.getRGB(255, 164, 164));
|
||||
|
@ -1302,6 +1307,7 @@ static void draw_cursor(void)
|
|||
case EditorTool_GRAVITY_LINES:
|
||||
case EditorTool_ROOMTEXT:
|
||||
case EditorTool_SCRIPTS:
|
||||
case EditorTool_COINS:
|
||||
// 1x1
|
||||
graphics.draw_rect(x, y, 8, 8, blue);
|
||||
break;
|
||||
|
@ -1709,6 +1715,12 @@ void editorclass::draw_tool(EditorTools tool, int x, int y)
|
|||
case EditorTool_START_POINT:
|
||||
graphics.draw_sprite(x, y, 184, graphics.col_crewcyan);
|
||||
break;
|
||||
case EditorTool_COINS:
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, x, y - 1, 8, 8, graphics.getRGB(255, 255, 0));
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, x + 9, y - 1, 8, 8, graphics.getRGB(255, 255, 0));
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, x, y + 8, 8, 8, graphics.getRGB(255, 255, 0));
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, x + 9, y + 8, 8, 8, graphics.getRGB(255, 255, 0));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2414,6 +2426,9 @@ void editorclass::entity_clicked(const int index)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
lclickdelay = 0;
|
||||
break;
|
||||
case 10:
|
||||
// Checkpoints
|
||||
// If it's not textured as a checkpoint, then just leave it be
|
||||
|
@ -2597,6 +2612,9 @@ void editorclass::tool_place()
|
|||
add_entity(levx, levy, tilex, tiley, 16, 0);
|
||||
lclickdelay = 1;
|
||||
break;
|
||||
case EditorTool_COINS:
|
||||
add_entity(levx, levy, tilex, tiley, 8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ enum EditorTools
|
|||
EditorTool_WARP_LINES,
|
||||
EditorTool_CREWMATES,
|
||||
EditorTool_START_POINT,
|
||||
EditorTool_COINS,
|
||||
|
||||
NUM_EditorTools
|
||||
};
|
||||
|
|
|
@ -1526,7 +1526,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int
|
|||
|
||||
//Check if it's already been collected
|
||||
entity.para = meta1;
|
||||
if (!INBOUNDS_ARR(meta1, collect) || collect[meta1]) return;
|
||||
if (coincollect.find(meta1) != coincollect.end()) return;
|
||||
break;
|
||||
case 9: //Something Shiny
|
||||
entity.rule = 3;
|
||||
|
@ -2659,10 +2659,7 @@ bool entityclass::updateentities( int i )
|
|||
if (entities[i].state == 1)
|
||||
{
|
||||
music.playef(Sound_COIN);
|
||||
if (INBOUNDS_ARR(entities[i].para, collect))
|
||||
{
|
||||
collect[(int) entities[i].para] = true;
|
||||
}
|
||||
coincollect.insert(entities[i].para);
|
||||
|
||||
return disableentity(i);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define ENTITY_H
|
||||
|
||||
#include <SDL.h>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -175,6 +176,7 @@ public:
|
|||
std::vector<blockclass> blocks;
|
||||
bool flags[100];
|
||||
bool collect[100];
|
||||
std::set<int> coincollect;
|
||||
bool customcollect[100];
|
||||
|
||||
int platformtile;
|
||||
|
|
|
@ -492,6 +492,23 @@ void Game::deletecustomlevelstats(void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#define LOAD_SET_RENAME(SET_NAME, DEST) \
|
||||
if (SDL_strcmp(pKey, #SET_NAME) == 0 && pText[0] != '\0') \
|
||||
{ \
|
||||
/* We're loading in 32-bit integers. If we need more than 16 chars,
|
||||
* something is seriously wrong */ \
|
||||
char buffer[16]; \
|
||||
size_t start = 0; \
|
||||
size_t i = 0; \
|
||||
\
|
||||
while (next_split_s(buffer, sizeof(buffer), &start, pText, ',')) \
|
||||
{ \
|
||||
DEST.insert(help.Int(buffer)); \
|
||||
++i; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LOAD_ARRAY_RENAME(ARRAY_NAME, DEST) \
|
||||
if (SDL_strcmp(pKey, #ARRAY_NAME) == 0 && pText[0] != '\0') \
|
||||
{ \
|
||||
|
@ -5436,6 +5453,8 @@ void Game::customloadquick(const std::string& savfile)
|
|||
|
||||
LOAD_ARRAY_RENAME(collect, obj.collect)
|
||||
|
||||
LOAD_SET_RENAME(coincollect, obj.coincollect)
|
||||
|
||||
LOAD_ARRAY_RENAME(customcollect, obj.customcollect)
|
||||
|
||||
if (SDL_strcmp(pKey, "finalmode") == 0)
|
||||
|
@ -5979,6 +5998,16 @@ bool Game::customsavequick(const std::string& savfile)
|
|||
}
|
||||
xml::update_tag(msgs, "collect", collect.c_str());
|
||||
|
||||
std::string coincollect;
|
||||
std::set<int>::iterator iterator = obj.coincollect.begin();
|
||||
while (iterator != obj.coincollect.end()) {
|
||||
{
|
||||
coincollect += help.String(*iterator) + ",";
|
||||
iterator++;
|
||||
}
|
||||
}
|
||||
xml::update_tag(msgs, "coincollect", coincollect.c_str());
|
||||
|
||||
std::string customcollect;
|
||||
for(size_t i = 0; i < SDL_arraysize(obj.customcollect); i++ )
|
||||
{
|
||||
|
@ -7199,6 +7228,11 @@ int Game::trinkets(void)
|
|||
return temp;
|
||||
}
|
||||
|
||||
int Game::coins(void)
|
||||
{
|
||||
return (int) obj.coincollect.size();
|
||||
}
|
||||
|
||||
int Game::crewmates(void)
|
||||
{
|
||||
int temp = 0;
|
||||
|
|
|
@ -473,6 +473,7 @@ public:
|
|||
int deathseq, lifeseq;
|
||||
|
||||
int trinkets(void);
|
||||
int coins(void);
|
||||
int crewmates(void);
|
||||
int savepoint, teleportxpos;
|
||||
bool teleport;
|
||||
|
|
|
@ -1866,6 +1866,9 @@ void mapclass::loadlevel(int rx, int ry)
|
|||
case 3: // Disappearing platforms
|
||||
obj.createentity(ex, ey, 3);
|
||||
break;
|
||||
case 8: // Coins
|
||||
obj.createentity(ex, ey, 8, cl.findcoin(edi));
|
||||
break;
|
||||
case 9: // Trinkets
|
||||
obj.createentity(ex, ey, 9, cl.findtrinket(edi));
|
||||
break;
|
||||
|
|
|
@ -2070,6 +2070,26 @@ void gamerender(void)
|
|||
);
|
||||
}
|
||||
|
||||
bool show_coins = game.coins() > 0;
|
||||
#ifndef NO_CUSTOM_LEVELS
|
||||
show_coins = show_coins || (map.custommode && (cl.numcoins() > 0));
|
||||
#endif
|
||||
|
||||
if (show_coins) {
|
||||
int color = 255 - help.glow / 2;
|
||||
|
||||
font::print(PR_BOR | PR_RIGHT, 304, 231, help.String(game.coins()), color, color, 196);
|
||||
|
||||
if (!graphics.notextoutline) {
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, 310, 230, 8, 8, graphics.getRGB(0, 0, 0));
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, 312, 230, 8, 8, graphics.getRGB(0, 0, 0));
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, 311, 229, 8, 8, graphics.getRGB(0, 0, 0));
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, 311, 231, 8, 8, graphics.getRGB(0, 0, 0));
|
||||
}
|
||||
|
||||
graphics.draw_grid_tile(graphics.grphx.im_tiles_white, 48, 311, 230, 8, 8, graphics.getRGB(color, color, 196));
|
||||
}
|
||||
|
||||
if (map.roomtexton)
|
||||
{
|
||||
//Draw room text!
|
||||
|
|
|
@ -1238,6 +1238,14 @@ void scriptclass::run(void)
|
|||
position--;
|
||||
}
|
||||
}
|
||||
else if (words[0] == "ifcoins")
|
||||
{
|
||||
if (game.coins() >= ss_toi(words[1]))
|
||||
{
|
||||
load("custom_" + raw_words[2]);
|
||||
position--;
|
||||
}
|
||||
}
|
||||
else if (words[0] == "hidecoordinates")
|
||||
{
|
||||
map.setexplored(ss_toi(words[1]), ss_toi(words[2]), false);
|
||||
|
@ -1385,6 +1393,7 @@ void scriptclass::run(void)
|
|||
obj.collect[i] = false;
|
||||
obj.customcollect[i] = false;
|
||||
}
|
||||
obj.coincollect.clear();
|
||||
game.deathcounts = 0;
|
||||
game.advancetext = false;
|
||||
game.hascontrol = true;
|
||||
|
@ -3242,6 +3251,8 @@ void scriptclass::hardreset(void)
|
|||
SDL_memset(obj.customcollect, false, sizeof(obj.customcollect));
|
||||
i = 100; //previously a for-loop iterating over collect/customcollect set this to 100
|
||||
|
||||
obj.coincollect.clear();
|
||||
|
||||
int theplayer = obj.getplayer();
|
||||
if (INBOUNDS_VEC(theplayer, obj.entities)){
|
||||
obj.entities[theplayer].tile = 0;
|
||||
|
|
Loading…
Reference in a new issue