mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-12-01 15:35:47 +00:00
4519 lines
96 KiB
C++
4519 lines
96 KiB
C++
/*
|
|
Copyright (C) 2007, 2010 - Bit-Blot
|
|
|
|
This file is part of Aquaria.
|
|
|
|
Aquaria is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
#include "../BBGE/DebugFont.h"
|
|
#include "../ExternalLibs/glpng.h"
|
|
#include "../BBGE/AfterEffect.h"
|
|
|
|
#include "DSQ.h"
|
|
#include "States.h"
|
|
#include "Game.h"
|
|
#include "Logo.h"
|
|
#include "Avatar.h"
|
|
#include "Entity.h"
|
|
#include "Avatar.h"
|
|
#include "Shot.h"
|
|
#include "GridRender.h"
|
|
#include "AnimationEditor.h"
|
|
#include "Intro.h"
|
|
|
|
#include "RoundedRect.h"
|
|
#include "TTFFont.h"
|
|
#include "ModSelector.h"
|
|
#include "Network.h"
|
|
#include "ttvfs_stdio.h"
|
|
#include "GLLoad.h"
|
|
#include "RenderBase.h"
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#ifdef BBGE_BUILD_VFS
|
|
#include "ttvfs.h"
|
|
#endif
|
|
|
|
#ifdef BBGE_BUILD_UNIX
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
|
|
static void Linux_CopyTree(const char *src, const char *dst)
|
|
{
|
|
|
|
|
|
struct stat statbuf;
|
|
if (stat(src, &statbuf) == -1)
|
|
return;
|
|
|
|
if (S_ISDIR(statbuf.st_mode))
|
|
{
|
|
createDir(dst); // don't care if this fails.
|
|
DIR *dirp = opendir(src);
|
|
if (dirp == NULL)
|
|
return;
|
|
|
|
struct dirent *dent;
|
|
while ((dent = readdir(dirp)) != NULL)
|
|
{
|
|
if ((strcmp(dent->d_name, ".") == 0) || (strcmp(dent->d_name, "..") == 0))
|
|
continue;
|
|
const size_t srclen = strlen(src) + strlen(dent->d_name) + 2;
|
|
char *subsrc = new char[srclen];
|
|
snprintf(subsrc, srclen, "%s/%s", src, dent->d_name);
|
|
const size_t dstlen = strlen(dst) + strlen(dent->d_name) + 2;
|
|
char *subdst = new char[dstlen];
|
|
snprintf(subdst, dstlen, "%s/%s", dst, dent->d_name);
|
|
Linux_CopyTree(subsrc, subdst);
|
|
delete[] subdst;
|
|
delete[] subsrc;
|
|
}
|
|
closedir(dirp);
|
|
}
|
|
|
|
else if (S_ISREG(statbuf.st_mode))
|
|
{
|
|
const int in = open(src, O_RDONLY);
|
|
if (in == -1)
|
|
return;
|
|
|
|
// fail if it already exists. That's okay in this case.
|
|
const int out = open(dst, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
|
if (out == -1)
|
|
{
|
|
close(in);
|
|
return;
|
|
}
|
|
|
|
const size_t buflen = 256 * 1024;
|
|
char *buf = new char[buflen];
|
|
bool failed = false;
|
|
ssize_t br = 0;
|
|
while ( (!failed) && ((br = read(in, buf, buflen)) > 0) )
|
|
failed = (write(out, buf, br) != br);
|
|
|
|
if (br < 0)
|
|
failed = true;
|
|
|
|
delete[] buf;
|
|
|
|
if (close(out) < 0)
|
|
failed = true;
|
|
|
|
close(in);
|
|
|
|
if (failed)
|
|
unlink(dst);
|
|
}
|
|
|
|
else
|
|
{
|
|
fprintf(stderr, "WARNING: we should have copied %s to %s, but it's not a dir or file! Skipped it.\n", src, dst);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
const int saveSlotPageSize = 4;
|
|
int maxPages = 15;
|
|
#ifdef AQUARIA_BUILD_CONSOLE
|
|
const int MAX_CONSOLELINES = 18;
|
|
#endif
|
|
|
|
DSQ *dsq = 0;
|
|
|
|
const bool isReleaseCandidate = false;
|
|
const bool isFinalCandidate = false;
|
|
const bool isGoldMaster = true;
|
|
|
|
Vector savesz;
|
|
|
|
/// WARNING: this is just to init, the actual value is set from user settings!
|
|
#define PARTICLE_AMOUNT_DEFAULT 2048
|
|
|
|
#ifdef AQUARIA_DEMO
|
|
#define APPNAME "Aquaria Demo"
|
|
#else
|
|
#define APPNAME "Aquaria"
|
|
#endif
|
|
|
|
DSQ::DSQ(const std::string& fileSystem, const std::string& extraDataDir)
|
|
: Core(fileSystem, extraDataDir, LR_MAX, APPNAME, PARTICLE_AMOUNT_DEFAULT, "Aquaria")
|
|
{
|
|
dsq = this;
|
|
|
|
cutscene_bg = 0;
|
|
cutscene_text = 0;
|
|
cutscene_text2 = 0;
|
|
|
|
doScreenTrans = false;
|
|
|
|
cutscenePaused = false;
|
|
inCutscene = false;
|
|
_canSkipCutscene = false;
|
|
skippingCutscene = false;
|
|
|
|
bar_left = bar_right = bar_up = bar_down = barFade_left = barFade_right = 0;
|
|
|
|
difficulty = DIFF_NORMAL;
|
|
|
|
|
|
|
|
watchQuitFlag = false;
|
|
watchForQuit = false;
|
|
|
|
particleBank1 = "data/particles/";
|
|
particleBank2 = "";
|
|
|
|
shotBank1 = "data/shots/";
|
|
shotBank2 = "";
|
|
|
|
disableMiniMapOnNoInput = true;
|
|
noEffectTimer = 0;
|
|
saveSlotPageCount = 0;
|
|
inModSelector = false;
|
|
subtext = 0;
|
|
subbox = 0;
|
|
modSelectorScr = 0;
|
|
blackout = 0;
|
|
inputMode = INPUT_MOUSE;
|
|
overlay = 0;
|
|
recentSaveSlot = -1;
|
|
arialFontData = 0;
|
|
|
|
#ifdef BBGE_BUILD_ACHIEVEMENTS_INTERNAL
|
|
achievement_text = 0;
|
|
achievement_box = 0;
|
|
#endif
|
|
|
|
#ifdef AQUARIA_BUILD_CONSOLE
|
|
console = 0;
|
|
#endif
|
|
cmDebug = 0;
|
|
languagePack = "english";
|
|
saveSlotMode = SSM_NONE;
|
|
afterEffectManagerLayer = LR_AFTER_EFFECTS; // LR_AFTER_EFFECTS
|
|
renderObjectLayers.resize(LR_MAX);
|
|
|
|
entities.resize(64, 0);
|
|
|
|
shakeCameraTimer = shakeCameraMag = 0;
|
|
avgFPS.resize(dsq->user.video.fpsSmoothing);
|
|
|
|
cursor = cursorGlow = 0;
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
firstElementOnLayer[i] = 0;
|
|
}
|
|
|
|
DSQ::~DSQ()
|
|
{
|
|
dsq = 0;
|
|
}
|
|
|
|
// actually toggle
|
|
void DSQ::toggleFullscreen()
|
|
{
|
|
setFullscreen(!_fullscreen);
|
|
user.video.full = _fullscreen;
|
|
}
|
|
|
|
// for handling the input, not the actual switch functionality
|
|
void DSQ::onSwitchScreenMode()
|
|
{
|
|
if (getAltState())
|
|
toggleFullscreen();
|
|
}
|
|
|
|
void DSQ::onWindowResize(int w, int h)
|
|
{
|
|
Core::onWindowResize(w, h);
|
|
screenTransition->reloadDevice();
|
|
}
|
|
|
|
void DSQ::rumble(float leftMotor, float rightMotor, float time, int source)
|
|
{
|
|
if (this->inputMode == INPUT_JOYSTICK)
|
|
{
|
|
if(source < 0)
|
|
for(size_t i = 0; i < user.control.actionSets.size(); ++i)
|
|
{
|
|
const ActionSet& as = user.control.actionSets[i];
|
|
if(Joystick *j = core->getJoystick(as.joystickID))
|
|
j->rumble(leftMotor, rightMotor, time);
|
|
}
|
|
else if(source < (int)user.control.actionSets.size())
|
|
{
|
|
const ActionSet& as = user.control.actionSets[source];
|
|
if(Joystick *j = core->getJoystick(as.joystickID))
|
|
j->rumble(leftMotor, rightMotor, time);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DSQ::newGame()
|
|
{
|
|
dsq->game->resetFromTitle();
|
|
dsq->initScene = "NaijaCave";
|
|
dsq->game->transitionToScene(dsq->initScene);
|
|
}
|
|
|
|
void DSQ::loadElementEffects()
|
|
{
|
|
bool found = false;
|
|
std::string fn;
|
|
if (dsq->mod.isActive())
|
|
{
|
|
fn = dsq->mod.getPath() + "elementeffects.txt";
|
|
if(exists(fn))
|
|
found = true;
|
|
}
|
|
if(!found)
|
|
fn = "data/elementeffects.txt";
|
|
|
|
InStream inFile(fn.c_str());
|
|
elementEffects.clear();
|
|
std::string line;
|
|
while (std::getline(inFile, line))
|
|
{
|
|
debugLog("Line: " + line);
|
|
std::istringstream is(line);
|
|
ElementEffect e;
|
|
int efxType = EFX_NONE;
|
|
int idx;
|
|
std::string type;
|
|
is >> idx >> type;
|
|
if (type == "EFX_SEGS")
|
|
{
|
|
efxType = EFX_SEGS;
|
|
is >> e.segsx >> e.segsy >> e.segs_dgox >> e.segs_dgoy >> e.segs_dgmx >> e.segs_dgmy >> e.segs_dgtm >> e.segs_dgo;
|
|
}
|
|
else if (type == "EFX_WAVY")
|
|
{
|
|
debugLog("loading wavy");
|
|
efxType = EFX_WAVY;
|
|
is >> e.segsy >> e.wavy_radius >> e.wavy_flip;
|
|
|
|
}
|
|
else if (type == "EFX_ALPHA")
|
|
{
|
|
efxType = EFX_ALPHA;
|
|
float to_x, time, loop, pingPong, ease;
|
|
is >> e.blendType >> e.alpha.x >> to_x >> time >> loop >> pingPong >> ease;
|
|
e.alpha.interpolateTo(to_x, time, loop, pingPong, ease);
|
|
}
|
|
e.type = efxType;
|
|
elementEffects.push_back(e);
|
|
}
|
|
inFile.close();
|
|
}
|
|
|
|
ElementEffect DSQ::getElementEffectByIndex(int e)
|
|
{
|
|
if (e < elementEffects.size() && e >= 0)
|
|
{
|
|
return elementEffects[e];
|
|
}
|
|
|
|
ElementEffect empty;
|
|
empty.type = EFX_NONE;
|
|
|
|
return empty;
|
|
}
|
|
|
|
void DSQ::centerMessage(const std::string &text, float y, int type)
|
|
{
|
|
Vector pos(400,y);
|
|
float time = 2;
|
|
|
|
BitmapText *t = 0;
|
|
if (type == 1)
|
|
t = new BitmapText(&smallFontRed);
|
|
else
|
|
t = new BitmapText(&smallFont);
|
|
t->position = pos;
|
|
t->alpha.ensureData();
|
|
t->alpha.data->path.addPathNode(1, 0);
|
|
t->alpha.data->path.addPathNode(1, 0.8);
|
|
t->alpha.data->path.addPathNode(0, 1);
|
|
t->alpha.startPath(time);
|
|
t->followCamera = 1;
|
|
t->setLife(time + 0.5f);
|
|
t->setDecayRate(1);
|
|
t->setText(text);
|
|
t->offset.interpolateTo(Vector(0, -40), 2, 0, 0, 1);
|
|
getTopStateData()->addRenderObject(t, LR_OVERLAY);
|
|
}
|
|
|
|
void DSQ::centerText(const std::string &text)
|
|
{
|
|
Vector pos(400,200);
|
|
float time = 8;
|
|
|
|
BitmapText *s = new BitmapText(&font);
|
|
s->color = Vector(0,0,0);
|
|
s->position = pos;
|
|
s->offset = Vector(1,1);
|
|
s->setText(text);
|
|
s->setLife(time + 0.5f);
|
|
s->setDecayRate(1);
|
|
s->followCamera = 1;
|
|
s->alpha.ensureData();
|
|
s->alpha.data->path.addPathNode(0, 0);
|
|
s->alpha.data->path.addPathNode(1, 0.1);
|
|
s->alpha.data->path.addPathNode(1, 0.8);
|
|
s->alpha.data->path.addPathNode(0, 1);
|
|
s->alpha.startPath(time);
|
|
getTopStateData()->addRenderObject(s, LR_HUD);
|
|
|
|
|
|
BitmapText *t = new BitmapText(&font);
|
|
|
|
|
|
t->position =pos;
|
|
t->alpha.ensureData();
|
|
t->alpha.data->path.addPathNode(0, 0);
|
|
t->alpha.data->path.addPathNode(1, 0.1);
|
|
t->alpha.data->path.addPathNode(1, 0.8);
|
|
t->alpha.data->path.addPathNode(0, 1);
|
|
t->alpha.startPath(time);
|
|
|
|
t->followCamera = 1;
|
|
t->setLife(time + 0.5f);
|
|
t->setDecayRate(1);
|
|
|
|
t->setText(text);
|
|
getTopStateData()->addRenderObject(t, LR_HUD);
|
|
}
|
|
|
|
void DSQ::destroyFonts()
|
|
{
|
|
|
|
debugLog("destroyFonts...");
|
|
font.destroy();
|
|
smallFont.destroy();
|
|
subsFont.destroy();
|
|
goldFont.destroy();
|
|
smallFontRed.destroy();
|
|
|
|
debugLog("ttf fonts...");
|
|
fontArialBig.destroy();
|
|
fontArialSmall.destroy();
|
|
fontArialSmallest.destroy();
|
|
delete[] arialFontData;
|
|
arialFontData = 0;
|
|
|
|
debugLog("done destroyFonts");
|
|
}
|
|
|
|
void DSQ::loadFonts()
|
|
{
|
|
debugLog("loadFonts...");
|
|
|
|
destroyFonts();
|
|
|
|
std::string file = localisePath("data/font-small.glf");
|
|
|
|
font.load(file, 1, false);
|
|
font.fontTopColor = Vector(0.9,0.9,1);
|
|
font.fontBtmColor = Vector(0.5,0.8,1);
|
|
font.overrideTexture = core->addTexture("font");
|
|
|
|
smallFont.load(file, 0.6, false);
|
|
smallFont.fontTopColor = Vector(0.9,0.9,1);
|
|
smallFont.fontBtmColor = Vector(0.5,0.8,1);
|
|
smallFont.overrideTexture = core->addTexture("font");
|
|
|
|
smallFontRed.load(file, 0.6, false);
|
|
smallFontRed.fontTopColor = Vector(1,0.9,0.9);
|
|
smallFontRed.fontBtmColor = Vector(1,0.8,0.5);
|
|
smallFontRed.overrideTexture = core->addTexture("font");
|
|
|
|
subsFont.load(file, 0.5, false);
|
|
subsFont.fontTopColor = Vector(1,1,1);
|
|
subsFont.fontBtmColor = Vector(0.5,0.8,1);
|
|
subsFont.overrideTexture = core->addTexture("font");
|
|
|
|
goldFont.load(file, 1, false);
|
|
goldFont.fontTopColor = Vector(1,0.9,0.5);
|
|
goldFont.fontBtmColor = Vector(0.6,0.5,0.25);
|
|
goldFont.overrideTexture = core->addTexture("font");
|
|
|
|
|
|
file = localisePath("data/font.ttf");
|
|
|
|
debugLog("ttf...");
|
|
arialFontData = (unsigned char *)readFile(file, &arialFontDataSize);
|
|
if (arialFontData)
|
|
{
|
|
fontArialSmall .create(arialFontData, arialFontDataSize, 12);
|
|
fontArialBig .create(arialFontData, arialFontDataSize, 18);
|
|
fontArialSmallest.create(arialFontData, arialFontDataSize, 10);
|
|
}
|
|
debugLog("done loadFonts");
|
|
|
|
|
|
|
|
}
|
|
|
|
void DSQ::onReloadResources()
|
|
{
|
|
Core::onReloadResources();
|
|
|
|
loadFonts();
|
|
|
|
setTexturePointers();
|
|
}
|
|
|
|
void DSQ::debugMenu()
|
|
{
|
|
if (isDeveloperKeys() || (mod.isActive() && mod.isDebugMenu()))
|
|
{
|
|
|
|
if (core->getShiftState())
|
|
|
|
{
|
|
core->frameOutputMode = false;
|
|
dsq->game->togglePause(true);
|
|
std::string s = dsq->getUserInputString(dsq->continuity.stringBank.get(2012), "");
|
|
stringToUpper(s);
|
|
|
|
|
|
|
|
if (!dsq->game->isSceneEditorActive())
|
|
dsq->game->togglePause(false);
|
|
if (!s.empty())
|
|
{
|
|
char c = s[0];
|
|
int i = 0;
|
|
if (c == '1')
|
|
{
|
|
v.load();
|
|
|
|
core->particleManager->loadParticleBank(particleBank1, particleBank2);
|
|
|
|
// important: kill all shots before reloading the shot bank
|
|
// still might crash here
|
|
Shot::killAllShots();
|
|
Shot::loadShotBank(shotBank1, shotBank2);
|
|
dsq->continuity.loadEatBank();
|
|
|
|
dsq->game->loadEntityTypeList();
|
|
if (core->afterEffectManager)
|
|
{
|
|
core->afterEffectManager->loadShaders();
|
|
}
|
|
dsq->user.load();
|
|
dsq->continuity.loadIngredientData();
|
|
}
|
|
else if (c == '2')
|
|
{
|
|
if (dsq->game && dsq->game->avatar)
|
|
{
|
|
dsq->game->avatar->heal(999);
|
|
}
|
|
}
|
|
else if (c == '3')
|
|
{
|
|
dsq->continuity.reset();
|
|
}
|
|
else if (c == 'B')
|
|
{
|
|
dsq->unloadResources();
|
|
}
|
|
else if (c == 'A')
|
|
{
|
|
dsq->reloadResources();
|
|
}
|
|
else if (c == 'J')
|
|
{
|
|
std::istringstream is(s);
|
|
std::string state;
|
|
char read = ' ';
|
|
is >> read >> state;
|
|
|
|
dsq->quitNestedMain();
|
|
dsq->enqueueJumpState(state);
|
|
}
|
|
else if (c == 'Q')
|
|
{
|
|
dsq->quitNestedMain();
|
|
}
|
|
|
|
else if (c == '5')
|
|
{
|
|
|
|
dsq->game->invinciblity = !dsq->game->invinciblity;
|
|
}
|
|
else if (c == '6')
|
|
{
|
|
while (core->getKeyState(KEY_RETURN))
|
|
core->run(0.1);
|
|
dsq->setStory();
|
|
}
|
|
else if (c == '8')
|
|
{
|
|
for (i = 0; i <= SONG_MAX; i++)
|
|
dsq->continuity.learnSong(i);
|
|
}
|
|
else if (c == '9')
|
|
{
|
|
for (i = 0; i <= SONG_MAX; i++)
|
|
dsq->continuity.learnSong(i);
|
|
for (i = 0; i < FORMUPGRADE_MAX; i++)
|
|
{
|
|
dsq->continuity.learnFormUpgrade((FormUpgradeType)i);
|
|
}
|
|
}
|
|
else if (c == '0')
|
|
{
|
|
dsq->continuity.learnSong(SONG_SHIELDAURA);
|
|
dsq->continuity.learnSong(SONG_ENERGYFORM);
|
|
dsq->continuity.learnSong(SONG_BIND);
|
|
}
|
|
else if (c == 'S')
|
|
{
|
|
std::istringstream is(s);
|
|
int num = 0;
|
|
char read=' ';
|
|
is >> read >> num;
|
|
dsq->continuity.learnSong(num);
|
|
|
|
|
|
}
|
|
else if (c == 'F')
|
|
{
|
|
std::istringstream is(s);
|
|
char read = ' ';
|
|
std::string entityName;
|
|
is >> read >> entityName;
|
|
Entity *e = dsq->getEntityByNameNoCase(entityName);
|
|
if (e)
|
|
{
|
|
dsq->cameraPos = game->getCameraPositionFor(e->position);
|
|
}
|
|
}
|
|
else if (c == 'C')
|
|
{
|
|
std::istringstream is(s);
|
|
std::string nm;
|
|
char read=' ';
|
|
is >> read >> nm;
|
|
dsq->continuity.setCostume(nm);
|
|
}
|
|
else if (c == 'R')
|
|
{
|
|
dsq->demo.toggleRecord(true);
|
|
}
|
|
else if (c == 'P')
|
|
{
|
|
dsq->demo.togglePlayback(true);
|
|
}
|
|
else if (c == 'T')
|
|
{
|
|
if (dsq->demo.frames.size()> 0)
|
|
{
|
|
dsq->game->avatar->position = dsq->demo.frames[0].avatarPos;
|
|
dsq->game->avatar->rotation.z = dsq->demo.frames[0].rot;
|
|
}
|
|
}
|
|
else if (c == 'U')
|
|
{
|
|
dsq->demo.renderFramesToDisk();
|
|
|
|
|
|
}
|
|
else if (c == 'K')
|
|
{
|
|
dsq->demo.clearRecordedFrames();
|
|
}
|
|
else if (c == 'H')
|
|
{
|
|
std::ostringstream os;
|
|
os << dsq->game->avatar->health;
|
|
std::istringstream is(dsq->getUserInputString(dsq->continuity.stringBank.get(2013), os.str()));
|
|
float h = 0;
|
|
is >> h;
|
|
dsq->game->avatar->health = h;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void DSQ::takeScreenshotKey()
|
|
{
|
|
if (getCtrlState() && getAltState())
|
|
screenshot();
|
|
}
|
|
|
|
Quad *loading=0;
|
|
|
|
float loadingProgress = 0;
|
|
static const float loadingProgressTable[] = {
|
|
#define LOAD_INITIAL 0 // Initial display (just so it's not empty)
|
|
#define LOAD_PARTICLES 1 // After loading particles and shots
|
|
#define LOAD_SOUNDCACHE 2 // After loading the sound cache
|
|
#define LOAD_FONTS 3 // After loading fonts
|
|
#define LOAD_GRAPHICS1 4 // After creating graphics resources
|
|
#define LOAD_GRAPHICS2 5 // After creating more graphics resources
|
|
#define LOAD_TEXTURES 6 // After loading textures to be precached
|
|
#define LOAD_FINISHED 7 // All done!
|
|
0.01, 0.07, 0.20, 0.23, 0.24, 0.25, 0.89, 1.00,
|
|
};
|
|
|
|
void loadBit(int index, float perc = 1)
|
|
{
|
|
const float previous = index==0 ? 0 : loadingProgressTable[index-1];
|
|
const float next = loadingProgressTable[index];
|
|
loadingProgress = MIN(1, previous + ((next - previous) * MIN(1, perc)));
|
|
|
|
loading->setWidthHeight(loadingProgress*600, 23);
|
|
|
|
core->render();
|
|
core->showBuffer();
|
|
}
|
|
|
|
unsigned int soundsLoaded = 0;
|
|
const unsigned int soundsExpected = 195;
|
|
void loadBitForSoundCache()
|
|
{
|
|
if (soundsLoaded > 0 && soundsLoaded < soundsExpected)
|
|
{
|
|
// Only update every 4 sounds so we don't waste too much
|
|
// time waiting for vsync.
|
|
if (soundsLoaded % 4 == 0)
|
|
{
|
|
loadBit(LOAD_SOUNDCACHE,
|
|
(float)soundsLoaded / soundsExpected);
|
|
}
|
|
}
|
|
soundsLoaded++;
|
|
}
|
|
|
|
unsigned int texturesLoaded = 0;
|
|
const unsigned int texturesExpected = 652;
|
|
void loadBitForTexPrecache()
|
|
{
|
|
if (texturesLoaded > 0 && texturesLoaded < texturesExpected)
|
|
{
|
|
if (texturesLoaded % 16 == 0)
|
|
{
|
|
loadBit(LOAD_TEXTURES,
|
|
(float)texturesLoaded / texturesExpected);
|
|
}
|
|
}
|
|
texturesLoaded++;
|
|
}
|
|
|
|
|
|
void DSQ::setVersionLabelText()
|
|
{
|
|
#ifdef AQUARIA_OVERRIDE_VERSION_STRING
|
|
std::string overrideText = AQUARIA_OVERRIDE_VERSION_STRING;
|
|
if(user.system.allowDangerousScriptFunctions)
|
|
overrideText += continuity.stringBank.get(2050);
|
|
versionLabel->setText(overrideText);
|
|
return;
|
|
#endif
|
|
|
|
std::ostringstream os;
|
|
os << "Aquaria";
|
|
|
|
#ifdef AQUARIA_DEMO
|
|
os << " Demo";
|
|
#endif
|
|
|
|
os << " v" << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION;
|
|
|
|
if (!isFinalCandidate && !isGoldMaster && VERSION_BETA)
|
|
{
|
|
os << "b" << VERSION_BETA;
|
|
}
|
|
|
|
if (isFinalCandidate)
|
|
{
|
|
os << "fc" << VERSION_FC;
|
|
}
|
|
else if (isReleaseCandidate)
|
|
{
|
|
os << "RC";
|
|
}
|
|
else if (isGoldMaster)
|
|
{
|
|
|
|
}
|
|
|
|
#ifdef AQUARIA_CUSTOM_BUILD_ID
|
|
os << AQUARIA_CUSTOM_BUILD_ID;
|
|
#endif
|
|
|
|
if(user.system.allowDangerousScriptFunctions)
|
|
os << continuity.stringBank.get(2050);
|
|
|
|
versionLabel->setText(os.str());
|
|
}
|
|
|
|
static bool sdlVideoModeOK(const int w, const int h, const int bpp)
|
|
{
|
|
#ifdef BBGE_BUILD_SDL2
|
|
SDL_DisplayMode mode;
|
|
const int modecount = SDL_GetNumDisplayModes(0);
|
|
for (int i = 0; i < modecount; i++) {
|
|
SDL_GetDisplayMode(0, i, &mode);
|
|
if (!mode.w || !mode.h || (w >= mode.w && h >= mode.h)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
#else
|
|
return SDL_VideoModeOK(w, h, bpp, SDL_OPENGL | SDL_FULLSCREEN);
|
|
#endif
|
|
}
|
|
|
|
void DSQ::init()
|
|
{
|
|
core->settings.runInBackground = true;
|
|
|
|
#ifdef BBGE_BUILD_WINDOWS
|
|
/*
|
|
const std::string welcomeMessage = \
|
|
"Thank you for reviewing Aquaria!\n\
|
|
This build is not yet final, and as such there are a couple things lacking. They include:\n\
|
|
* documentation (not 100% complete)\n\
|
|
* mod editing (some known issues)\n\
|
|
* gamepad support/config (some known issues)\n\
|
|
\nFor the best experience, we recommend playing using the mouse or mouse and keyboard.\n\
|
|
Have fun!";
|
|
|
|
if (!welcomeMessage.empty())
|
|
{
|
|
MessageBox(core->hWnd, welcomeMessage.c_str(), "Welcome to Aquaria", MB_OK);
|
|
}
|
|
*/
|
|
#endif
|
|
|
|
disableMiniMapOnNoInput = true;
|
|
fpsText = 0;
|
|
cmDebug = 0;
|
|
|
|
debugLog("DSQ init");
|
|
|
|
useFrameBuffer = false;
|
|
gameSpeed = 1;
|
|
|
|
// steam gets inited in here
|
|
Core::init();
|
|
|
|
continuity.stringBank.load();
|
|
|
|
vars = &v;
|
|
v.load();
|
|
|
|
// steam callbacks are inited here
|
|
continuity.init();
|
|
|
|
// do copy stuff
|
|
#ifdef BBGE_BUILD_UNIX
|
|
std::string fn;
|
|
fn = getPreferencesFolder() + "/" + userSettingsFilename;
|
|
if (!exists(fn))
|
|
Linux_CopyTree(adjustFilenameCase(userSettingsFilename).c_str(), adjustFilenameCase(fn).c_str());
|
|
|
|
fn = getUserDataFolder() + "/_mods";
|
|
if (!exists(fn))
|
|
Linux_CopyTree(adjustFilenameCase("_mods").c_str(), adjustFilenameCase(fn).c_str());
|
|
#endif
|
|
|
|
createDir(getUserDataFolder());
|
|
createDir(getUserDataFolder() + "/save");
|
|
createDir(getUserDataFolder() + "/_mods");
|
|
createDir(getUserDataFolder() + "/screenshots");
|
|
|
|
addStateInstance(game = new Game);
|
|
addStateInstance(new GameOver);
|
|
#ifdef AQUARIA_BUILD_SCENEEDITOR
|
|
addStateInstance(new AnimationEditor);
|
|
#endif
|
|
addStateInstance(new Intro2);
|
|
addStateInstance(new BitBlotLogo);
|
|
#ifdef AQUARIA_BUILD_SCENEEDITOR
|
|
addStateInstance(new ParticleEditor);
|
|
#endif
|
|
addStateInstance(new Credits);
|
|
addStateInstance(new Intro);
|
|
addStateInstance(new Nag);
|
|
|
|
|
|
|
|
this->setBaseTextureDirectory("gfx/");
|
|
|
|
bool fullscreen = true;
|
|
voiceOversEnabled = true;
|
|
|
|
|
|
|
|
user.load(false);
|
|
|
|
particleManager->setSize(user.video.numParticles);
|
|
|
|
fullscreen = user.video.full;
|
|
useFrameBuffer = user.video.fbuffer;
|
|
|
|
if (isDeveloperKeys())
|
|
{
|
|
maxPages = 600/saveSlotPageSize;
|
|
}
|
|
|
|
if (isDeveloperKeys())
|
|
debugLog("DeveloperKeys Enabled");
|
|
else
|
|
debugLog("DeveloperKeys Disabled");
|
|
|
|
if (voiceOversEnabled)
|
|
debugLog("VoiceOvers Enabled");
|
|
else
|
|
debugLog("VoiceOvers Disabled");
|
|
|
|
SDL_Init(SDL_INIT_VIDEO);
|
|
if (fullscreen && !sdlVideoModeOK(user.video.resx, user.video.resy, user.video.bits))
|
|
{
|
|
// maybe we can force a sane resolution if SetVideoMode is going to fail...
|
|
user.video.resx = 800;
|
|
user.video.resy = 600;
|
|
if (!sdlVideoModeOK(user.video.resx, user.video.resy, user.video.bits))
|
|
fullscreen = false; // last chance.
|
|
}
|
|
|
|
debugLog("Init Graphics Library...");
|
|
initGraphicsLibrary(user.video.resx, user.video.resy, fullscreen, user.video.vsync, user.video.bits);
|
|
debugLog("OK");
|
|
|
|
setInputGrab(0);
|
|
|
|
debugLog("Init Sound Library...");
|
|
initSoundLibrary(user.audio.deviceName);
|
|
debugLog("Set Voice Fader");
|
|
sound->setVoiceFader(0.5);
|
|
sound->event_playVoice.set(MakeFunctionEvent(DSQ, onPlayVoice));
|
|
sound->event_stopVoice.set(MakeFunctionEvent(DSQ, onStopVoice));
|
|
debugLog("OK");
|
|
|
|
debugLog("Init Input Library...");
|
|
initInputLibrary();
|
|
debugLog("OK");
|
|
|
|
if (user.control.joystickEnabled)
|
|
{
|
|
debugLog("Init Joystick Library...");
|
|
initJoystickLibrary();
|
|
|
|
debugLog("OK");
|
|
}
|
|
|
|
user.apply();
|
|
|
|
applyPatches();
|
|
|
|
loading = new Quad("loading/juice", Vector(400,300));
|
|
loading->alpha = 1.0;
|
|
loading->followCamera = 1;
|
|
loading->setWidthHeight(0,0);
|
|
addRenderObject(loading, LR_HUD);
|
|
|
|
Vector loadShift(2, 0);
|
|
|
|
|
|
Vector sz(800.0f/1024.0f, 600.0f/768.0f);
|
|
|
|
|
|
|
|
Quad *tube = new Quad("loading/tube", Vector(400, 300));
|
|
tube->followCamera = 1;
|
|
tube->scale = sz;
|
|
addRenderObject(tube, LR_HUD);
|
|
|
|
Quad *label = new Quad("loading/label", Vector(400, 300));
|
|
label->followCamera = 1;
|
|
label->scale = sz;
|
|
addRenderObject(label, LR_HUD);
|
|
|
|
int sideOut = 300, sideDown = 8;
|
|
|
|
Quad *sidel = new Quad("loading/side", Vector(400-sideOut, 300+sideDown));
|
|
sidel->followCamera = 1;
|
|
sidel->scale = sz;
|
|
addRenderObject(sidel, LR_HUD);
|
|
|
|
Quad *sider = new Quad("loading/side", Vector(400+sideOut, 300+sideDown));
|
|
sider->flipHorizontal();
|
|
sider->followCamera = 1;
|
|
sider->scale = sz;
|
|
addRenderObject(sider, LR_HUD);
|
|
|
|
|
|
|
|
core->render();
|
|
core->showBuffer();
|
|
|
|
|
|
|
|
loadBit(LOAD_INITIAL);
|
|
|
|
debugLog("Loading Particle Bank...");
|
|
{
|
|
core->particleManager->loadParticleBank(particleBank1, particleBank2);
|
|
Shot::loadShotBank(shotBank1, shotBank2);
|
|
}
|
|
debugLog("OK");
|
|
|
|
loadBit(LOAD_PARTICLES);
|
|
|
|
|
|
|
|
debugLog("Loading Sound Cache...");
|
|
sound->loadSoundCache("sfx/cache/", ".ogg", loadBitForSoundCache);
|
|
debugLog("OK");
|
|
|
|
loadBit(LOAD_SOUNDCACHE);
|
|
|
|
|
|
debugLog("Init Script Interface...");
|
|
scriptInterface.init();
|
|
debugLog("OK");
|
|
|
|
loadFonts();
|
|
|
|
loadBit(LOAD_FONTS);
|
|
|
|
dsq->continuity.stringBank.load();
|
|
|
|
setTexturePointers();
|
|
|
|
cursor = new Quad;
|
|
{
|
|
cursor->alphaMod = 0.5;
|
|
cursor->toggleCull(false);
|
|
cursor->followCamera = 1;
|
|
cursor->setWidthHeight(24, 24);
|
|
cursor->alpha = 0;
|
|
}
|
|
addRenderObject (cursor, LR_CURSOR);
|
|
|
|
user.video.darkbuffersize = MAX(user.video.darkbuffersize,128);
|
|
|
|
dsq->darkLayer.setLayers(LR_ELEMENTS13, LR_AFTER_EFFECTS);
|
|
debugLog("dark layer init");
|
|
dsq->darkLayer.init(user.video.darkbuffersize, user.video.darkfbuffer);
|
|
debugLog("dark layer togle...");
|
|
dsq->darkLayer.toggle(0);
|
|
debugLog("done");
|
|
|
|
debugLog("post FX init");
|
|
dsq->postProcessingFx.init();
|
|
debugLog("done");
|
|
|
|
|
|
#ifdef AQUARIA_BUILD_CONSOLE
|
|
debugLog("Creating console");
|
|
console = new DebugFont;
|
|
|
|
{
|
|
console->position = Vector(10 - virtualOffX,400);
|
|
console->followCamera = 1;
|
|
console->alpha = 0;
|
|
|
|
|
|
|
|
console->setFontSize(6);
|
|
}
|
|
addRenderObject(console, LR_DEBUG_TEXT);
|
|
#else
|
|
debugLog("NOT creating console (disabled in this build)");
|
|
#endif
|
|
|
|
debugLog("1");
|
|
|
|
if (isDeveloperKeys())
|
|
{
|
|
|
|
cmDebug = new DebugFont();
|
|
{
|
|
|
|
|
|
cmDebug->position = Vector(20 - virtualOffX,50);
|
|
cmDebug->followCamera = 1;
|
|
cmDebug->alpha = 0;
|
|
|
|
|
|
|
|
cmDebug->setFontSize(6);
|
|
}
|
|
addRenderObject(cmDebug, LR_DEBUG_TEXT);
|
|
}
|
|
|
|
debugLog("2");
|
|
|
|
versionLabel = new BitmapText(&smallFont);
|
|
{
|
|
setVersionLabelText();
|
|
|
|
versionLabel->followCamera = 1;
|
|
versionLabel->setAlign(ALIGN_LEFT);
|
|
versionLabel->scale = Vector(0.7, 0.7);
|
|
versionLabel->alphaMod = 0.75;
|
|
versionLabel->alpha = 0;
|
|
}
|
|
addRenderObject(versionLabel, LR_REGISTER_TEXT);
|
|
|
|
|
|
subbox = new Quad();
|
|
subbox->position = Vector(400,580);
|
|
subbox->alpha = 0;
|
|
subbox->alphaMod = 0.7;
|
|
subbox->followCamera = 1;
|
|
subbox->autoWidth = AUTO_VIRTUALWIDTH;
|
|
subbox->setHeight(40);
|
|
subbox->color = 0;
|
|
addRenderObject(subbox, LR_SUBTITLES);
|
|
|
|
subtext = new BitmapText(&dsq->subsFont);
|
|
|
|
subtext->position = Vector(400,570);
|
|
subtext->followCamera = 1;
|
|
subtext->alpha = 0;
|
|
subtext->setFontSize(14);
|
|
subtext->setWidth(800);
|
|
subtext->setAlign(ALIGN_CENTER);
|
|
|
|
addRenderObject(subtext, LR_SUBTITLES);
|
|
|
|
#ifdef BBGE_BUILD_ACHIEVEMENTS_INTERNAL
|
|
achievement_box = new Quad();
|
|
achievement_box->position = Vector(800,0);
|
|
achievement_box->alpha = 0;
|
|
achievement_box->alphaMod = 0.7;
|
|
achievement_box->followCamera = 1;
|
|
achievement_box->setWidthHeight(400, 87);
|
|
achievement_box->color = 0;
|
|
addRenderObject(achievement_box, LR_SUBTITLES);
|
|
|
|
achievement_text = new BitmapText(&dsq->subsFont);
|
|
achievement_text->position = Vector(603, 5);
|
|
achievement_text->followCamera = 1;
|
|
achievement_text->alpha = 0;
|
|
achievement_text->setFontSize(6);
|
|
achievement_text->setWidth(280);
|
|
achievement_text->setAlign(ALIGN_LEFT);
|
|
addRenderObject(achievement_text, LR_SUBTITLES);
|
|
#endif
|
|
|
|
cutscene_bg = new Quad();
|
|
cutscene_bg->autoWidth = AUTO_VIRTUALWIDTH;
|
|
cutscene_bg->color = 0;
|
|
cutscene_bg->alphaMod = 0.75;
|
|
cutscene_bg->setWidthHeight(0, 80);
|
|
cutscene_bg->position = Vector(400,300);
|
|
cutscene_bg->alpha.x = 0;
|
|
cutscene_bg->followCamera = 1;
|
|
addRenderObject(cutscene_bg, LR_SUBTITLES);
|
|
|
|
cutscene_text = new BitmapText(&dsq->font);
|
|
cutscene_text->setText(dsq->continuity.stringBank.get(2004));
|
|
cutscene_text->position = Vector(400,300-16);
|
|
cutscene_text->alpha.x = 0;
|
|
cutscene_text->followCamera = 1;
|
|
addRenderObject(cutscene_text, LR_SUBTITLES);
|
|
|
|
cutscene_text2 = new BitmapText(&dsq->smallFont);
|
|
cutscene_text2->setText(dsq->continuity.stringBank.get(2005));
|
|
cutscene_text2->position = Vector(400,300+10);
|
|
cutscene_text2->alpha.x = 0;
|
|
cutscene_text2->followCamera = 1;
|
|
addRenderObject(cutscene_text2, LR_SUBTITLES);
|
|
|
|
debugLog("3");
|
|
|
|
loadBit(LOAD_GRAPHICS1);
|
|
|
|
debugLog("4");
|
|
|
|
cursorGlow = new Quad;
|
|
{
|
|
cursorGlow->setTexture("glow");
|
|
cursorGlow->setWidthHeight(48, 48);
|
|
cursorGlow->alpha = 0;
|
|
cursorGlow->setBlendType(RenderObject::BLEND_ADD);
|
|
}
|
|
cursor->addChild(cursorGlow, PM_NONE, RBP_OFF);
|
|
addRenderObject(cursorGlow, LR_CURSOR);
|
|
|
|
cursorBlinker = new Quad;
|
|
{
|
|
cursorBlinker->setTexture("cursor");
|
|
cursorBlinker->scale = Vector(1.5, 1.5);
|
|
cursorBlinker->scale.interpolateTo(Vector(2,2), 0.2, -1, 1, 1);
|
|
cursorBlinker->alpha = 0;
|
|
cursorBlinker->alphaMod = 0.5;
|
|
}
|
|
cursor->addChild(cursorBlinker, PM_NONE, RBP_OFF);
|
|
addRenderObject(cursorBlinker, LR_CURSOR);
|
|
|
|
debugLog("5");
|
|
|
|
recreateBlackBars();
|
|
|
|
debugLog("6");
|
|
|
|
overlay = new Quad;
|
|
{
|
|
overlay->position = Vector(400,300,3);
|
|
overlay->color = 0;
|
|
overlay->autoWidth = AUTO_VIRTUALWIDTH;
|
|
overlay->autoHeight = AUTO_VIRTUALHEIGHT;
|
|
overlay->alpha = 0;
|
|
overlay->followCamera = 1;
|
|
}
|
|
addRenderObject(overlay, LR_OVERLAY);
|
|
|
|
overlay2 = new Quad;
|
|
{
|
|
overlay2->position = Vector(400,300);
|
|
overlay2->color = 0;
|
|
overlay2->autoWidth = AUTO_VIRTUALWIDTH;
|
|
overlay2->autoHeight = AUTO_VIRTUALHEIGHT;
|
|
overlay2->alpha = 0;
|
|
overlay2->followCamera = 1;
|
|
}
|
|
addRenderObject(overlay2, LR_OVERLAY);
|
|
|
|
overlay3 = new Quad;
|
|
{
|
|
overlay3->position = Vector(400,300);
|
|
overlay3->color = 0;
|
|
overlay3->autoWidth = AUTO_VIRTUALWIDTH;
|
|
overlay3->autoHeight = AUTO_VIRTUALHEIGHT;
|
|
overlay3->alpha = 0;
|
|
overlay3->followCamera = 1;
|
|
}
|
|
addRenderObject(overlay3, LR_OVERLAY);
|
|
|
|
overlayRed = new Quad;
|
|
{
|
|
overlayRed->position = Vector(400,300);
|
|
overlayRed->color = Vector(1,0,0);
|
|
overlayRed->alphaMod = 0.5;
|
|
overlayRed->autoWidth = AUTO_VIRTUALWIDTH;
|
|
overlayRed->autoHeight = AUTO_VIRTUALHEIGHT;
|
|
overlayRed->alpha = 0;
|
|
overlayRed->followCamera = 1;
|
|
}
|
|
addRenderObject(overlayRed, LR_OVERLAY);
|
|
|
|
sceneColorOverlay = new Quad;
|
|
{
|
|
sceneColorOverlay->position = Vector(400,300);
|
|
sceneColorOverlay->color = Vector(1,1,1);
|
|
sceneColorOverlay->alpha = 1;
|
|
sceneColorOverlay->setBlendType(RenderObject::BLEND_MULT);
|
|
sceneColorOverlay->autoWidth = AUTO_VIRTUALWIDTH;
|
|
sceneColorOverlay->autoHeight = AUTO_VIRTUALHEIGHT;
|
|
sceneColorOverlay->followCamera = 1;
|
|
}
|
|
addRenderObject(sceneColorOverlay, LR_SCENE_COLOR);
|
|
|
|
tfader = new Quad;
|
|
{
|
|
tfader->position = Vector(400,300,3);
|
|
tfader->color = 0;
|
|
tfader->autoWidth = AUTO_VIRTUALWIDTH;
|
|
tfader->autoHeight = AUTO_VIRTUALHEIGHT;
|
|
tfader->alpha = 0;
|
|
tfader->followCamera = 1;
|
|
}
|
|
addRenderObject(tfader, LR_TRANSITION);
|
|
|
|
screenTransition = new AquariaScreenTransition();
|
|
{
|
|
screenTransition->position = Vector(400,300);
|
|
}
|
|
addRenderObject(screenTransition, LR_TRANSITION);
|
|
|
|
debugLog("8");
|
|
|
|
loadBit(LOAD_GRAPHICS2);
|
|
|
|
debugLog("9");
|
|
|
|
fpsText = new DebugFont;
|
|
{
|
|
fpsText->color = Vector(1,1,1);
|
|
fpsText->setFontSize(6);
|
|
|
|
fpsText->position = Vector(10 - virtualOffX,580);
|
|
fpsText->position.z = 5;
|
|
|
|
|
|
fpsText->setText("FPS");
|
|
fpsText->alpha= 0;
|
|
|
|
}
|
|
addRenderObject(fpsText, LR_DEBUG_TEXT);
|
|
|
|
precacher.precacheList("data/precache.txt", loadBitForTexPrecache);
|
|
|
|
setTexturePointers();
|
|
|
|
loadBit(LOAD_TEXTURES);
|
|
|
|
resetLayerPasses();
|
|
|
|
renderObjectLayerOrder[LR_BACKGROUND_ELEMENTS1] = LR_ELEMENTS1;
|
|
renderObjectLayerOrder[LR_BACKGROUND_ELEMENTS2] = LR_ELEMENTS2;
|
|
renderObjectLayerOrder[LR_BACKGROUND_ELEMENTS3] = LR_ELEMENTS3;
|
|
|
|
renderObjectLayerOrder[LR_FOREGROUND_ELEMENTS1] = LR_ELEMENTS8;
|
|
renderObjectLayerOrder[LR_FOREGROUND_ELEMENTS2] = LR_ELEMENTS9;
|
|
|
|
renderObjectLayerOrder[LR_BACKDROP_ELEMENTS1] = LR_ELEMENTS10;
|
|
renderObjectLayerOrder[LR_BACKDROP_ELEMENTS2] = LR_ELEMENTS11;
|
|
renderObjectLayerOrder[LR_BACKDROP_ELEMENTS3] = LR_ELEMENTS12;
|
|
|
|
renderObjectLayerOrder[LR_ENTITIES_MINUS4_PLACEHOLDER] = LR_ENTITIES_MINUS4;
|
|
renderObjectLayerOrder[LR_ENTITIES_MINUS3_PLACEHOLDER] = LR_ENTITIES_MINUS3;
|
|
renderObjectLayerOrder[LR_ENTITIES_MINUS2_PLACEHOLDER] = LR_ENTITIES_MINUS2;
|
|
|
|
renderObjectLayerOrder[LR_DARK_LAYER] = LR_ELEMENTS13;
|
|
|
|
renderObjectLayerOrder[LR_BACKDROP_ELEMENTS4] = LR_ELEMENTS14;
|
|
renderObjectLayerOrder[LR_BACKDROP_ELEMENTS5] = LR_ELEMENTS15;
|
|
renderObjectLayerOrder[LR_BACKDROP_ELEMENTS6] = LR_ELEMENTS16;
|
|
|
|
renderObjectLayerOrder[LR_ELEMENTS1] = -1;
|
|
renderObjectLayerOrder[LR_ELEMENTS2] = -1;
|
|
renderObjectLayerOrder[LR_ELEMENTS3] = -1;
|
|
|
|
renderObjectLayerOrder[LR_ELEMENTS8] = -1;
|
|
renderObjectLayerOrder[LR_ELEMENTS9] = -1;
|
|
|
|
renderObjectLayerOrder[LR_ELEMENTS10] = -1;
|
|
renderObjectLayerOrder[LR_ELEMENTS11] = -1;
|
|
renderObjectLayerOrder[LR_ELEMENTS12] = -1;
|
|
|
|
renderObjectLayerOrder[LR_ELEMENTS14] = -1;
|
|
renderObjectLayerOrder[LR_ELEMENTS15] = -1;
|
|
renderObjectLayerOrder[LR_ELEMENTS16] = -1;
|
|
|
|
renderObjectLayerOrder[LR_ELEMENTS13] = -1;
|
|
|
|
renderObjectLayerOrder[LR_ENTITIES_MINUS4] = -1;
|
|
renderObjectLayerOrder[LR_ENTITIES_MINUS3] = -1;
|
|
renderObjectLayerOrder[LR_ENTITIES_MINUS2] = -1;
|
|
|
|
|
|
|
|
setMousePosition(core->center);
|
|
|
|
|
|
|
|
loadBit(LOAD_FINISHED);
|
|
|
|
|
|
|
|
// Don't do transitions for a faster start up in dev mode
|
|
if (!isDeveloperKeys())
|
|
{
|
|
float trans = 0.5;
|
|
overlay->alpha.interpolateTo(1, trans);
|
|
core->run(trans);
|
|
}
|
|
|
|
removeRenderObject(loading);
|
|
loading = 0;
|
|
removeRenderObject(sidel);
|
|
removeRenderObject(sider);
|
|
removeRenderObject(label);
|
|
removeRenderObject(tube);
|
|
|
|
if (useFrameBuffer && core->frameBuffer.isInited())
|
|
core->afterEffectManager = new AfterEffectManager(vars->afterEffectsXDivs,vars->afterEffectsYDivs);
|
|
else
|
|
core->afterEffectManager = 0;
|
|
|
|
bindInput();
|
|
setInputGrab(user.system.grabInput);
|
|
|
|
// Go directly to the title in dev mode
|
|
if(isDeveloperKeys())
|
|
title();
|
|
else
|
|
enqueueJumpState("BitBlotLogo");
|
|
}
|
|
|
|
void DSQ::recreateBlackBars()
|
|
{
|
|
bool useOldAlpha=false;
|
|
InterpolatedVector abar_left, abar_right, abarFade_left, abarFade_right;
|
|
|
|
if (bar_left)
|
|
{
|
|
useOldAlpha = true;
|
|
abar_left = bar_left->alpha;
|
|
removeRenderObject(bar_left);
|
|
}
|
|
if (bar_right)
|
|
{
|
|
abar_right = bar_right->alpha;
|
|
removeRenderObject(bar_right);
|
|
}
|
|
if (barFade_left)
|
|
{
|
|
abarFade_left = barFade_left->alpha;
|
|
removeRenderObject(barFade_left);
|
|
}
|
|
if (barFade_right)
|
|
{
|
|
abarFade_right = barFade_right->alpha;
|
|
removeRenderObject(barFade_right);
|
|
}
|
|
if (bar_up)
|
|
removeRenderObject(bar_up);
|
|
if (bar_down)
|
|
removeRenderObject(bar_down);
|
|
|
|
bar_left = bar_right = bar_up = bar_down = barFade_left = barFade_right = 0;
|
|
|
|
if (getVirtualWidth() > 800)
|
|
{
|
|
int sz2 = (core->getVirtualWidth() - baseVirtualWidth)/2.0f;
|
|
|
|
bar_left = new Quad;
|
|
{
|
|
bar_left->position = Vector(-sz2, 300);
|
|
bar_left->setWidthHeight(sz2*2, 600);
|
|
bar_left->color = 0;
|
|
bar_left->followCamera = 1;
|
|
bar_left->cull = 0;
|
|
}
|
|
addRenderObject(bar_left, LR_BLACKBARS);
|
|
|
|
bar_right = new Quad;
|
|
{
|
|
bar_right->position = Vector(800 + sz2, 300);
|
|
bar_right->setWidthHeight(sz2*2, 600);
|
|
bar_right->color = 0;
|
|
bar_right->followCamera = 1;
|
|
bar_right->cull = 0;
|
|
}
|
|
addRenderObject(bar_right, LR_BLACKBARS);
|
|
|
|
barFade_left = new Quad;
|
|
{
|
|
barFade_left->setTexture("gui/edge");
|
|
barFade_left->position = Vector(16, 300);
|
|
barFade_left->setWidthHeight(34, 620);
|
|
barFade_left->color = 0;
|
|
barFade_left->followCamera = 1;
|
|
barFade_left->cull = 0;
|
|
}
|
|
addRenderObject(barFade_left, LR_BLACKBARS);
|
|
|
|
barFade_right = new Quad;
|
|
{
|
|
barFade_right->setTexture("gui/edge");
|
|
barFade_right->flipHorizontal();
|
|
barFade_right->position = Vector(800-16, 300);
|
|
barFade_right->setWidthHeight(34, 620);
|
|
barFade_right->color = 0;
|
|
barFade_right->followCamera = 1;
|
|
barFade_right->cull = 0;
|
|
}
|
|
addRenderObject(barFade_right, LR_BLACKBARS);
|
|
|
|
if (useOldAlpha)
|
|
{
|
|
bar_left->alpha = abar_left;
|
|
bar_right->alpha = abar_right;
|
|
barFade_left->alpha = abarFade_left;
|
|
barFade_right->alpha = abarFade_right;
|
|
}
|
|
else
|
|
{
|
|
bar_right->alpha = 0;
|
|
bar_left->alpha = 0;
|
|
barFade_right->alpha = 0;
|
|
barFade_left->alpha = 0;
|
|
}
|
|
}
|
|
|
|
// top and bottom bars are not toggle-able, they will always be on if they are needed
|
|
if (getVirtualHeight() > 600)
|
|
{
|
|
int sz2 = (core->getVirtualHeight() - baseVirtualHeight)/2.0f;
|
|
bar_up = new Quad;
|
|
{
|
|
bar_up->position = Vector(400, -sz2);
|
|
bar_up->setWidthHeight(800, sz2*2);
|
|
bar_up->color = 0;
|
|
bar_up->followCamera = 1;
|
|
bar_up->cull = 0;
|
|
}
|
|
addRenderObject(bar_up, LR_BLACKBARS);
|
|
|
|
bar_down = new Quad;
|
|
{
|
|
bar_down->position = Vector(400, 600 + sz2);
|
|
bar_down->setWidthHeight(800, sz2*2);
|
|
bar_down->color = 0;
|
|
bar_down->followCamera = 1;
|
|
bar_down->cull = 0;
|
|
}
|
|
addRenderObject(bar_down, LR_BLACKBARS);
|
|
}
|
|
}
|
|
|
|
void DSQ::setBlackBarsColor(Vector color)
|
|
{
|
|
if (bar_left && bar_right)
|
|
{
|
|
bar_left->color = bar_right->color = barFade_left->color = barFade_right->color = color;
|
|
}
|
|
}
|
|
|
|
void DSQ::toggleBlackBars(bool on, float t)
|
|
{
|
|
if (bar_left && bar_right)
|
|
{
|
|
if (on)
|
|
{
|
|
bar_left->alpha = bar_right->alpha = 1;
|
|
barFade_right->alpha = barFade_left->alpha = 1;
|
|
}
|
|
else
|
|
{
|
|
if (t != 0)
|
|
{
|
|
bar_left->alpha.interpolateTo(0, t);
|
|
bar_right->alpha.interpolateTo(0, t);
|
|
barFade_left->alpha.interpolateTo(0, t);
|
|
barFade_right->alpha.interpolateTo(0, t);
|
|
}
|
|
else
|
|
{
|
|
bar_left->alpha = bar_right->alpha = 0;
|
|
barFade_right->alpha = barFade_left->alpha = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int DSQ::getEntityLayerToLayer(int lcode)
|
|
{
|
|
if (lcode == -4)
|
|
return LR_ENTITIES_MINUS4; // in front of elements11
|
|
else if (lcode == -3)
|
|
return LR_ENTITIES_MINUS3; // in front of elements2
|
|
else if (lcode == -2)
|
|
return LR_ENTITIES_MINUS2; // in front of elements3
|
|
else if (lcode == -1)
|
|
return LR_ENTITIES0;
|
|
else if (lcode == -100)
|
|
return LR_ENTITIES00;
|
|
else if (lcode == 0)
|
|
return LR_ENTITIES;
|
|
else if (lcode == 1)
|
|
return LR_ENTITIES2;
|
|
else if (lcode == 2)
|
|
return LR_DARK_LAYER;
|
|
std::ostringstream os;
|
|
os << "Invalid entity layer code: " << lcode;
|
|
debugLog(os.str());
|
|
return 0;
|
|
}
|
|
|
|
void DSQ::setStory()
|
|
{
|
|
std::string flagString = getUserInputString(dsq->continuity.stringBank.get(2014), "0");
|
|
int flag = 0;
|
|
std::istringstream is(flagString);
|
|
is >> flag;
|
|
|
|
core->run(0.2);
|
|
std::ostringstream os;
|
|
os << dsq->continuity.getFlag(flag);
|
|
flagString = getUserInputString(dsq->continuity.stringBank.get(2015), os.str());
|
|
int value = 0;
|
|
std::istringstream is2(flagString);
|
|
is2 >> value;
|
|
dsq->continuity.setFlag(flag, value);
|
|
}
|
|
|
|
Vector DSQ::getNoteVector(int note, float mag)
|
|
{
|
|
Vector vec;
|
|
switch(note)
|
|
{
|
|
case 0:
|
|
vec = Vector(0,1);
|
|
break;
|
|
case 1:
|
|
vec = Vector(0.5, 0.5);
|
|
break;
|
|
case 2:
|
|
vec = Vector(1, 0);
|
|
break;
|
|
case 3:
|
|
vec = Vector(0.5, -0.5);
|
|
break;
|
|
case 4:
|
|
vec = Vector(0, -1);
|
|
break;
|
|
case 5:
|
|
vec = Vector(-0.5, -0.5);
|
|
break;
|
|
case 6:
|
|
vec = Vector(-1, 0);
|
|
break;
|
|
case 7:
|
|
vec = Vector(-0.5, 0.5);
|
|
break;
|
|
}
|
|
return vec*mag;
|
|
}
|
|
|
|
int DSQ::getRandNote()
|
|
{
|
|
static int lastRand = -1;
|
|
|
|
int r = rand()%8;
|
|
|
|
int c = 0;
|
|
while (r == lastRand)
|
|
{
|
|
r = rand()%8;
|
|
c++;
|
|
if (c > 8) break;
|
|
}
|
|
lastRand = r;
|
|
|
|
|
|
return r;
|
|
}
|
|
|
|
Vector DSQ::getNoteColor(int note)
|
|
{
|
|
Vector noteColor;
|
|
switch(note)
|
|
{
|
|
case 0:
|
|
// light green
|
|
noteColor = Vector(0.5, 1, 0.5);
|
|
break;
|
|
case 1:
|
|
// blue/green
|
|
noteColor = Vector(0.5, 1, 0.75);
|
|
break;
|
|
case 2:
|
|
// blue
|
|
noteColor = Vector(0.5, 0.5, 1);
|
|
break;
|
|
case 3:
|
|
// purple
|
|
noteColor = Vector(1, 0.5, 1);
|
|
break;
|
|
case 4:
|
|
// red
|
|
noteColor = Vector(1, 0.5, 0.5);
|
|
break;
|
|
case 5:
|
|
// red/orange
|
|
noteColor = Vector(1, 0.6, 0.5);
|
|
break;
|
|
case 6:
|
|
// orange
|
|
noteColor = Vector(1, 0.75, 0.5);
|
|
break;
|
|
case 7:
|
|
// orange
|
|
noteColor = Vector(1, 1, 0.5);
|
|
break;
|
|
}
|
|
return noteColor;
|
|
}
|
|
|
|
void DSQ::toggleVersionLabel(bool on)
|
|
{
|
|
float a = 0;
|
|
if (on)
|
|
a = 1;
|
|
|
|
versionLabel->alpha.interpolateTo(a, 1);
|
|
}
|
|
|
|
void DSQ::setInputMode(InputMode mode)
|
|
{
|
|
inputMode = mode;
|
|
switch(inputMode)
|
|
{
|
|
case INPUT_JOYSTICK:
|
|
core->joystickAsMouse = true;
|
|
updateCursorFromMouse = false;
|
|
break;
|
|
case INPUT_MOUSE:
|
|
setMousePosition(core->mouse.position);
|
|
core->joystickAsMouse = false;
|
|
updateCursorFromMouse = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DSQ::toggleRenderCollisionShapes()
|
|
{
|
|
if (core->getCtrlState() && core->getShiftState())
|
|
RenderObject::renderCollisionShape = !RenderObject::renderCollisionShape;
|
|
}
|
|
|
|
void DSQ::unloadDevice()
|
|
{
|
|
destroyFonts();
|
|
|
|
Core::unloadDevice();
|
|
darkLayer.unloadDevice();
|
|
}
|
|
|
|
void DSQ::reloadDevice()
|
|
{
|
|
loadFonts();
|
|
|
|
Core::reloadDevice();
|
|
darkLayer.reloadDevice();
|
|
|
|
recreateBlackBars();
|
|
}
|
|
|
|
#ifdef AQUARIA_BUILD_CONSOLE
|
|
void DSQ::toggleConsole()
|
|
{
|
|
if (console && isDeveloperKeys())
|
|
{
|
|
if (console->alpha == 0)
|
|
{
|
|
console->alpha.interpolateTo(1, 0.1);
|
|
cmDebug->alpha.interpolateTo(1, 0.1);
|
|
fpsText->alpha.interpolateTo(1, 0.1);
|
|
RenderObject::renderPaths = true;
|
|
}
|
|
else if (console->alpha == 1)
|
|
{
|
|
console->alpha.interpolateTo(0, 0.1);
|
|
cmDebug->alpha.interpolateTo(0, 0.1);
|
|
fpsText->alpha.interpolateTo(0, 0.1);
|
|
RenderObject::renderPaths = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DSQ::debugLog(const std::string &s)
|
|
{
|
|
consoleLines.push_back(s);
|
|
if (consoleLines.size() > MAX_CONSOLELINES)
|
|
{
|
|
|
|
for (int i = 0; i < consoleLines.size()-1; i++)
|
|
{
|
|
consoleLines[i] = consoleLines[i+1];
|
|
}
|
|
consoleLines.resize(MAX_CONSOLELINES);
|
|
}
|
|
if (console)
|
|
{
|
|
std::string text;
|
|
for (int i = 0; i < consoleLines.size(); i++)
|
|
{
|
|
text += consoleLines[i] + '\n';
|
|
}
|
|
console->setText(text);
|
|
}
|
|
Core::debugLog(s);
|
|
}
|
|
#endif // AQUARIA_BUILD_CONSOLE
|
|
|
|
int DSQ::getEntityTypeIndexByName(std::string s)
|
|
{
|
|
for (int i = 0; i < game->entityTypeList.size(); i++)
|
|
{
|
|
EntityClass *t = &game->entityTypeList[i];
|
|
if (t->name == s)
|
|
return t->idx;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void DSQ::loadModsCallback(const std::string &filename, void *param)
|
|
{
|
|
|
|
int pos = filename.find_last_of('/')+1;
|
|
int pos2 = filename.find_last_of('.');
|
|
std::string name = filename.substr(pos, pos2-pos);
|
|
ModEntry m;
|
|
m.path = name;
|
|
m.id = dsq->modEntries.size();
|
|
|
|
XMLDocument d;
|
|
if(!Mod::loadModXML(&d, name))
|
|
{
|
|
std::ostringstream os;
|
|
os << "Failed to load mod xml: " << filename << " -- Error: " << d.GetErrorStr1();
|
|
dsq->debugLog(os.str());
|
|
return;
|
|
}
|
|
|
|
m.type = Mod::getTypeFromXML(d.FirstChildElement("AquariaMod"));
|
|
|
|
dsq->modEntries.push_back(m);
|
|
|
|
std::ostringstream ss;
|
|
ss << "Loaded ModEntry [" << m.path << "] -> " << m.id << " | type " << m.type;
|
|
|
|
dsq->debugLog(ss.str());
|
|
}
|
|
|
|
void DSQ::loadModPackagesCallback(const std::string &filename, void *param)
|
|
{
|
|
bool ok = dsq->mountModPackage(filename);
|
|
|
|
std::ostringstream ss;
|
|
ss << "Mount Mod Package '" << filename << "' : " << (ok ? "ok" : "FAIL");
|
|
dsq->debugLog(ss.str());
|
|
|
|
// they will be enumerated by the following loadModsCallback round
|
|
}
|
|
|
|
void DSQ::startSelectedMod()
|
|
{
|
|
ModEntry *e = getSelectedModEntry();
|
|
if (e)
|
|
{
|
|
clearModSelector();
|
|
mod.load(e->path);
|
|
mod.start();
|
|
|
|
|
|
}
|
|
}
|
|
|
|
ModEntry* DSQ::getSelectedModEntry()
|
|
{
|
|
if (!modEntries.empty() && selectedMod >= 0 && selectedMod < modEntries.size())
|
|
return &modEntries[selectedMod];
|
|
return 0;
|
|
}
|
|
|
|
void DSQ::loadMods()
|
|
{
|
|
modEntries.clear();
|
|
|
|
std::string modpath = mod.getBaseModPath();
|
|
debugLog("loadMods: " + modpath);
|
|
|
|
#ifdef BBGE_BUILD_VFS
|
|
// first load the packages, then enumerate XMLs
|
|
forEachFile(modpath, ".aqmod", loadModPackagesCallback);
|
|
#endif
|
|
|
|
forEachFile(modpath, ".xml", loadModsCallback);
|
|
selectedMod = 0;
|
|
|
|
std::ostringstream os;
|
|
os << "loadMods done, " << modEntries.size() << " entries";
|
|
debugLog(os.str());
|
|
}
|
|
|
|
void DSQ::applyPatches()
|
|
{
|
|
#ifndef AQUARIA_DEMO
|
|
#ifdef BBGE_BUILD_VFS
|
|
|
|
// This is to allow files in patches to override files in mods on non-win32 systems
|
|
vfs.Mount(mod.getBaseModPath().c_str(), "_mods");
|
|
|
|
loadMods();
|
|
|
|
for (std::vector<std::string>::iterator it = activePatches.begin(); it != activePatches.end(); ++it)
|
|
for(int i = 0; i < modEntries.size(); ++i)
|
|
if(modEntries[i].type == MODTYPE_PATCH)
|
|
if(!nocasecmp(modEntries[i].path.c_str(), it->c_str()))
|
|
_applyPatch(modEntries[i].path);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifdef BBGE_BUILD_VFS
|
|
|
|
static void refr_pushback(ttvfs::DirBase *vd, void *user)
|
|
{
|
|
std::list<std::string> *li = (std::list<std::string>*)user;
|
|
li->push_back(vd->fullname());
|
|
}
|
|
|
|
static void refr_insert(VFILE *vf, void *user)
|
|
{
|
|
// texture names are like: "naija/naija2-frontleg3" - no .png extension, and no gfx/ path
|
|
std::vector<std::string>*files = (std::vector<std::string>*)user;
|
|
std::string t = vf->fullname();
|
|
size_t dotpos = t.rfind('.');
|
|
size_t pathstart = t.find("gfx/");
|
|
if(dotpos == std::string::npos || pathstart == std::string::npos || dotpos < pathstart)
|
|
return; // whoops
|
|
|
|
files->push_back(t.substr(pathstart + 4, dotpos - (pathstart + 4)));
|
|
}
|
|
|
|
|
|
// this thing is rather heuristic... but works for normal mod paths
|
|
// there is apparently nothing else except Textures that is a subclass of Resource,
|
|
// thus directly using "gfx" subdir should be fine...
|
|
void DSQ::refreshResourcesForPatch(const std::string& name)
|
|
{
|
|
std::list<std::string> left;
|
|
std::vector<std::string> files;
|
|
left.push_back(mod.getBaseModPath() + name + "/gfx");
|
|
ttvfs::DirView view;
|
|
do
|
|
{
|
|
std::string dirname = left.front();
|
|
left.pop_front();
|
|
if(vfs.FillDirView(dirname.c_str(), view))
|
|
{
|
|
view.forEachDir(refr_pushback, &left);
|
|
view.forEachFile(refr_insert, &files);
|
|
}
|
|
}
|
|
while(left.size());
|
|
|
|
std::sort(files.begin(), files.end());
|
|
std::vector<std::string>::iterator newend = unique(files.begin(), files.end());
|
|
files.erase(newend, files.end());
|
|
|
|
std::ostringstream os;
|
|
os << "refreshResourcesForPatch - " << files.size() << " to refresh";
|
|
debugLog(os.str());
|
|
|
|
int reloaded = 0;
|
|
if(files.size())
|
|
{
|
|
for(int i = 0; i < dsq->resources.size(); ++i)
|
|
{
|
|
Texture *r = dsq->resources[i];
|
|
bool found = false;
|
|
for(size_t i = 0; i < files.size(); ++i)
|
|
if(files[i] == r->name)
|
|
{
|
|
++reloaded;
|
|
r->reload();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
os.str("");
|
|
os << "refreshResourcesForPatch - " << reloaded << " textures reloaded";
|
|
debugLog(os.str());
|
|
}
|
|
#else
|
|
void DSQ::refreshResourcesForPatch(const std::string& name) {}
|
|
#endif
|
|
|
|
void DSQ::activatePatch(const std::string& name)
|
|
{
|
|
_applyPatch(name);
|
|
activePatches.push_back(name);
|
|
}
|
|
|
|
void DSQ::_applyPatch(const std::string& name)
|
|
{
|
|
#ifdef BBGE_BUILD_VFS
|
|
#ifdef AQUARIA_DEMO
|
|
return;
|
|
#endif
|
|
|
|
std::string src = mod.getBaseModPath();
|
|
src += name;
|
|
debugLog("Apply patch: " + src);
|
|
vfs.Mount(src.c_str(), "");
|
|
refreshResourcesForPatch(name);
|
|
#endif
|
|
}
|
|
|
|
void DSQ::disablePatch(const std::string& name)
|
|
{
|
|
#ifdef BBGE_BUILD_VFS
|
|
std::string src = mod.getBaseModPath();
|
|
src += name;
|
|
debugLog("Unapply patch: " + src);
|
|
vfs.Unmount(src.c_str(), "");
|
|
|
|
// preserve order
|
|
std::vector<std::string>::iterator it = std::remove(activePatches.begin(), activePatches.end(), name);
|
|
activePatches.erase(it, activePatches.end());
|
|
|
|
refreshResourcesForPatch(name);
|
|
#endif
|
|
}
|
|
|
|
bool DSQ::isPatchActive(const std::string& name)
|
|
{
|
|
for(size_t i = 0; i < activePatches.size(); ++i)
|
|
if(activePatches[i] == name)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
void DSQ::playMenuSelectSfx()
|
|
{
|
|
core->sound->playSfx("MenuSelect");
|
|
}
|
|
|
|
void DSQ::playPositionalSfx(const std::string &name, const Vector &position, float f, float fadeOut, SoundHolder *holder)
|
|
{
|
|
PlaySfx sfx;
|
|
sfx.freq = f;
|
|
sfx.name = name;
|
|
sfx.relative = false;
|
|
sfx.positional = true;
|
|
sfx.x = position.x;
|
|
sfx.y = position.y;
|
|
|
|
void *c = sound->playSfx(sfx);
|
|
|
|
if (fadeOut != 0)
|
|
sound->fadeSfx(c, SFT_OUT, fadeOut);
|
|
|
|
if (holder)
|
|
holder->linkSound(c);
|
|
}
|
|
|
|
void DSQ::shutdown()
|
|
{
|
|
mod.stop();
|
|
|
|
Network::shutdown();
|
|
|
|
scriptInterface.shutdown();
|
|
precacher.clean();
|
|
|
|
|
|
core->particleManager->clearParticleBank();
|
|
Shot::clearShotBank();
|
|
SkeletalSprite::clearCache();
|
|
|
|
|
|
cursor->setTexturePointer(0);
|
|
|
|
UNREFTEX(texCursor);
|
|
UNREFTEX(texCursorSwim);
|
|
UNREFTEX(texCursorBurst);
|
|
UNREFTEX(texCursorSing);
|
|
UNREFTEX(texCursorLook);
|
|
|
|
#ifdef AQUARIA_BUILD_CONSOLE
|
|
removeRenderObject(console);
|
|
console = 0;
|
|
#endif
|
|
removeRenderObject(cmDebug);
|
|
cmDebug = 0;
|
|
removeRenderObject(subtext);
|
|
subtext = 0;
|
|
removeRenderObject(subbox);
|
|
subbox = 0;
|
|
|
|
#ifdef BBGE_BUILD_ACHIEVEMENTS_INTERNAL
|
|
removeRenderObject(achievement_text);
|
|
achievement_text = 0;
|
|
removeRenderObject(achievement_box);
|
|
achievement_box = 0;
|
|
#endif
|
|
|
|
removeRenderObject(cursor);
|
|
removeRenderObject(cursorGlow); // is this necessary? probably
|
|
removeRenderObject(cursorBlinker);
|
|
removeRenderObject(overlay);
|
|
removeRenderObject(overlay2);
|
|
removeRenderObject(overlay3);
|
|
removeRenderObject(overlayRed);
|
|
removeRenderObject(tfader);
|
|
|
|
removeRenderObject(fpsText);
|
|
|
|
if (bar_left)
|
|
removeRenderObject(bar_left);
|
|
if (bar_right)
|
|
removeRenderObject(bar_right);
|
|
if (barFade_left)
|
|
removeRenderObject(barFade_left);
|
|
if (barFade_right)
|
|
removeRenderObject(barFade_right);
|
|
if (bar_up)
|
|
removeRenderObject(bar_up);
|
|
if (bar_down)
|
|
removeRenderObject(bar_down);
|
|
|
|
if (cutscene_bg)
|
|
removeRenderObject(cutscene_bg);
|
|
if (cutscene_text)
|
|
removeRenderObject(cutscene_text);
|
|
if (cutscene_text2)
|
|
removeRenderObject(cutscene_text2);
|
|
|
|
|
|
removeRenderObject(versionLabel);
|
|
versionLabel = 0;
|
|
|
|
if (screenTransition)
|
|
{
|
|
screenTransition->destroy();
|
|
removeRenderObject(screenTransition);
|
|
}
|
|
|
|
destroyFonts();
|
|
|
|
|
|
screenTransition = 0;
|
|
|
|
core->run(0.1);
|
|
overlay = 0;
|
|
overlay2 = 0;
|
|
overlay3 = 0;
|
|
cursor = 0;
|
|
tfader = 0;
|
|
|
|
continuity.shutdown();
|
|
|
|
|
|
Core::shutdown();
|
|
}
|
|
|
|
void DSQ::setTexturePointers()
|
|
{
|
|
texCursor = core->addTexture("cursor");
|
|
texCursorLook = core->addTexture("cursor-look");
|
|
texCursorBurst = core->addTexture("cursor-burst");
|
|
texCursorSwim = core->addTexture("cursor-swim");
|
|
texCursorSing = core->addTexture("cursor-sing");
|
|
|
|
if (cursor)
|
|
cursor->setTexturePointer(texCursor);
|
|
}
|
|
|
|
void DSQ::setCursor(CursorType type)
|
|
{
|
|
switch(type)
|
|
{
|
|
case CURSOR_NORMAL:
|
|
cursor->setTexturePointer(texCursor);
|
|
break;
|
|
case CURSOR_LOOK:
|
|
cursor->setTexturePointer(texCursorLook);
|
|
break;
|
|
case CURSOR_BURST:
|
|
cursor->setTexturePointer(texCursorBurst);
|
|
break;
|
|
case CURSOR_SWIM:
|
|
cursor->setTexturePointer(texCursorSwim);
|
|
break;
|
|
case CURSOR_SING:
|
|
cursor->setTexturePointer(texCursorSing);
|
|
break;
|
|
default:
|
|
cursor->setTexturePointer(texCursor);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DSQ::toggleEffects()
|
|
{
|
|
|
|
|
|
}
|
|
|
|
void DSQ::clickRingEffect(Vector pos, int type, Vector color, float ut)
|
|
{
|
|
switch(type)
|
|
{
|
|
case 0:
|
|
{
|
|
float t = 0.5;
|
|
if (ut != 0) t = ut;
|
|
Quad *q = new Quad;
|
|
q->setTexture("Particles/SoftRing");
|
|
q->setWidthHeight(100, 100);
|
|
q->scale = Vector(1,1);
|
|
q->scale.interpolateTo(Vector(5,5), t);
|
|
|
|
q->color = color;
|
|
|
|
q->setBlendType(RenderObject::BLEND_ADD);
|
|
|
|
q->alpha.ensureData();
|
|
q->alpha.data->path.addPathNode(0, 0);
|
|
q->alpha.data->path.addPathNode(0.5, 0.1);
|
|
q->alpha.data->path.addPathNode(0.5, 0.5);
|
|
q->alpha.data->path.addPathNode(0, 1);
|
|
q->alpha.startPath(t);
|
|
|
|
q->position = pos;
|
|
|
|
q->followCamera = 1;
|
|
|
|
q->setLife(t);
|
|
|
|
getTopStateData()->addRenderObject(q, LR_WORLDMAPHUD);
|
|
}
|
|
break;
|
|
case 1:
|
|
{
|
|
float t = 0.2;
|
|
if (ut != 0) t = ut;
|
|
Quad *q = new Quad;
|
|
q->setTexture("Particles/SoftRing");
|
|
q->setWidthHeight(100, 100);
|
|
q->scale = Vector(5,5);
|
|
q->scale.interpolateTo(Vector(1,1), t);
|
|
|
|
q->setBlendType(RenderObject::BLEND_ADD);
|
|
|
|
q->color = color;
|
|
|
|
q->alpha.ensureData();
|
|
q->alpha.data->path.addPathNode(0, 0);
|
|
q->alpha.data->path.addPathNode(0.5, 0.1);
|
|
q->alpha.data->path.addPathNode(0.5, 0.5);
|
|
q->alpha.data->path.addPathNode(0, 1);
|
|
q->alpha.startPath(t);
|
|
|
|
q->position = pos;
|
|
|
|
q->followCamera = 1;
|
|
|
|
q->setLife(t);
|
|
|
|
getTopStateData()->addRenderObject(q, LR_WORLDMAPHUD);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
Entity *DSQ::getEntityByName(const std::string& name)
|
|
{
|
|
Entity *e = 0;
|
|
FOR_ENTITIES(i)
|
|
{
|
|
e = (*i);
|
|
|
|
if (e->life == 1 && (nocasecmp(e->name, name)==0))
|
|
{
|
|
break;
|
|
}
|
|
e = 0;
|
|
}
|
|
return e;
|
|
}
|
|
|
|
// HACK: warning SLOW!
|
|
// really?
|
|
Entity *DSQ::getEntityByNameNoCase(std::string name)
|
|
{
|
|
stringToUpper(name);
|
|
Entity *e = 0;
|
|
FOR_ENTITIES(i)
|
|
{
|
|
e = (*i);
|
|
|
|
std::string check = e->name;
|
|
stringToUpper(check);
|
|
if (e->life == 1 && check == name)
|
|
{
|
|
break;
|
|
}
|
|
e = 0;
|
|
}
|
|
return e;
|
|
}
|
|
|
|
void DSQ::doLoadMenu()
|
|
{
|
|
doSaveSlotMenu(SSM_LOAD);
|
|
if (selectedSaveSlot != 0)
|
|
{
|
|
|
|
dsq->doScreenTrans = true;
|
|
}
|
|
else
|
|
{
|
|
|
|
clearSaveSlots(true);
|
|
}
|
|
}
|
|
|
|
void DSQ::doSavePoint(const Vector &position)
|
|
{
|
|
|
|
|
|
dsq->game->avatar->setv(EV_LOOKAT, 0);
|
|
core->sound->playSfx("MemoryCrystalActivate");
|
|
|
|
Quad *glow = new Quad;
|
|
{
|
|
glow->setTexture("save-point-glow");
|
|
glow->alpha = 0;
|
|
glow->alpha.interpolateTo(0.5, 1, 1, -1, 1);
|
|
glow->setBlendType(RenderObject::BLEND_ADD);
|
|
glow->position = position;
|
|
glow->scale = Vector(1,1)*1.25f;
|
|
glow->setLife(3);
|
|
glow->setDecayRate(1);
|
|
}
|
|
addRenderObject(glow, LR_LIGHTING);
|
|
|
|
dsq->game->avatar->idle();
|
|
dsq->game->avatar->vel=0;
|
|
dsq->game->avatar->disableInput();
|
|
dsq->game->avatar->fhTo(false);
|
|
dsq->game->avatar->position.interpolateTo(position, 1, 0, 0, 1);
|
|
dsq->game->avatar->myZoom.interpolateTo(Vector(1,1),0.5);
|
|
|
|
dsq->game->avatar->skeletalSprite.animate("save", 0, 3);
|
|
dsq->game->clearControlHint();
|
|
dsq->run(2);
|
|
dsq->game->avatar->enableInput();
|
|
dsq->game->avatar->revive();
|
|
dsq->game->togglePause(1);
|
|
dsq->doSaveSlotMenu(SSM_SAVE, position);
|
|
dsq->game->togglePause(0);
|
|
core->resetTimer();
|
|
dsq->game->avatar->setv(EV_LOOKAT, 1);
|
|
|
|
|
|
}
|
|
|
|
void DSQ::playNoEffect()
|
|
{
|
|
if (noEffectTimer <= 0)
|
|
{
|
|
sound->playSfx("noeffect", 0.9);
|
|
noEffectTimer = 0.2;
|
|
}
|
|
}
|
|
|
|
void DSQ::clearMenu(float t)
|
|
{
|
|
for (int i = 0; i < menu.size(); i++)
|
|
{
|
|
menu[i]->setLife(1);
|
|
menu[i]->setDecayRate(1/t);
|
|
menu[i]->fadeAlphaWithLife = 1;
|
|
|
|
}
|
|
menu.clear();
|
|
}
|
|
|
|
void DSQ::screenMessage(const std::string &msg)
|
|
{
|
|
debugLog(msg);
|
|
|
|
DebugFont *b = new DebugFont();
|
|
b->position = Vector(16,300);
|
|
b->setFontSize(10);
|
|
b->setText(msg);
|
|
b->alpha = 0;
|
|
b->alpha.interpolateTo(1, 0.75, 1, 1);
|
|
b->followCamera= 1;
|
|
b->setLife(2);
|
|
b->setDecayRate(1);
|
|
core->getTopStateData()->addRenderObject(b, LR_DEBUG_TEXT);
|
|
|
|
|
|
}
|
|
|
|
void DSQ::onExitSaveSlotMenu()
|
|
{
|
|
onPickedSaveSlot(0);
|
|
}
|
|
|
|
bool DSQ::onPickedSaveSlot(AquariaSaveSlot *slot)
|
|
{
|
|
if (slot == 0)
|
|
{
|
|
selectedSaveSlot = 0;
|
|
quitNestedMain();
|
|
return true;
|
|
}
|
|
else if ((saveSlotMode == SSM_LOAD && !slot->isEmpty()) || saveSlotMode == SSM_SAVE)
|
|
{
|
|
bool doit = false;
|
|
|
|
if (saveSlotMode == SSM_SAVE && !slot->isEmpty())
|
|
{
|
|
selectedSaveSlot = 0;
|
|
if (confirm("", "save"))
|
|
doit = true;
|
|
}
|
|
else
|
|
{
|
|
doit = true;
|
|
}
|
|
|
|
if (doit)
|
|
{
|
|
selectedSaveSlot = slot;
|
|
quitNestedMain();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
slot->setFocus(true);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < saveSlots.size(); i++)
|
|
{
|
|
saveSlots[i]->mbDown = false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void DSQ::nag(NagType type)
|
|
{
|
|
nagType = type;
|
|
core->enqueueJumpState("nag");
|
|
}
|
|
|
|
void DSQ::doModSelect()
|
|
{
|
|
modIsSelected = false;
|
|
|
|
dsq->loadMods();
|
|
|
|
createModSelector();
|
|
|
|
resetTimer();
|
|
|
|
inModSelector = true;
|
|
|
|
run(-1);
|
|
|
|
clearModSelector();
|
|
|
|
if (modIsSelected)
|
|
{
|
|
#ifdef AQUARIA_DEMO
|
|
nag(NAG_TOTITLE);
|
|
#else
|
|
dsq->startSelectedMod();
|
|
#endif
|
|
}
|
|
|
|
inModSelector = false;
|
|
|
|
modIsSelected = false;
|
|
|
|
resetTimer();
|
|
}
|
|
|
|
void DSQ::createModSelector()
|
|
{
|
|
blackout = new Quad;
|
|
blackout->color = 0;
|
|
blackout->autoWidth = AUTO_VIRTUALWIDTH;
|
|
blackout->autoHeight = AUTO_VIRTUALHEIGHT;
|
|
blackout->followCamera = 1;
|
|
blackout->position = Vector(400,300);
|
|
blackout->alphaMod = 0.75;
|
|
blackout->alpha = 0;
|
|
blackout->alpha.interpolateTo(1, 0.2);
|
|
addRenderObject(blackout, LR_MENU);
|
|
|
|
modSelectorScr = new ModSelectorScreen();
|
|
modSelectorScr->position = Vector(400,300);
|
|
modSelectorScr->setWidth(getVirtualWidth()); // just to be sure
|
|
modSelectorScr->setHeight(getVirtualHeight());
|
|
modSelectorScr->autoWidth = AUTO_VIRTUALWIDTH;
|
|
modSelectorScr->autoHeight = AUTO_VIRTUALHEIGHT;
|
|
modSelectorScr->init();
|
|
addRenderObject(modSelectorScr, LR_MENU);
|
|
}
|
|
|
|
bool DSQ::modIsKnown(const std::string& name)
|
|
{
|
|
std::string nlower = name;
|
|
stringToLower(nlower);
|
|
|
|
for(int i = 0; i < modEntries.size(); ++i)
|
|
{
|
|
std::string elower = modEntries[i].path;
|
|
stringToLower(elower);
|
|
if(nlower == elower)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool DSQ::mountModPackage(const std::string& pkg)
|
|
{
|
|
#ifdef BBGE_BUILD_VFS
|
|
ttvfs::DirBase *vd = vfs.GetDir(pkg.c_str());
|
|
if (!vd)
|
|
{
|
|
// Load archive only if no such directory exists already (prevent loading multiple times)
|
|
vd = vfs.AddArchive(pkg.c_str());
|
|
if(!vd)
|
|
{
|
|
debugLog("Package: Unable to load " + pkg);
|
|
return false;
|
|
}
|
|
}
|
|
vfs.Mount(pkg.c_str(), mod.getBaseModPath().c_str());
|
|
debugLog("Package: Mounted " + pkg + " as archive in _mods");
|
|
return true;
|
|
#else
|
|
debugLog("Package: Can't mount " + pkg + ", VFS support disabled");
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
#ifdef BBGE_BUILD_VFS
|
|
static void _CloseSubdirCallback(ttvfs::DirBase *vd, void*)
|
|
{
|
|
vd->close();
|
|
}
|
|
#endif
|
|
|
|
// This just closes some file handles, nothing fancy
|
|
void DSQ::unloadMods()
|
|
{
|
|
#ifdef BBGE_BUILD_VFS
|
|
ttvfs::DirView view;
|
|
if(vfs.FillDirView(mod.getBaseModPath().c_str(), view))
|
|
view.forEachDir(_CloseSubdirCallback);
|
|
#endif
|
|
}
|
|
|
|
void DSQ::applyParallaxUserSettings()
|
|
{
|
|
dsq->getRenderObjectLayer(LR_ELEMENTS10)->visible = dsq->user.video.parallaxOn0;
|
|
dsq->getRenderObjectLayer(LR_ELEMENTS11)->visible = dsq->user.video.parallaxOn1;
|
|
dsq->getRenderObjectLayer(LR_ELEMENTS12)->visible = dsq->user.video.parallaxOn2;
|
|
}
|
|
|
|
void DSQ::clearModSelector()
|
|
{
|
|
if (blackout)
|
|
{
|
|
blackout->setLife(1);
|
|
blackout->setDecayRate(2);
|
|
blackout->fadeAlphaWithLife = 1;
|
|
blackout = 0;
|
|
}
|
|
|
|
if(modSelectorScr)
|
|
{
|
|
modSelectorScr->close();
|
|
modSelectorScr->setLife(1);
|
|
modSelectorScr->setDecayRate(2);
|
|
modSelectorScr->fadeAlphaWithLife = 1;
|
|
modSelectorScr = 0;
|
|
}
|
|
|
|
// This just closes some file handles, nothing fancy
|
|
unloadMods();
|
|
|
|
clearMenu();
|
|
}
|
|
|
|
|
|
|
|
void DSQ::updateSaveSlotPageCount()
|
|
{
|
|
std::ostringstream os;
|
|
os << dsq->continuity.stringBank.get(2006) << " " << user.data.savePage+1 << "/" << maxPages+1;
|
|
saveSlotPageCount->setText(os.str());
|
|
}
|
|
|
|
|
|
void DSQ::createSaveSlots(SaveSlotMode ssm)
|
|
{
|
|
if (!saveSlots.empty())
|
|
{
|
|
errorLog("save slots weren't cleared");
|
|
}
|
|
if (!menu.empty())
|
|
{
|
|
errorLog ("menu wasn't cleared");
|
|
}
|
|
menu.resize(5);
|
|
|
|
float t = 0.3;
|
|
|
|
|
|
blackout = new Quad;
|
|
blackout->color = 0;
|
|
blackout->autoWidth = AUTO_VIRTUALWIDTH;
|
|
blackout->autoHeight = AUTO_VIRTUALHEIGHT;
|
|
blackout->followCamera = 1;
|
|
blackout->position = Vector(400,300);
|
|
blackout->alphaMod = 0.75;
|
|
blackout->alpha = 0;
|
|
blackout->alpha.interpolateTo(1, 0.5);
|
|
addRenderObject(blackout, LR_MENU);
|
|
|
|
|
|
menu[1] = new Quad("gui/save-menu", Vector(400,300));
|
|
savesz = Vector(750.0f/1024.0f, 750.0f/1024.0f);
|
|
menu[1]->alpha = 0;
|
|
menu[1]->alpha.interpolateTo(1, t);
|
|
menu[1]->scale = savesz * 0.5f;
|
|
menu[1]->scale.interpolateTo(savesz, t);
|
|
menu[1]->followCamera = 1;
|
|
addRenderObject(menu[1], LR_MENU);
|
|
|
|
core->sound->playSfx("menu-open");
|
|
|
|
watch(t);
|
|
|
|
saveSlotPageCount = new BitmapText(&dsq->smallFont);
|
|
saveSlotPageCount->followCamera = 1;
|
|
saveSlotPageCount->setAlign(ALIGN_LEFT);
|
|
saveSlotPageCount->position = Vector(590, 300);
|
|
addRenderObject(saveSlotPageCount, LR_MENU);
|
|
updateSaveSlotPageCount();
|
|
|
|
|
|
cancel = new AquariaMenuItem();
|
|
|
|
cancel->useGlow("glow", 200, 50);
|
|
cancel->event.set(MakeFunctionEvent(DSQ,onExitSaveSlotMenu));
|
|
cancel->position = Vector(665, 545);
|
|
addRenderObject(cancel, LR_MENU);
|
|
|
|
menu[0] = cancel;
|
|
|
|
|
|
|
|
arrowUp = new AquariaMenuItem();
|
|
arrowUp->useQuad("gui/arrow-left");
|
|
arrowUp->useGlow("glow", 100, 50);
|
|
arrowUp->useSound("click");
|
|
arrowUp->event.set(MakeFunctionEvent(DSQ, prevSaveSlotPage));
|
|
arrowUp->rotation.z = 90;
|
|
arrowUp->scale = Vector(0.75, 0.75);
|
|
arrowUp->position = Vector(620, 200);
|
|
addRenderObject(arrowUp, LR_MENU);
|
|
|
|
menu[2] = arrowUp;
|
|
|
|
arrowDown = new AquariaMenuItem();
|
|
arrowDown->useQuad("gui/arrow-right");
|
|
arrowDown->useSound("click");
|
|
arrowDown->useGlow("glow", 100, 50);
|
|
arrowDown->scale = Vector(0.75, 0.75);
|
|
arrowDown->event.set(MakeFunctionEvent(DSQ, nextSaveSlotPage));
|
|
arrowDown->rotation.z = 90;
|
|
arrowDown->position = Vector(620, 400);
|
|
addRenderObject(arrowDown, LR_MENU);
|
|
|
|
if (dsq->game->miniMapRender)
|
|
dsq->game->miniMapRender->slide(1);
|
|
|
|
menu[3] = arrowDown;
|
|
|
|
BitmapText *txt = new BitmapText(&dsq->font);
|
|
if (ssm == SSM_LOAD)
|
|
txt->setText(continuity.stringBank.get(2001));
|
|
else
|
|
txt->setText(continuity.stringBank.get(2000));
|
|
txt->position = Vector(230, 68);
|
|
txt->followCamera = 1;
|
|
addRenderObject(txt, LR_MENU);
|
|
|
|
menu[4] = txt;
|
|
|
|
createSaveSlotPage();
|
|
|
|
saveSlots[0]->setFocus(true);
|
|
}
|
|
|
|
void DSQ::title(bool fade)
|
|
{
|
|
core->settings.runInBackground = false;
|
|
recentSaveSlot = -1;
|
|
|
|
dsq->overlay->color = 0;
|
|
dsq->overlay->alpha.interpolateTo(1, 1);
|
|
|
|
if (fade)
|
|
{
|
|
dsq->sound->fadeMusic(SFT_OUT, 1);
|
|
}
|
|
|
|
run(1);
|
|
|
|
resetTimer();
|
|
|
|
if (fade)
|
|
dsq->sound->stopMusic();
|
|
|
|
user.save();
|
|
|
|
if (mod.isActive())
|
|
{
|
|
mod.shutdown();
|
|
}
|
|
|
|
// Will be re-loaded on demand
|
|
unloadMods();
|
|
|
|
// VERY important
|
|
dsq->continuity.reset();
|
|
|
|
dsq->game->transitionToScene("Title");
|
|
}
|
|
|
|
void DSQ::createSaveSlotPage()
|
|
{
|
|
for (int i = 0; i < saveSlots.size(); i++)
|
|
{
|
|
saveSlots[i]->safeKill();
|
|
}
|
|
|
|
saveSlots.resize(saveSlotPageSize);
|
|
for (int i = 0; i < saveSlots.size(); i++)
|
|
{
|
|
saveSlots[i] = new AquariaSaveSlot(i + user.data.savePage * saveSlotPageSize);
|
|
saveSlots[i]->followCamera = 1;
|
|
saveSlots[i]->position = Vector(409,193+i*90);
|
|
if (i != 1)
|
|
saveSlots[i]->position.y ++;
|
|
|
|
if (i == 1 || i == 3)
|
|
saveSlots[i]->position.y -= 0.5f;
|
|
|
|
addRenderObject(saveSlots[i], LR_FILEMENU);
|
|
}
|
|
|
|
saveSlots[0]->setDirMove(DIR_RIGHT, arrowUp);
|
|
saveSlots[1]->setDirMove(DIR_RIGHT, arrowUp);
|
|
saveSlots[2]->setDirMove(DIR_RIGHT, arrowDown);
|
|
saveSlots[3]->setDirMove(DIR_RIGHT, cancel);
|
|
arrowDown->setDirMove(DIR_DOWN, cancel);
|
|
cancel->setDirMove(DIR_UP, arrowDown);
|
|
cancel->setDirMove(DIR_LEFT, saveSlots[3]);
|
|
}
|
|
|
|
void DSQ::nextSaveSlotPage()
|
|
{
|
|
if (saveSlots.empty()) return;
|
|
|
|
user.data.savePage++;
|
|
if (user.data.savePage > maxPages)
|
|
user.data.savePage = 0;
|
|
createSaveSlotPage();
|
|
|
|
updateSaveSlotPageCount();
|
|
}
|
|
|
|
void DSQ::prevSaveSlotPage()
|
|
{
|
|
if (saveSlots.empty()) return;
|
|
|
|
user.data.savePage--;
|
|
if (user.data.savePage < 0)
|
|
user.data.savePage = maxPages;
|
|
createSaveSlotPage();
|
|
|
|
updateSaveSlotPageCount();
|
|
}
|
|
|
|
void DSQ::hideSaveSlotCrap()
|
|
{
|
|
clearMenu();
|
|
|
|
if (blackout)
|
|
blackout->alpha = 0;
|
|
|
|
if (saveSlotPageCount)
|
|
saveSlotPageCount->alpha = 0;
|
|
}
|
|
|
|
void DSQ::clearSaveSlots(bool trans)
|
|
{
|
|
if (trans)
|
|
{
|
|
core->sound->playSfx("menu-close");
|
|
}
|
|
float t = 0.3;
|
|
if (blackout)
|
|
{
|
|
if (!trans)
|
|
{
|
|
blackout->setLife(1);
|
|
blackout->setDecayRate(10);
|
|
if (blackout->alpha.x > 0)
|
|
blackout->fadeAlphaWithLife = 1;
|
|
}
|
|
else
|
|
{
|
|
blackout->setLife(1);
|
|
blackout->setDecayRate(1);
|
|
if (blackout->alpha.x > 0)
|
|
blackout->fadeAlphaWithLife = 1;
|
|
}
|
|
}
|
|
if (saveSlotPageCount)
|
|
{
|
|
saveSlotPageCount->setLife(1);
|
|
saveSlotPageCount->setDecayRate(10);
|
|
if (saveSlotPageCount->alpha.x > 0)
|
|
saveSlotPageCount->fadeAlphaWithLife = 1;
|
|
}
|
|
|
|
for (int i = 0; i < saveSlots.size(); i++)
|
|
{
|
|
saveSlots[i]->close(trans);
|
|
}
|
|
|
|
saveSlots.clear();
|
|
|
|
|
|
|
|
if (trans)
|
|
{
|
|
disableMiniMapOnNoInput = false;
|
|
|
|
for (int i = 0; i < menu.size(); i++)
|
|
{
|
|
if (i != 1)
|
|
{
|
|
menu[i]->alpha = 0;
|
|
|
|
}
|
|
}
|
|
if (menu.size() >= 2)
|
|
{
|
|
menu[1]->scale.interpolateTo(savesz*0.5f, t);
|
|
menu[1]->alpha.interpolateTo(0, t);
|
|
watch(t);
|
|
}
|
|
|
|
disableMiniMapOnNoInput = true;
|
|
}
|
|
clearMenu();
|
|
|
|
|
|
if (dsq->game->miniMapRender)
|
|
dsq->game->miniMapRender->slide(0);
|
|
}
|
|
|
|
void DSQ::hideSaveSlots()
|
|
{
|
|
for (int i = 0; i < saveSlots.size(); i++)
|
|
{
|
|
saveSlots[i]->hide();
|
|
}
|
|
}
|
|
|
|
void DSQ::transitionSaveSlots()
|
|
{
|
|
hideSaveSlotCrap();
|
|
|
|
for (int i = 0; i < saveSlots.size(); i++)
|
|
{
|
|
saveSlots[i]->transition();
|
|
}
|
|
}
|
|
|
|
void DSQ::doSaveSlotMenu(SaveSlotMode ssm, const Vector &position)
|
|
{
|
|
int scrShotWidth = 0, scrShotHeight = 0;
|
|
unsigned char *scrShotData = 0;
|
|
|
|
if (ssm == SSM_SAVE && user.video.saveSlotScreens)
|
|
{
|
|
prepScreen(1);
|
|
|
|
int renderWidth = getWindowWidth(), renderHeight = getWindowHeight();
|
|
int i = 2;
|
|
while (1 << i < renderHeight)
|
|
{
|
|
i++;
|
|
}
|
|
scrShotWidth = scrShotHeight = 1 << (i-1);
|
|
int x = renderWidth/2 - scrShotWidth/2;
|
|
int y = renderHeight/2 - scrShotHeight/2;
|
|
|
|
glPushAttrib(GL_VIEWPORT_BIT);
|
|
glViewport(0, 0, renderWidth, renderHeight);
|
|
clearBuffers();
|
|
render();
|
|
scrShotData = core->grabScreenshot(x, y, scrShotWidth, scrShotHeight);
|
|
glPopAttrib();
|
|
showBuffer();
|
|
|
|
prepScreen(0);
|
|
}
|
|
|
|
saveSlotMode = SSM_NONE;
|
|
|
|
createSaveSlots(ssm);
|
|
const int firstSaveSlot = user.data.savePage * saveSlotPageSize;
|
|
if (user.data.saveSlot >= firstSaveSlot && user.data.saveSlot < firstSaveSlot + saveSlots.size())
|
|
{
|
|
selectedSaveSlot = saveSlots[user.data.saveSlot - firstSaveSlot];
|
|
selectedSaveSlot->setFocus(true);
|
|
}
|
|
else
|
|
{
|
|
selectedSaveSlot = 0;
|
|
}
|
|
|
|
saveSlotMode = ssm;
|
|
|
|
|
|
|
|
resetTimer();
|
|
core->run(-1);
|
|
|
|
|
|
|
|
if (selectedSaveSlot == 0)
|
|
{
|
|
if (saveSlotMode == SSM_SAVE)
|
|
{
|
|
clearSaveSlots(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Drop focus early so it doesn't see joystick movement and
|
|
// try to select a destroyed save slot (and thus crash).
|
|
selectedSaveSlot->setFocus(false);
|
|
recentSaveSlot = selectedSaveSlot->getSlotIndex();
|
|
user.data.saveSlot = recentSaveSlot;
|
|
if (saveSlotMode == SSM_SAVE)
|
|
{
|
|
continuity.saveFile(selectedSaveSlot->getSlotIndex(), position, scrShotData, scrShotWidth, scrShotHeight);
|
|
if (user.video.saveSlotScreens && scrShotData != 0)
|
|
{
|
|
std::ostringstream os;
|
|
os << dsq->getSaveDirectory() << "/screen-" << numToZeroString(selectedSaveSlot->getSlotIndex(), 4) << ".zga";
|
|
|
|
// Cut off top and bottom to get a 4:3 aspect ratio.
|
|
int adjHeight = (scrShotWidth * 3.0f) / 4.0f;
|
|
int imageDataSize = scrShotWidth * scrShotHeight * 4;
|
|
int adjImageSize = scrShotWidth * adjHeight * 4;
|
|
int adjOffset = scrShotWidth * ((scrShotHeight-adjHeight)/2) * 4;
|
|
memmove(scrShotData, scrShotData + adjOffset, adjImageSize);
|
|
memset(scrShotData + adjImageSize, 0, imageDataSize - adjImageSize);
|
|
zgaSave(os.str().c_str(), scrShotWidth, scrShotHeight, 32, scrShotData);
|
|
}
|
|
|
|
PlaySfx sfx;
|
|
sfx.name = "saved";
|
|
sfx.vol = 0.55;
|
|
dsq->sound->playSfx(sfx);
|
|
confirm("", "saved", 1);
|
|
|
|
clearSaveSlots(true);
|
|
}
|
|
else if (saveSlotMode == SSM_LOAD)
|
|
{
|
|
continuity.loadFile(selectedSaveSlot->getSlotIndex());
|
|
dsq->game->transitionToScene(dsq->game->sceneToLoad);
|
|
}
|
|
// when gameover hits, load up this instead of that.
|
|
}
|
|
|
|
resetTimer();
|
|
|
|
delete[] scrShotData;
|
|
saveSlotMode = SSM_NONE;
|
|
|
|
}
|
|
|
|
std::string DSQ::getEntityFlagName(Entity *e)
|
|
{
|
|
if (!dsq->game) return "";
|
|
std::ostringstream os;
|
|
os << dsq->game->sceneName << e->startPos.x << e->startPos.y;
|
|
return os.str();
|
|
}
|
|
|
|
void doAlphabetInputKey(int d, char c, char map[], std::string *text, char upper=0)
|
|
{
|
|
if (core->getKeyState(d) && !map[d])
|
|
{
|
|
char usec = c;
|
|
if (upper != 0 && (core->getKeyState(KEY_LSHIFT) || core->getKeyState(KEY_RSHIFT)))
|
|
{
|
|
usec = upper;
|
|
}
|
|
*text += usec;
|
|
map[d] = 1;
|
|
}
|
|
else if (!core->getKeyState(d) && map[d])
|
|
{
|
|
map[d] = 0;
|
|
}
|
|
}
|
|
|
|
void DSQ::generateCollisionMask(RenderObject *r)
|
|
{
|
|
Quad *q = dynamic_cast<Quad*>(r);
|
|
if (q)
|
|
game->generateCollisionMask(q);
|
|
}
|
|
|
|
void DSQ::onConfirmYes()
|
|
{
|
|
dsq->confirmDone = 1;
|
|
}
|
|
|
|
void DSQ::onConfirmNo()
|
|
{
|
|
dsq->confirmDone = 2;
|
|
}
|
|
|
|
bool DSQ::confirm(const std::string &text, const std::string &image, bool ok, float countdown)
|
|
{
|
|
const float t = 0.3;
|
|
|
|
sound->playSfx("menu-open");
|
|
|
|
confirmDone = 0;
|
|
|
|
std::string imageName = "gui/confirm-bg";
|
|
if (!image.empty())
|
|
{
|
|
imageName += "-" + image;
|
|
}
|
|
|
|
Quad *bgLabel = new Quad(imageName, Vector(400,300));
|
|
bgLabel->followCamera = 1;
|
|
bgLabel->alpha = 0;
|
|
bgLabel->alpha.interpolateTo(1, t);
|
|
|
|
bgLabel->scale = Vector(0.5, 0.5);
|
|
bgLabel->scale.interpolateTo(Vector(1,1), t);
|
|
addRenderObject(bgLabel, LR_CONFIRM);
|
|
|
|
const int GUILEVEL_CONFIRM = 200;
|
|
|
|
AquariaGuiElement::currentGuiInputLevel = GUILEVEL_CONFIRM;
|
|
|
|
dsq->run(t);
|
|
|
|
float t2 = 0.05;
|
|
|
|
|
|
|
|
AquariaMenuItem *yes=0;
|
|
AquariaMenuItem *no=0;
|
|
|
|
if (ok)
|
|
{
|
|
yes = new AquariaMenuItem();
|
|
yes->useQuad("gui/ok");
|
|
yes->useGlow("glow", 64, 50);
|
|
yes->event.set(MakeFunctionEvent(DSQ,onConfirmYes));
|
|
|
|
yes->position = Vector(400, 340);
|
|
addRenderObject(yes, LR_CONFIRM);
|
|
|
|
yes->setFocus(true);
|
|
|
|
yes->setCanDirMove(false);
|
|
|
|
yes->guiInputLevel = GUILEVEL_CONFIRM;
|
|
}
|
|
else
|
|
{
|
|
yes = new AquariaMenuItem();
|
|
yes->useQuad("yes");
|
|
yes->useGlow("glow", 64, 50);
|
|
yes->event.set(MakeFunctionEvent(DSQ,onConfirmYes));
|
|
|
|
yes->position = Vector(330, 340);
|
|
addRenderObject(yes, LR_CONFIRM);
|
|
|
|
yes->guiInputLevel = GUILEVEL_CONFIRM;
|
|
|
|
no = new AquariaMenuItem();
|
|
no->useQuad("no");
|
|
no->useGlow("glow", 64, 50);
|
|
no->event.set(MakeFunctionEvent(DSQ,onConfirmNo));
|
|
|
|
no->position = Vector(470, 340);
|
|
addRenderObject(no, LR_CONFIRM);
|
|
|
|
no->guiInputLevel = GUILEVEL_CONFIRM;
|
|
|
|
no->setFocus(true);
|
|
|
|
no->setDirMove(DIR_LEFT, yes);
|
|
|
|
no->setDirMove(DIR_UP, no);
|
|
no->setDirMove(DIR_DOWN, no);
|
|
no->setDirMove(DIR_RIGHT, no);
|
|
|
|
yes->setDirMove(DIR_RIGHT, no);
|
|
|
|
yes->setDirMove(DIR_UP, yes);
|
|
yes->setDirMove(DIR_DOWN, yes);
|
|
yes->setDirMove(DIR_LEFT, yes);
|
|
}
|
|
|
|
BitmapText *txt = new BitmapText(&dsq->smallFont);
|
|
txt->followCamera = 1;
|
|
txt->position = Vector(400,250);
|
|
txt->setText(text);
|
|
txt->alpha = 0;
|
|
txt->scale = Vector(0.9, 0.9);
|
|
txt->alpha.interpolateTo(1, t2);
|
|
addRenderObject(txt, LR_CONFIRM);
|
|
|
|
dsq->run(t2);
|
|
|
|
while (!confirmDone)
|
|
{
|
|
dsq->run(FRAME_TIME);
|
|
if (countdown > 0) {
|
|
countdown -= FRAME_TIME;
|
|
if (countdown < 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
sound->playSfx("menu-close");
|
|
|
|
txt->alpha.interpolateTo(0, t2);
|
|
if (yes) yes->alpha.interpolateTo(0, t2);
|
|
if (no) no->alpha.interpolateTo(0, t2);
|
|
dsq->run(t2);
|
|
|
|
bgLabel->alpha.interpolateTo(0, t);
|
|
bgLabel->scale.interpolateTo(Vector(0.5, 0.5), t);
|
|
dsq->run(t);
|
|
|
|
bgLabel->safeKill();
|
|
txt->safeKill();
|
|
if (yes)
|
|
{
|
|
yes->setFocus(false);
|
|
yes->safeKill();
|
|
}
|
|
if (no)
|
|
{
|
|
no->setFocus(false);
|
|
no->safeKill();
|
|
}
|
|
|
|
bool ret = (confirmDone == 1);
|
|
|
|
if (countdown < 0)
|
|
ret = false;
|
|
|
|
AquariaGuiElement::currentGuiInputLevel = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
std::string DSQ::getUserInputString(std::string labelText, std::string t, bool allowNonLowerCase)
|
|
{
|
|
float trans = 0.1;
|
|
|
|
bool pauseState = dsq->game->isPaused();
|
|
|
|
dsq->game->togglePause(true);
|
|
|
|
sound->playSfx("Menu-Open");
|
|
|
|
RoundedRect *bg = new RoundedRect;
|
|
bg->setWidthHeight(790, 64, 10);
|
|
bg->position = Vector(400,300);
|
|
bg->followCamera = 1;
|
|
bg->alpha = 0;
|
|
addRenderObject(bg, LR_DEBUG_TEXT);
|
|
|
|
|
|
|
|
TTFText *label = new TTFText(&dsq->fontArialSmall);
|
|
label->setText(labelText);
|
|
label->position = Vector(-400 + 20, -12);
|
|
bg->addChild(label, PM_POINTER);
|
|
|
|
TTFText *inputText = new TTFText(&dsq->fontArialBig);
|
|
|
|
inputText->position = Vector(-400 + 20,8+8);
|
|
bg->addChild(inputText, PM_POINTER);
|
|
|
|
|
|
bg->show();
|
|
run(trans);
|
|
|
|
|
|
std::string text = t;
|
|
char map[256];
|
|
for (int i = 0; i < 256; i++)
|
|
map[i] = 0;
|
|
bool delDown = false;
|
|
bool escDown = false;
|
|
|
|
float dt = 1.0f/60.0f;
|
|
float blinkTimer = 0;
|
|
bool blink = false;
|
|
|
|
while (1)
|
|
{
|
|
if (blink)
|
|
{
|
|
text.resize(text.size()-1);
|
|
inputText->setText(text);
|
|
}
|
|
if (inputText->getActualWidth() < 800-60)
|
|
{
|
|
doAlphabetInputKey(KEY_A, 'a', (char*)&map, &text, 'A');
|
|
doAlphabetInputKey(KEY_B, 'b', (char*)&map, &text, 'B');
|
|
doAlphabetInputKey(KEY_C, 'c', (char*)&map, &text, 'C');
|
|
doAlphabetInputKey(KEY_D, 'd', (char*)&map, &text, 'D');
|
|
doAlphabetInputKey(KEY_E, 'e', (char*)&map, &text, 'E');
|
|
doAlphabetInputKey(KEY_F, 'f', (char*)&map, &text, 'F');
|
|
doAlphabetInputKey(KEY_G, 'g', (char*)&map, &text, 'G');
|
|
doAlphabetInputKey(KEY_H, 'h', (char*)&map, &text, 'H');
|
|
doAlphabetInputKey(KEY_I, 'i', (char*)&map, &text, 'I');
|
|
doAlphabetInputKey(KEY_J, 'j', (char*)&map, &text, 'J');
|
|
doAlphabetInputKey(KEY_K, 'k', (char*)&map, &text, 'K');
|
|
doAlphabetInputKey(KEY_L, 'l', (char*)&map, &text, 'L');
|
|
doAlphabetInputKey(KEY_M, 'm', (char*)&map, &text, 'M');
|
|
doAlphabetInputKey(KEY_N, 'n', (char*)&map, &text, 'N');
|
|
doAlphabetInputKey(KEY_O, 'o', (char*)&map, &text, 'O');
|
|
doAlphabetInputKey(KEY_P, 'p', (char*)&map, &text, 'P');
|
|
doAlphabetInputKey(KEY_Q, 'q', (char*)&map, &text, 'Q');
|
|
doAlphabetInputKey(KEY_R, 'r', (char*)&map, &text, 'R');
|
|
doAlphabetInputKey(KEY_S, 's', (char*)&map, &text, 'S');
|
|
doAlphabetInputKey(KEY_T, 't', (char*)&map, &text, 'T');
|
|
doAlphabetInputKey(KEY_U, 'u', (char*)&map, &text, 'U');
|
|
doAlphabetInputKey(KEY_V, 'v', (char*)&map, &text, 'V');
|
|
doAlphabetInputKey(KEY_W, 'w', (char*)&map, &text, 'W');
|
|
doAlphabetInputKey(KEY_X, 'x', (char*)&map, &text, 'X');
|
|
doAlphabetInputKey(KEY_Y, 'y', (char*)&map, &text, 'Y');
|
|
doAlphabetInputKey(KEY_Z, 'z', (char*)&map, &text, 'Z');
|
|
doAlphabetInputKey(KEY_1, '1', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_2, '2', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_3, '3', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_4, '4', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_5, '5', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_6, '6', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_7, '7', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_8, '8', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_9, '9', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_0, '0', (char*)&map, &text);
|
|
|
|
doAlphabetInputKey(KEY_PERIOD, '.', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_SPACE, ' ', (char*)&map, &text);
|
|
doAlphabetInputKey(KEY_MINUS, '-', (char*)&map, &text, '_');
|
|
|
|
doAlphabetInputKey(KEY_TILDE, '~', (char*)&map, &text, '~');
|
|
}
|
|
|
|
if (core->getKeyState(KEY_BACKSPACE))
|
|
{
|
|
if (!delDown)
|
|
{
|
|
if (!text.empty())
|
|
{
|
|
text.resize(text.size()-1);
|
|
}
|
|
}
|
|
delDown = true;
|
|
}
|
|
else
|
|
{
|
|
delDown = false;
|
|
}
|
|
|
|
blinkTimer += dt;
|
|
if (blinkTimer > 0.2f)
|
|
{
|
|
blink = !blink;
|
|
blinkTimer = 0;
|
|
}
|
|
|
|
if (blink)
|
|
{
|
|
text += "|";
|
|
}
|
|
|
|
|
|
|
|
if (core->getKeyState(KEY_RETURN))
|
|
break;
|
|
|
|
if (!escDown && core->getKeyState(KEY_ESCAPE))
|
|
escDown = true;
|
|
else if (escDown && !core->getKeyState(KEY_ESCAPE))
|
|
{
|
|
escDown = false;
|
|
text = t;
|
|
break;
|
|
}
|
|
inputText->setText(text);
|
|
core->run(dt);
|
|
}
|
|
|
|
if (blink && !text.empty() && (text[text.size()-1] == '|'))
|
|
text.resize(text.size()-1);
|
|
|
|
sound->playSfx("Menu-Close");
|
|
|
|
|
|
bg->hide();
|
|
|
|
run(0.2);
|
|
|
|
inputText->alpha = 0;
|
|
label->alpha = 0;
|
|
inputText->safeKill();
|
|
label->safeKill();
|
|
bg->alpha = 0;
|
|
bg->safeKill();
|
|
|
|
dsq->game->togglePause(pauseState);
|
|
|
|
if (!allowNonLowerCase)
|
|
stringToLower(text);
|
|
|
|
debugLog("getUserInputString returned: " + text);
|
|
|
|
return text;
|
|
}
|
|
|
|
void DSQ::stopVoice()
|
|
{
|
|
sound->stopVoice();
|
|
subtitlePlayer.end();
|
|
}
|
|
|
|
bool DSQ::playedVoice(const std::string &file)
|
|
{
|
|
std::string f = file;
|
|
stringToUpper(f);
|
|
for (int i = 0; i < dsq->continuity.voiceOversPlayed.size(); i++)
|
|
{
|
|
if (f == dsq->continuity.voiceOversPlayed[i])
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void DSQ::voiceOnce(const std::string &file)
|
|
{
|
|
std::string f = file;
|
|
stringToUpper(f);
|
|
if (!playedVoice(f))
|
|
{
|
|
voice(file);
|
|
}
|
|
}
|
|
|
|
// This is a pretty "dangerous" function
|
|
// it will kill the current voice over and all pending voice overs
|
|
// recommended only in situations where overriding the voice is acceptable
|
|
// i.e. song cave door (1st songdoor)
|
|
void DSQ::voiceInterupt(const std::string &f)
|
|
{
|
|
sound->playVoice(f, SVT_INTERRUPT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSQ::onPlayVoice()
|
|
{
|
|
|
|
}
|
|
|
|
void DSQ::onStopVoice()
|
|
{
|
|
subtitlePlayer.end();
|
|
|
|
}
|
|
|
|
void DSQ::voice(const std::string &f, float volMod)
|
|
{
|
|
debugLog("Voice: " + f);
|
|
std::string file = f;
|
|
stringToUpper(file);
|
|
|
|
if (!playedVoice(file))
|
|
dsq->continuity.voiceOversPlayed.push_back(file);
|
|
|
|
sound->playVoice(file, SVT_QUEUE, volMod);
|
|
}
|
|
|
|
void DSQ::onPlayedVoice(const std::string &name)
|
|
{
|
|
Core::onPlayedVoice(name);
|
|
|
|
if (user.audio.subtitles)
|
|
subtitlePlayer.go(name);
|
|
}
|
|
|
|
Entity *DSQ::getFirstEntity()
|
|
{
|
|
iter = &entities[0];
|
|
return getNextEntity();
|
|
}
|
|
|
|
Entity *DSQ::getNextEntity()
|
|
{
|
|
if (*iter == 0)
|
|
return 0;
|
|
return *(iter++);
|
|
}
|
|
|
|
bool DSQ::runScript(const std::string &name, const std::string &function, bool ignoremissing /* = false */)
|
|
{
|
|
if (!scriptInterface.runScript(name, function, ignoremissing))
|
|
{
|
|
debugLog("Could not find script file [" + name + "]");
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool DSQ::runScriptNum(const std::string &name, const std::string &func, float num)
|
|
{
|
|
if (!scriptInterface.runScriptNum(name, func, num))
|
|
{
|
|
debugLog("Could not find script file [" + name + "]");
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void DSQ::collectScriptGarbage()
|
|
{
|
|
scriptInterface.collectGarbage();
|
|
}
|
|
|
|
void DSQ::onMouseInput()
|
|
{
|
|
if (dsq->game && dsq->game->avatar)
|
|
{
|
|
if (!dsq->game->isInGameMenu() && !dsq->game->isSceneEditorActive() && !dsq->game->isPaused())
|
|
{
|
|
bool limitRange = true;
|
|
int range = 300;
|
|
if (dsq->game->avatar->singing)
|
|
range = 100;
|
|
else
|
|
limitRange = false;
|
|
|
|
if (limitRange)
|
|
{
|
|
Vector diff = core->mouse.position - core->center;
|
|
if (diff.getSquaredLength2D() > sqr(range))
|
|
{
|
|
diff.setLength2D(range);
|
|
core->mouse.position = core->center + diff;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//prepare for screenshot or unprepare
|
|
void DSQ::prepScreen(bool t)
|
|
{
|
|
if (t)
|
|
{
|
|
cursor->offset = Vector(2000, 0);
|
|
|
|
if (game->miniMapRender)
|
|
game->miniMapRender->offset = Vector(2000,0);
|
|
if (fpsText)
|
|
fpsText->offset = Vector(2000,0);
|
|
}
|
|
else
|
|
{
|
|
|
|
cursor->offset = Vector(0,0);
|
|
if (game->miniMapRender)
|
|
game->miniMapRender->offset = Vector(0,0);
|
|
if (fpsText)
|
|
fpsText->offset = Vector(0,0);
|
|
}
|
|
}
|
|
|
|
void DSQ::onRender()
|
|
{
|
|
if (cursor)
|
|
{
|
|
// HACK: not so pretty :D
|
|
if (core->getTopStateObject() == (StateObject*)game)
|
|
{
|
|
if (doScreenshot)
|
|
prepScreen(1);
|
|
}
|
|
cursor->position = mouse.position;
|
|
cursor->position.z = 0;
|
|
}
|
|
}
|
|
|
|
void DSQ::vision(std::string folder, int num, bool ignoreMusic)
|
|
{
|
|
toggleBlackBars(1);
|
|
|
|
dsq->toggleCursor(false);
|
|
if (game)
|
|
game->togglePause(true);
|
|
|
|
dsq->overlay->color = Vector(1,1,1);
|
|
|
|
float t = 0.1;
|
|
|
|
dsq->game->miniMapRender->toggle(0);
|
|
|
|
fade(1, t);
|
|
run(t);
|
|
|
|
// load images
|
|
typedef std::list<Quad*> QuadList;
|
|
QuadList images;
|
|
|
|
for (int i = num-1; i >= 0; i--)
|
|
{
|
|
Quad *q = new Quad;
|
|
std::string label = "visions/"+folder+"/"+numToZeroString(i, 2)+".png";
|
|
|
|
q->setTexture(label);
|
|
|
|
q->setWidthHeight(800,600);
|
|
q->followCamera = 1;
|
|
q->position = Vector(400,300);
|
|
images.push_front(q);
|
|
addRenderObject(q, LR_HUD);
|
|
}
|
|
|
|
if (!ignoreMusic)
|
|
sound->setMusicFader(0, t);
|
|
|
|
for (QuadList::iterator i = images.begin(); i != images.end(); i++)
|
|
{
|
|
sound->playSfx("memory-flash");
|
|
|
|
(*i)->scale.interpolateTo(Vector(1.1,1.1), 0.4);
|
|
fade(0, t);
|
|
run(t);
|
|
|
|
run(0.1);
|
|
|
|
fade(1, t);
|
|
run(t);
|
|
|
|
(*i)->alpha = 0;
|
|
}
|
|
|
|
if (game)
|
|
game->togglePause(false);
|
|
dsq->toggleCursor(true);
|
|
|
|
sound->playSfx("memory-flash");
|
|
fade(0, t);
|
|
run(t);
|
|
|
|
for (QuadList::iterator i = images.begin(); i != images.end(); i++)
|
|
{
|
|
(*i)->safeKill();
|
|
}
|
|
images.clear();
|
|
|
|
if (!ignoreMusic)
|
|
sound->setMusicFader(1, t);
|
|
|
|
dsq->overlay->color = Vector(0,0,0);
|
|
|
|
dsq->game->miniMapRender->toggle(1);
|
|
|
|
toggleBlackBars(0);
|
|
}
|
|
|
|
bool DSQ::isDeveloperKeys()
|
|
{
|
|
#ifdef AQUARIA_DEMO
|
|
return false;
|
|
#endif
|
|
|
|
return user.system.devModeOn;
|
|
}
|
|
|
|
bool DSQ::canOpenEditor() const
|
|
{
|
|
#ifdef AQUARIA_BUILD_SCENEEDITOR
|
|
return dsq->isDeveloperKeys() || (dsq->mod.isActive() && !dsq->mod.isEditorBlocked());
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool DSQ::isQuitFlag()
|
|
{
|
|
return watchQuitFlag;
|
|
}
|
|
|
|
void DSQ::watch(float t, int canQuit)
|
|
{
|
|
watchQuitFlag = false;
|
|
watchForQuit = false;
|
|
|
|
bool wasInputEnabled = false;
|
|
|
|
if (dsq->game && dsq->game->avatar)
|
|
{
|
|
wasInputEnabled = dsq->game->avatar->isInputEnabled();
|
|
|
|
if (wasInputEnabled)
|
|
{
|
|
dsq->game->avatar->disableInput();
|
|
}
|
|
}
|
|
|
|
core->quitNestedMain();
|
|
|
|
if (canQuit)
|
|
{
|
|
watchForQuit = true;
|
|
}
|
|
|
|
if (t != 0.0f)
|
|
core->run(t);
|
|
else
|
|
errorLog("Called Watch with time == 0");
|
|
|
|
if (canQuit && watchQuitFlag)
|
|
{
|
|
// did it!
|
|
}
|
|
|
|
watchForQuit = false;
|
|
|
|
if (dsq->game && dsq->game->avatar)
|
|
{
|
|
if (wasInputEnabled)
|
|
dsq->game->avatar->enableInput();
|
|
}
|
|
}
|
|
|
|
void DSQ::action(int id, int state, int source)
|
|
{
|
|
Core::action(id, state, source);
|
|
|
|
if (id == ACTION_ESC && !state)
|
|
{
|
|
if (isInCutscene())
|
|
{
|
|
if (isCutscenePaused())
|
|
{
|
|
pauseCutscene(false);
|
|
}
|
|
else
|
|
{
|
|
pauseCutscene(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(id == ACTION_SCREENSHOT && state)
|
|
{
|
|
screenshot();
|
|
}
|
|
}
|
|
|
|
void DSQ::bindInput()
|
|
{
|
|
clearActions();
|
|
almb.clear();
|
|
armb.clear();
|
|
|
|
addAction(MakeFunctionEvent(DSQ, onSwitchScreenMode), KEY_RETURN, 1);
|
|
|
|
if (isDeveloperKeys())
|
|
{
|
|
#ifdef AQUARIA_BUILD_CONSOLE
|
|
addAction(MakeFunctionEvent(DSQ, toggleConsole), KEY_TILDE, 0);
|
|
#endif
|
|
addAction(MakeFunctionEvent(DSQ, toggleRenderCollisionShapes), KEY_RETURN, 0);
|
|
}
|
|
addAction(MakeFunctionEvent(DSQ, debugMenu), KEY_BACKSPACE, 0);
|
|
//addAction(MakeFunctionEvent(DSQ, takeScreenshotKey ), KEY_P, 0);
|
|
|
|
for(size_t i = 0; i < dsq->user.control.actionSets.size(); ++i)
|
|
{
|
|
ActionSet& as = dsq->user.control.actionSets[i];
|
|
int sourceID = (int)i;
|
|
|
|
as.importAction(this, "Escape", ACTION_ESC, sourceID);
|
|
as.importAction(this, "Screenshot", ACTION_SCREENSHOT, sourceID);
|
|
|
|
if(ActionInput *a = as.getActionInputByName("PrimaryAction"))
|
|
almb.push_back(a);
|
|
if(ActionInput *a = as.getActionInputByName("SecondaryAction"))
|
|
armb.push_back(a);
|
|
}
|
|
}
|
|
|
|
void DSQ::jiggleCursor()
|
|
{
|
|
// hacky
|
|
SDL_ShowCursor(SDL_ENABLE);
|
|
SDL_ShowCursor(SDL_DISABLE);
|
|
}
|
|
|
|
void DSQ::updateActionButtons()
|
|
{
|
|
// HACK: not optimal
|
|
|
|
// This must be done *before* Core::updateActionButtons()
|
|
// for LMB/RMB emulation to work properly -- fg
|
|
if (/*inputMode != INPUT_KEYBOARD &&*/ game->isActive())
|
|
{
|
|
for(size_t i = 0; i < almb.size(); ++i)
|
|
if (ActionMapper::getKeyState(almb[i]->key[0]) || ActionMapper::getKeyState(almb[i]->key[1]))
|
|
{
|
|
mouse.buttons.left = DOWN;
|
|
break;
|
|
}
|
|
for(size_t i = 0; i < armb.size(); ++i)
|
|
if (ActionMapper::getKeyState(armb[i]->key[0]) || ActionMapper::getKeyState(armb[i]->key[1]))
|
|
{
|
|
mouse.buttons.right = DOWN;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (joystickAsMouse)
|
|
{
|
|
for(size_t i = 0; i < almb.size(); ++i)
|
|
if (ActionMapper::getKeyState(almb[i]->joy[0]))
|
|
{
|
|
mouse.buttons.left = DOWN;
|
|
break;
|
|
}
|
|
for(size_t i = 0; i < armb.size(); ++i)
|
|
if (ActionMapper::getKeyState(armb[i]->joy[0]))
|
|
{
|
|
mouse.buttons.right = DOWN;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Core::updateActionButtons();
|
|
}
|
|
|
|
static float skipSfxVol = 1.0;
|
|
void DSQ::onUpdate(float dt)
|
|
{
|
|
if (isSkippingCutscene())
|
|
{
|
|
if (!isInCutscene())
|
|
{
|
|
pauseCutscene(false);
|
|
skippingCutscene = false;
|
|
settings.renderOn = true;
|
|
sound->setSfxVolume(skipSfxVol);
|
|
}
|
|
else
|
|
{
|
|
sound->stopVoice();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isCutscenePaused())
|
|
{
|
|
sound->pause();
|
|
float sec = 1.0f/60.0f;
|
|
while (isCutscenePaused())
|
|
{
|
|
pollEvents(sec);
|
|
ActionMapper::onUpdate(sec);
|
|
SDL_Delay(int(sec*1000));
|
|
render();
|
|
showBuffer();
|
|
resetTimer();
|
|
|
|
if (_canSkipCutscene && core->getKeyState(KEY_S))
|
|
{
|
|
skippingCutscene = true;
|
|
settings.renderOn = false;
|
|
skipSfxVol = sound->getSfxVol();
|
|
sound->setSfxVolume(0.0);
|
|
resetTimer();
|
|
sound->resume();
|
|
return;
|
|
}
|
|
}
|
|
dsq->resetTimer();
|
|
dsq->sound->resume();
|
|
}
|
|
}
|
|
|
|
// This queries pressed keys and updates ActionMapper
|
|
Core::onUpdate(dt);
|
|
|
|
|
|
mod.update(dt);
|
|
|
|
if (dsq->game && watchForQuit && isNested())
|
|
{
|
|
if (dsq->game->isActing(ACTION_ESC, -1))
|
|
{
|
|
watchQuitFlag = true;
|
|
quitNestedMain();
|
|
}
|
|
}
|
|
|
|
// messy
|
|
if (versionLabel && versionLabel->alpha.x > 0)
|
|
{
|
|
versionLabel->position = Vector(10 - core->getVirtualOffX(), 575);
|
|
}
|
|
|
|
if (noEffectTimer > 0)
|
|
{
|
|
noEffectTimer -=dt;
|
|
if (noEffectTimer < 0)
|
|
noEffectTimer = 0;
|
|
}
|
|
|
|
|
|
subtitlePlayer.update(dt);
|
|
|
|
demo.update(dt);
|
|
|
|
if (joystickEnabled)
|
|
{
|
|
if (dsq->inputMode != INPUT_JOYSTICK)
|
|
{
|
|
const float thresh = JOY_AXIS_THRESHOLD;
|
|
for(size_t i = 0; i < getNumJoysticks(); ++i)
|
|
if(Joystick *j = getJoystick(i))
|
|
if(j && j->isEnabled())
|
|
if (j->anyButton() || !j->position.isLength2DIn(thresh) || !j->rightStick.isLength2DIn(thresh))
|
|
{
|
|
//debugLog("setting joystick input mode");
|
|
dsq->setInputMode(INPUT_JOYSTICK);
|
|
}
|
|
}
|
|
else if (dsq->inputMode != INPUT_MOUSE)
|
|
{
|
|
if ((!core->mouse.change.isLength2DIn(5) || (core->getMouseButtonState(0) || core->getMouseButtonState(1))) /*&& !core->joystick.anyButton()*/)
|
|
{
|
|
//debugLog("setting mouse input mode");
|
|
dsq->setInputMode(INPUT_MOUSE);
|
|
}
|
|
}
|
|
}
|
|
if (dsq->game->avatar)
|
|
{
|
|
if (dsq->game->avatar->isActing(ACTION_SWIMUP, -1) ||
|
|
dsq->game->avatar->isActing(ACTION_SWIMDOWN, -1) ||
|
|
dsq->game->avatar->isActing(ACTION_SWIMLEFT, -1) ||
|
|
dsq->game->avatar->isActing(ACTION_SWIMRIGHT, -1))
|
|
{
|
|
dsq->setInputMode(INPUT_KEYBOARD);
|
|
}
|
|
}
|
|
|
|
// check the actual values, since mouse.buttons.left might be overwritten by keys
|
|
int cb = 0;
|
|
if (user.control.flipInputButtons)
|
|
cb = 1;
|
|
|
|
if (dsq->inputMode == INPUT_KEYBOARD && (core->getMouseButtonState(cb)))
|
|
{
|
|
dsq->setInputMode(INPUT_MOUSE);
|
|
}
|
|
|
|
|
|
|
|
if (isDeveloperKeys() && cmDebug && cmDebug->alpha == 1 && fpsText)
|
|
{
|
|
std::ostringstream os;
|
|
|
|
|
|
if (dsq->game->avatar)
|
|
{
|
|
Avatar *avatar = dsq->game->avatar;
|
|
os << "rolling: " << dsq->game->avatar->isRolling() << " rollDelay: " << dsq->game->avatar->rollDelay << std::endl;
|
|
os << "canChangeForm: " << dsq->game->avatar->canChangeForm << " gamespeed: " << gameSpeed.x << std::endl;
|
|
os << "h: " << dsq->game->avatar->health << " / " << dsq->game->avatar->maxHealth << std::endl;
|
|
os << "biteTimer: " << dsq->game->avatar->biteTimer << " flourTimer: " << dsq->game->avatar->flourishTimer.getValue() << std::endl;
|
|
os << "stillTimer: " << dsq->game->avatar->stillTimer.getValue() << std::endl;
|
|
os << "hp: " << dsq->game->avatar->getHealthPerc() << " flourishPowerTimer: " << dsq->game->avatar->flourishPowerTimer.getValue() << std::endl;
|
|
os << "maxSpeed: " << dsq->game->avatar->currentMaxSpeed << " - ";
|
|
os << "lockedToWall: " << dsq->game->avatar->state.lockedToWall;
|
|
os << std::endl;
|
|
os << "swmng: " << avatar->isSwimming();
|
|
os << " dualFormCharge: " << continuity.dualFormCharge;
|
|
os << std::endl;
|
|
os << "vel(" << avatar->vel.x << ", " << avatar->vel.y << ") ";
|
|
os << "vel2(" << avatar->vel2.x << ", " << avatar->vel2.y << ")";
|
|
os << std::endl;
|
|
os << "rot: " << avatar->rotation.z << " rotoff: " << avatar->rotationOffset.z << std::endl;
|
|
os << "p(" << int(avatar->position.x) << ", " << int(avatar->position.y) << ")" << std::endl;
|
|
os << "inp: " << avatar->isInputEnabled() << std::endl;
|
|
os << "wallNormal(" << avatar->wallNormal.x << ", " << avatar->wallNormal.y << ") collradius: " << avatar->collideRadius << std::endl;
|
|
os << "burst: " << avatar->burst << " burstTimer: " << avatar->burstTimer << std::endl;
|
|
os << "inCurrent: " << avatar->isInCurrent() << std::endl;
|
|
os << "qsongCastDelay: " << avatar->quickSongCastDelay << std::endl;
|
|
os << "singing: " << dsq->game->avatar->singing << " blockSinging: " << dsq->game->avatar->isBlockSinging();
|
|
os << " look: " << dsq->game->avatar->state.updateLookAtTime << " ";
|
|
|
|
os << "inputMode: ";
|
|
switch(dsq->inputMode)
|
|
{
|
|
case INPUT_MOUSE:
|
|
os << "mouse";
|
|
break;
|
|
case INPUT_JOYSTICK:
|
|
os << "joystick";
|
|
break;
|
|
}
|
|
os << std::endl;
|
|
Bone *b = dsq->game->avatar->skeletalSprite.getBoneByIdx(1);
|
|
if (b)
|
|
os << " headRot: " << b->rotation.z;
|
|
os << std::endl;
|
|
os << "fh: " << dsq->game->avatar->isfh() << " fv: " << dsq->game->avatar->isfv() << std::endl;
|
|
os << "canActivate: " << dsq->game->avatar->canActivateStuff();
|
|
os << " canBurst: " << dsq->game->avatar->canBurst();
|
|
os << " canLTW: " << dsq->game->avatar->canLockToWall();
|
|
os << " canSAC: " << dsq->game->avatar->canSwimAgainstCurrents() << std::endl;
|
|
}
|
|
|
|
// DO NOT CALL AVATAR-> beyond this point
|
|
os << "story: " << continuity.getStory() << std::endl;
|
|
os << "invGlobalScale: " << core->invGlobalScale;
|
|
os << std::endl;
|
|
os << "globalScale: " << core->globalScale.x << std::endl;
|
|
os << "mousePos:(" << core->mouse.position.x << ", " << core->mouse.position.y << ") mouseChange:(" << core->mouse.change.x << ", " << core->mouse.change.y << ")\n";
|
|
for(size_t i = 0; i < getNumJoysticks(); ++i)
|
|
if(Joystick *j = getJoystick(i))
|
|
{
|
|
os << "J[" << i << "," << (j->isEnabled() ? " on" : "off") << "]:[";
|
|
for(unsigned ii = 0; ii < MAX_JOYSTICK_BTN; ++ii)
|
|
if(j->getButton(ii))
|
|
os << (ii % 10);
|
|
else
|
|
os << '-';
|
|
os << "], (" << j->position.x << ", " << j->position.y << "), ("<< j->rightStick.x << ", " << j->rightStick.y << ")\n";
|
|
}
|
|
os << "altState: " << core->getKeyState(KEY_LALT) << " | " << core->getKeyState(KEY_RALT) << " mb: " << mouse.buttons.left << mouse.buttons.middle << mouse.buttons.right << std::endl;
|
|
os << "PMFree: " << particleManager->getFree() << " Active: " << particleManager->getNumActive() << std::endl;
|
|
os << "cameraPos: (" << dsq->cameraPos.x << ", " << dsq->cameraPos.y << ")" << std::endl;
|
|
os << "worldType: " << continuity.getWorldType() << " worldPaused: " << game->isWorldPaused() << std::endl;
|
|
os << "voiceTime: " << dsq->sound->getVoiceTime() << " bNat: " << dsq->game->bNatural;
|
|
int ca, ma;
|
|
dsq->sound->getStats(&ca, &ma);
|
|
os << " ca: " << ca << " ma: " << ma << std::endl;
|
|
os << dsq->sound->getVolumeString() << std::endl;
|
|
os << "runInBG: " << core->settings.runInBackground << " nested: " << core->getNestedMains() << std::endl;
|
|
os << core->globalResolutionScale.x << ", " << core->globalResolutionScale.y << std::endl;
|
|
os << "elemu: " << game->elementUpdateList.size() << " elemi: " << game->elementInteractionList.size() << std::endl;
|
|
os << "Lua mem: " << scriptInterface.gcGetStats() << " KB" << std::endl;
|
|
|
|
cmDebug->setText(os.str());
|
|
}
|
|
|
|
if (isDeveloperKeys() && fpsText && cmDebug && cmDebug->alpha == 1)
|
|
{
|
|
std::ostringstream os;
|
|
os << "FPS: " << core->fps << " | ROC: " << core->renderObjectCount << " | RC: " << g_dbg_numRenderCalls << " | RES: " << core->resources.size();
|
|
os << " | p: " << core->processedRenderObjectCount << " | t: " << core->totalRenderObjectCount;
|
|
os << " | s: " << dsq->continuity.seconds;
|
|
os << " | sndQ: " << core->dbg_numThreadDecoders;
|
|
os << " | dt: " << core->get_current_dt();
|
|
|
|
|
|
|
|
fpsText->setText(os.str());
|
|
}
|
|
|
|
if (shakeCameraTimer > 0)
|
|
{
|
|
shakeCameraTimer -= dt;
|
|
if (shakeCameraTimer <= 0)
|
|
{
|
|
shakeCameraTimer = 0;
|
|
cameraOffset = Vector(0,0);
|
|
}
|
|
else
|
|
{
|
|
cameraOffset = Vector((rand()%int(shakeCameraMag))-shakeCameraMag/2.0f, (rand()%int(shakeCameraMag))-shakeCameraMag/2.0f);
|
|
}
|
|
}
|
|
|
|
static bool lastfullscreen = false;
|
|
|
|
lastfullscreen = _fullscreen;
|
|
|
|
updatepecue(dt);
|
|
|
|
Network::update();
|
|
|
|
Shot::clearShotGarbage();
|
|
|
|
AquariaGuiElement::UpdateGlobalFocus(dt);
|
|
}
|
|
|
|
|
|
void DSQ::shakeCamera(float mag, float time)
|
|
{
|
|
cameraOffset = Vector(0,0);
|
|
shakeCameraMag = mag;
|
|
shakeCameraTimer = time;
|
|
}
|
|
|
|
bool DSQ::isShakingCamera()
|
|
{
|
|
return (shakeCameraTimer > 0);
|
|
}
|
|
|
|
bool DSQ::isScriptRunning()
|
|
{
|
|
if (nestedMains>1)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void DSQ::delay(float dt)
|
|
{
|
|
core->run(dt);
|
|
}
|
|
|
|
void DSQ::fade(float alpha, float time)
|
|
{
|
|
if (overlay)
|
|
overlay->alpha.interpolateTo(alpha, time,0);
|
|
}
|
|
|
|
void DSQ::toggleCursor(bool v, float time)
|
|
{
|
|
if (!cursor) return;
|
|
float t = time;
|
|
if (time == -1)
|
|
t = 0.1;
|
|
if (!v)
|
|
cursor->alpha.interpolateTo(0, t);
|
|
else
|
|
cursor->alpha.interpolateTo(1, t);
|
|
}
|
|
|
|
void DSQ::playVisualEffect(int vfx, Vector position, Entity *target)
|
|
{
|
|
switch(vfx)
|
|
{
|
|
case VFX_SHOCK:
|
|
{
|
|
|
|
|
|
|
|
core->sound->playSfx("ShockWave");
|
|
|
|
float t =1.0;
|
|
|
|
Quad *q = new Quad;
|
|
q->position = position;
|
|
q->scale = Vector(0,0);
|
|
q->scale.interpolateTo(Vector(5,5),t);
|
|
|
|
q->alpha.ensureData();
|
|
q->alpha.data->path.addPathNode(0, 0);
|
|
q->alpha.data->path.addPathNode(0.75, 0.25);
|
|
q->alpha.data->path.addPathNode(0.75, 0.75);
|
|
q->alpha.data->path.addPathNode(0, 1);
|
|
q->alpha.startPath(t);
|
|
q->setBlendType(RenderObject::BLEND_ADD);
|
|
q->setTexture("particles/EnergyRing");
|
|
if (target)
|
|
q->positionSnapTo = &target->position;
|
|
|
|
game->addRenderObject(q, LR_PARTICLES);
|
|
|
|
if (target && target->getEntityType() == ET_AVATAR)
|
|
if (core->afterEffectManager)
|
|
core->afterEffectManager->addEffect(new ShockEffect(Vector(core->width/2, core->height/2),core->screenCenter,0.08,0.05,22,0.2f, 1.2));
|
|
|
|
t = 0.75;
|
|
{
|
|
Quad *q = new Quad;
|
|
q->position = position;
|
|
q->scale = Vector(0.5,0.5);
|
|
q->scale.interpolateTo(Vector(2,2),t);
|
|
q->alpha.ensureData();
|
|
q->alpha.data->path.addPathNode(0, 0);
|
|
q->alpha.data->path.addPathNode(0.75, 0.25);
|
|
q->alpha.data->path.addPathNode(0.75, 0.75);
|
|
q->alpha.data->path.addPathNode(0, 1);
|
|
q->alpha.startPath(t);
|
|
q->setBlendType(RenderObject::BLEND_ADD);
|
|
q->setTexture("particles/EnergyPart");
|
|
if (target)
|
|
q->positionSnapTo = &target->position;
|
|
q->rotation.z = rand()%360;
|
|
game->addRenderObject(q, LR_PARTICLES);
|
|
}
|
|
}
|
|
break;
|
|
case VFX_SHOCKHIT:
|
|
{
|
|
float t = 1.0;
|
|
{
|
|
Quad *q = new Quad;
|
|
q->position = position;
|
|
q->scale = Vector(1,1);
|
|
q->scale.interpolateTo(Vector(3,3),t);
|
|
q->alpha.ensureData();
|
|
q->alpha.data->path.addPathNode(0, 0);
|
|
q->alpha.data->path.addPathNode(1, 0.3);
|
|
|
|
q->alpha.data->path.addPathNode(0, 1);
|
|
q->alpha.startPath(t);
|
|
q->setBlendType(RenderObject::BLEND_ADD);
|
|
q->rotation.z = rand()%360;
|
|
q->setTexture("particles/EnergyRing");
|
|
|
|
q->rotation.interpolateTo(Vector(0,0,q->rotation.z + 360), t+0.1f);
|
|
game->addRenderObject(q, LR_PARTICLES);
|
|
}
|
|
|
|
t = 0.75;
|
|
{
|
|
Quad *q = new Quad;
|
|
q->position = position;
|
|
q->scale = Vector(1,1);
|
|
q->scale.interpolateTo(Vector(3,3),t);
|
|
q->alpha.ensureData();
|
|
q->alpha.data->path.addPathNode(0, 0);
|
|
q->alpha.data->path.addPathNode(0.8, 0.25);
|
|
|
|
q->alpha.data->path.addPathNode(0, 1);
|
|
q->alpha.startPath(t);
|
|
q->setBlendType(RenderObject::BLEND_ADD);
|
|
|
|
q->setTexture("particles/EnergyDeltas");
|
|
q->rotation.z = rand()%360;
|
|
|
|
game->addRenderObject(q, LR_PARTICLES);
|
|
}
|
|
}
|
|
break;
|
|
case VFX_RIPPLE:
|
|
if (core->afterEffectManager)
|
|
core->afterEffectManager->addEffect(new ShockEffect(Vector(core->width/2, core->height/2),core->screenCenter,0.04,0.06,15,0.2f));
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
void DSQ::addElement(Element *e)
|
|
{
|
|
elements.push_back(e);
|
|
if (e->bgLayer >= 0 && e->bgLayer < 16)
|
|
{
|
|
e->bgLayerNext = firstElementOnLayer[e->bgLayer];
|
|
firstElementOnLayer[e->bgLayer] = e;
|
|
}
|
|
else
|
|
{
|
|
e->bgLayerNext = 0;
|
|
}
|
|
}
|
|
|
|
void DSQ::modifyDt(float &dt)
|
|
{
|
|
if (isDeveloperKeys())
|
|
{
|
|
if (core->getKeyState(KEY_G))
|
|
{
|
|
if(core->getShiftState())
|
|
dt *= 10;
|
|
else
|
|
dt *= 4;
|
|
}
|
|
else if (core->getKeyState(KEY_F))
|
|
{
|
|
if (core->getShiftState())
|
|
dt *= 0.1f;
|
|
else
|
|
dt *= 0.6;
|
|
}
|
|
else if (core->getKeyState(KEY_H))
|
|
dt = FRAME_TIME;
|
|
else
|
|
{
|
|
// frame cap
|
|
if (dt > FRAME_TIME)
|
|
dt = FRAME_TIME;
|
|
}
|
|
if (core->getKeyState(KEY_H))
|
|
stopVoice();
|
|
}
|
|
else
|
|
{
|
|
if (dt > FRAME_TIME)
|
|
dt = FRAME_TIME;
|
|
}
|
|
|
|
if (skippingCutscene)
|
|
dt = 0.07f;
|
|
|
|
gameSpeed.update(dt);
|
|
dt *= gameSpeed.x;
|
|
|
|
if (frameOutputMode)
|
|
{
|
|
dt = 1.0f/60.0f;
|
|
doScreenshot = true;
|
|
}
|
|
|
|
if (dsq->demo.mode == Demo::DEMOMODE_RECORD)
|
|
{
|
|
dt = 1.0f/60.0f;
|
|
}
|
|
}
|
|
|
|
void DSQ::removeElement(Element *element)
|
|
{
|
|
for (int i = 0; i < dsq->elements.size(); i++)
|
|
{
|
|
if (dsq->elements[i] == element)
|
|
{
|
|
removeElement(i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
// only happens in editor, no need to optimize
|
|
void DSQ::removeElement(int idx)
|
|
{
|
|
ElementContainer copy = elements;
|
|
clearElements();
|
|
int i = 0;
|
|
for (i = 0; i < idx; i++)
|
|
{
|
|
addElement(copy[i]);
|
|
}
|
|
for (i = idx+1; i < copy.size(); i++)
|
|
{
|
|
addElement(copy[i]);
|
|
}
|
|
copy.clear();
|
|
|
|
if (!dsq->game->elementUpdateList.empty())
|
|
dsq->game->rebuildElementUpdateList();
|
|
}
|
|
|
|
void DSQ::clearElements()
|
|
{
|
|
elements.clear();
|
|
for (int i = 0; i < 16; i++)
|
|
firstElementOnLayer[i] = 0;
|
|
}
|
|
|
|
|
|
void DSQ::addEntity(Entity *entity)
|
|
{
|
|
int i;
|
|
for (i = 0; entities[i] != 0; i++) {}
|
|
if (i+1 >= entities.size())
|
|
entities.resize(entities.size()*2, 0);
|
|
entities[i] = entity;
|
|
entities[i+1] = 0;
|
|
}
|
|
|
|
void DSQ::removeEntity(Entity *entity)
|
|
{
|
|
int i;
|
|
for (i = 0; entities[i] != 0; i++)
|
|
{
|
|
if (entities[i] == entity)
|
|
break;
|
|
}
|
|
for (; entities[i] != 0; i++)
|
|
{
|
|
entities[i] = entities[i+1];
|
|
}
|
|
}
|
|
|
|
void DSQ::clearEntities()
|
|
{
|
|
const int size = entities.size();
|
|
int i;
|
|
for (i = 0; i < size; i++)
|
|
{
|
|
entities[i] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
std::string DSQ::getSaveDirectory()
|
|
{
|
|
return getUserDataFolder() + "/save";
|
|
}
|
|
|
|
ParticleEffect *DSQ::spawnParticleEffect(const std::string &name, Vector position, float rotz, float t, int layer, float follow)
|
|
{
|
|
if (name.empty())
|
|
return NULL;
|
|
if (t!=0)
|
|
{
|
|
PECue p(name, position, rotz, t);
|
|
pecue.push_back(p);
|
|
return NULL;
|
|
}
|
|
|
|
ParticleEffect *e = core->createParticleEffect(name, position, layer, rotz);
|
|
e->followCamera = follow;
|
|
return e;
|
|
}
|
|
|
|
void DSQ::spawnAllIngredients(const Vector &position)
|
|
{
|
|
continuity.spawnAllIngredients(position);
|
|
}
|
|
|
|
void DSQ::updatepecue(float dt)
|
|
{
|
|
if (!core->particlesPaused)
|
|
{
|
|
|
|
int nz = 0;
|
|
for (int i = 0; i < pecue.size(); i++)
|
|
{
|
|
PECue *p = &pecue[i];
|
|
if (p->t > 0)
|
|
{
|
|
p->t -= dt;
|
|
if (p->t < 0)
|
|
{
|
|
p->t = 0;
|
|
spawnParticleEffect(p->name, p->pos, p->rot, 0);
|
|
}
|
|
nz ++;
|
|
}
|
|
}
|
|
// lazy ass delete
|
|
if (nz == 0)
|
|
{
|
|
pecue.clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
void AquariaScreenTransition::capture()
|
|
{
|
|
assert(screen_texture);
|
|
this->alpha = 0;
|
|
InterpolatedVector oldAlpha = dsq->cursor->alpha;
|
|
dsq->cursor->alpha.x = 0;
|
|
int width=0, height=0;
|
|
core->render();
|
|
|
|
width = core->getWindowWidth();
|
|
height = core->getWindowHeight();
|
|
|
|
glBindTexture(GL_TEXTURE_2D,screen_texture);
|
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
|
|
|
|
|
|
dsq->cursor->alpha = oldAlpha;
|
|
core->render();
|
|
core->showBuffer();
|
|
|
|
this->alpha = 1;
|
|
//ScreenTransition::capture();
|
|
}
|
|
|
|
void DSQ::setCutscene(bool on, bool canSkip)
|
|
{
|
|
inCutscene = on;
|
|
_canSkipCutscene = canSkip;
|
|
}
|
|
|
|
bool DSQ::canSkipCutscene()
|
|
{
|
|
return _canSkipCutscene;
|
|
}
|
|
|
|
bool DSQ::isSkippingCutscene()
|
|
{
|
|
return skippingCutscene;
|
|
}
|
|
|
|
bool DSQ::isInCutscene()
|
|
{
|
|
return inCutscene;
|
|
}
|
|
|
|
bool DSQ::isCutscenePaused()
|
|
{
|
|
return cutscenePaused;
|
|
}
|
|
|
|
void DSQ::pauseCutscene(bool on)
|
|
{
|
|
cutscenePaused = on;
|
|
|
|
cutsceneEffects(on);
|
|
}
|
|
|
|
void DSQ::cutsceneEffects(bool on)
|
|
{
|
|
if (cutscene_bg && cutscene_text && cutscene_text2)
|
|
{
|
|
if (canSkipCutscene())
|
|
{
|
|
cutscene_text->offset = Vector(0, -10);
|
|
cutscene_text2->offset = Vector(0, -10);
|
|
}
|
|
else
|
|
{
|
|
cutscene_text->offset = Vector(0,0);
|
|
cutscene_text2->offset = Vector(0,0);
|
|
}
|
|
cutscene_bg->alpha.x = on?1:0;
|
|
cutscene_text->alpha.x = on?1:0;
|
|
cutscene_text2->alpha.x = (on&&dsq->canSkipCutscene())?1:0;
|
|
}
|
|
}
|
|
|
|
void DSQ::onBackgroundUpdate()
|
|
{
|
|
Network::update();
|
|
Core::onBackgroundUpdate();
|
|
}
|
|
|
|
void DSQ::resetLayerPasses()
|
|
{
|
|
for(size_t i = 0; i < renderObjectLayers.size(); ++i)
|
|
{
|
|
renderObjectLayers[i].startPass = 0;
|
|
renderObjectLayers[i].endPass = 0;
|
|
}
|
|
renderObjectLayers[LR_ENTITIES].startPass = -2;
|
|
renderObjectLayers[LR_ENTITIES].endPass = 5;
|
|
}
|
|
|
|
bool DSQ::isMiniMapCursorOkay()
|
|
{
|
|
return ((inputMode != INPUT_MOUSE) || (!game->miniMapRender || !game->miniMapRender->isCursorIn()));
|
|
}
|
|
|
|
void DSQ::onJoystickAdded(int deviceID)
|
|
{
|
|
Core::onJoystickAdded(deviceID);
|
|
fixupJoysticks();
|
|
}
|
|
|
|
void DSQ::onJoystickRemoved(int instanceID)
|
|
{
|
|
Core::onJoystickRemoved(instanceID);
|
|
fixupJoysticks();
|
|
}
|
|
|
|
void DSQ::fixupJoysticks()
|
|
{
|
|
for(int i = 0; i < getNumJoysticks(); ++i)
|
|
if(Joystick *j = getJoystick(i))
|
|
j->setEnabled(false);
|
|
|
|
for(size_t i = 0; i < user.control.actionSets.size(); ++i)
|
|
{
|
|
ActionSet& as = user.control.actionSets[i];
|
|
as.updateJoystick();
|
|
}
|
|
|
|
// HACK: why here? kinda dirty, but the joystick ID needs to be propagated
|
|
importActionButtons();
|
|
}
|
|
|
|
void DSQ::initActionButtons()
|
|
{
|
|
clearActionButtons();
|
|
|
|
std::vector<int> allkeys;
|
|
// Don't need joysticks keys for this
|
|
for(int i = 0; i < MOUSE_BUTTON_EXTRA_END; ++i)
|
|
allkeys.push_back(i);
|
|
|
|
// create sentinel
|
|
ActionButtonStatus *allbtn = new ActionButtonStatus;
|
|
allbtn->importQuery(&allkeys[0], allkeys.size());
|
|
actionStatus.push_back(allbtn);
|
|
|
|
// create the rest
|
|
for(size_t i = 0; i < user.control.actionSets.size(); ++i)
|
|
actionStatus.push_back(new ActionButtonStatus);
|
|
|
|
importActionButtons();
|
|
}
|
|
|
|
void DSQ::importActionButtons()
|
|
{
|
|
assert(user.control.actionSets.size()+1 == actionStatus.size());
|
|
|
|
// ignore sentinel
|
|
for(size_t i = 1; i < actionStatus.size(); ++i)
|
|
{
|
|
const ActionSet& as = user.control.actionSets[i-1];
|
|
ActionButtonStatus *abs = actionStatus[i];
|
|
abs->import(as);
|
|
}
|
|
}
|