/* 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/Gradient.h" #include "../BBGE/AfterEffect.h" #include "../BBGE/MathFunctions.h" #include "../BBGE/DebugFont.h" #include "../BBGE/LensFlare.h" #include "../BBGE/RoundedRect.h" #include "../BBGE/SimpleIStringStream.h" #include "Game.h" #include "GridRender.h" #include "WaterSurfaceRender.h" #include "ScriptedEntity.h" #include "AutoMap.h" #include "FlockEntity.h" #include "SchoolFish.h" #include "Avatar.h" #include "Shot.h" #include "Web.h" #include "StatsAndAchievements.h" #include "ToolTip.h" std::vector allowedMaps; const int PATH_ACTIVATION_RANGE = 800; Vector worldLeftCenter(217,250), worldRightCenter(575, 250); Vector opt_save_original = Vector(350, 350), opt_cancel_original = Vector(450, 350); const float bgSfxVol = 1.0; const float MENUPAGETRANSTIME = 0.2; // 0.2 const int foodPageSize = 16; const int treasurePageSize = 16; int FoodSlot::foodSlotIndex = -1; int selectedTreasureFlag = -1; std::vector foodHolders; std::vector petSlots; std::string getSceneFilename(const std::string &scene) { if (dsq->mod.isActive()) return std::string(dsq->mod.getPath() + "maps/" + scene + ".xml"); else return std::string("data/maps/"+scene+".xml"); return ""; } PetSlot::PetSlot(int pet) : AquariaGuiQuad() { PetData *p = dsq->continuity.getPetData(pet); if (p) { std::string fn = "collectibles/egg-" + p->namePart; setTexture(fn); } scale = Vector(0.9, 0.9); petidx = pet; mouseDown = false; petFlag = FLAG_PET_NAMESTART + petidx; wasSlot = false; } void PetSlot::onUpdate(float dt) { AquariaGuiQuad::onUpdate(dt); if (!dsq->continuity.getFlag(petFlag)) { if (!wasSlot) { setTexture("gui/wok"); setWidthHeight(80); wasSlot = true; } //alphaMod = 0; return; } else { alphaMod = 1; if (wasSlot) { PetData *p = dsq->continuity.getPetData(petidx); if (p) { std::string fn = "collectibles/egg-" + p->namePart; setTexture(fn); } wasSlot = false; } } if (dsq->continuity.getFlag(FLAG_PET_ACTIVE) == petFlag) { color = Vector(1,1,1); } else color = Vector(0.5, 0.5, 0.5); if (alpha.x < 1) return; if ((core->mouse.position - getWorldPosition()).isLength2DIn(32)) { scale.interpolateTo(Vector(1.2, 1.2), 0.1); if (core->mouse.buttons.left && !mouseDown) { mouseDown = true; } else if (!core->mouse.buttons.left && mouseDown) { dsq->sound->playSfx("click"); if (dsq->continuity.getFlag(FLAG_PET_ACTIVE) == petFlag) { dsq->game->setActivePet(0); dsq->sound->playSfx("pet-on"); } else { dsq->game->setActivePet(FLAG_PET_NAMESTART + petidx); dsq->sound->playSfx("pet-off"); } mouseDown = false; } } else { mouseDown = false; scale.interpolateTo(Vector(0.9, 0.9), 0.1); } } FoodHolder::FoodHolder(int slot, bool trash) : Quad(), slot(slot), trash(trash) { foodHolderIngredient = 0; buttonDown = false; //setTexture("Gui/wok"); renderQuad = false; wok = new Quad; if (trash) wok->setTexture("gui/wok-drop"); else wok->setTexture("gui/wok"); addChild(wok, PM_POINTER, RBP_ON); ing = new Quad; ing->renderQuad = false; addChild(ing, PM_POINTER); lid = new Quad("gui/wok-lid", Vector(0,0)); lid->alpha = 0; lid->alphaMod = 0.5; addChild(lid, PM_POINTER); } void FoodHolder::animateLid(bool down, bool longAnim) { float t = 0.2; if (!longAnim) { t = 0.1; } if (down) { dsq->sound->playSfx("bubble-lid"); lid->alpha.interpolateTo(1, t); dsq->main(t); } else { lid->alpha.interpolateTo(0, t); } } bool FoodHolder::isTrash() { return trash; } bool FoodHolder::isEmpty() { return (foodHolderIngredient == 0); } IngredientData *FoodHolder::getIngredient() { return foodHolderIngredient; } void FoodHolder::setIngredient(IngredientData *i, bool effects) { IngredientData *oldi = foodHolderIngredient; foodHolderIngredient = i; if (oldi) { if (oldi->held > 0) oldi->held --; oldi->amount ++; } if (!i) { //ing->scale.interpolateTo(Vector(0,0), 0.1); ing->renderQuad = false; //setTexture("Gui/wok"); if (oldi && effects) { core->sound->playSfx("Drop"); } game->enqueuePreviewRecipe(); } else { i->held ++; if (i->amount > 0) i->amount --; ing->setTexture("Ingredients/" + i->gfx); ing->renderQuad = true; if (effects) { core->sound->playSfx("Wok"); ing->scale.ensureData(); ing->scale.data->path.clear(); ing->scale.data->path.addPathNode(Vector(1,1),0); ing->scale.data->path.addPathNode(Vector(1.25,1.25), 0.2); ing->scale.data->path.addPathNode(Vector(1,1),1); ing->scale.startPath(0.5); } game->enqueuePreviewRecipe(); } } void Game::enqueuePreviewRecipe() { enqueuedPreviewRecipe = 1; } void Game::updatePreviewRecipe() { const float t = 0.2; updateCookList(); if (cookList.size() < 2 || recipeMenu.on){ previewRecipe->alpha.interpolateTo(0, t); } else{ Recipe *r = findRecipe(cookList); IngredientData *data=0; if (r && r->isKnown()) { data = dsq->continuity.getIngredientDataByName(r->result); previewRecipe->setTexture("ingredients/"+data->gfx); } else { previewRecipe->setTexture("gui/question-mark"); } previewRecipe->alpha.interpolateTo(1, t); } } void FoodHolder::dropFood() { if (foodHolderIngredient) { setIngredient(0); dsq->game->refreshFoodSlots(true); } } void FoodHolder::onUpdate(float dt) { Quad::onUpdate(dt); if (!dsq->game->recipeMenu.on && foodHolderIngredient) { if ((core->mouse.position - getWorldPosition()).isLength2DIn(20)) { if (!buttonDown && core->mouse.buttons.left) { dropFood(); buttonDown = true; } } if (!buttonDown && core->mouse.buttons.left) buttonDown = true; if (buttonDown && !core->mouse.buttons.left) buttonDown = false; } } FoodSlot::FoodSlot(int slot) : AquariaGuiQuad(), slot(slot) { doubleClickDelay = 0; right = false; renderQuad = false; label = new DebugFont(8, ""); label->position = Vector(-2, 9); addChild(label, PM_POINTER); inCookSlot = false; ingredient = 0; lastIngredient = 0; lastAmount = 0; grabTime = 0; foodSlotIndex = -1; scaleFactor = 1; shareAlphaWithChildren = 1; rmb = 0; } void FoodSlot::setOriginalPosition(const Vector &op) { originalPosition = op; } void FoodSlot::toggle(bool f) { if (f) { alpha = 1; alphaMod = 1; label->alpha = 1; } else { alpha = 0; alphaMod = 0; label->alpha = 0; } } void FoodSlot::refresh(bool effects) { int offset = game->currentFoodPage*foodPageSize; IngredientData *i = dsq->continuity.getIngredientHeldByIndex(offset+slot); if (i) { ingredient = i; if (i->amount > 0) { std::ostringstream os; if (i->amount > 1) os << i->amount << "/" << MAX_INGREDIENT_AMOUNT; label->setText(os.str()); setTexture("Ingredients/" + i->gfx); renderQuad = true; } else { label->setText(""); renderQuad = true; setTexture("gui/wok"); setWidthHeight(64); } } else { ingredient = 0; label->setText(""); renderQuad = true; setTexture("gui/wok"); setWidthHeight(64); } scale.interpolateTo(Vector(1,1)*scaleFactor,0.001); if (ingredient != 0 && (i != lastIngredient || (i && i->amount != lastAmount))) { if (effects) { scale.ensureData(); scale.data->path.clear(); scale.data->path.addPathNode(Vector(1,1)*scaleFactor,0); scale.data->path.addPathNode(Vector(1.5,1.5)*scaleFactor, 0.2); scale.data->path.addPathNode(Vector(1,1)*scaleFactor,1); scale.startPath(0.5); } } lastIngredient = i; if (i) lastAmount = i->amount; else lastAmount = 0; } void FoodSlot::eatMe() { if (ingredient && !dsq->isNested()) { for (int i = 0; i < foodHolders.size(); i++) { if (!foodHolders[i]->isTrash() && !foodHolders[i]->isEmpty()) { dsq->sound->playSfx("denied"); foodHolders[i]->dropFood(); return; } } if (!ingredient->effects.empty()) { ingredient->amount--; dsq->continuity.applyIngredientEffects(ingredient); dsq->continuity.removeEmptyIngredients(); dsq->game->refreshFoodSlots(true); } else { dsq->sound->playSfx("denied"); /// don't } } } void FoodSlot::moveRight() { if (!ingredient) return; if (ingredient->amount <= 0) return; for (int i = foodHolders.size()-1; i >= 0; i--) { if (foodHolders[i]->alpha.x > 0 && foodHolders[i]->alphaMod > 0 && foodHolders[i]->isEmpty() && !foodHolders[i]->isTrash()) { foodHolders[i]->setIngredient(ingredient); inCookSlot = true; refresh(true); break; } } } void FoodSlot::discard() { if (!ingredient) return; if (ingredient->amount <= 0) return; ingredient->amount--; dsq->game->dropIngrNames.push_back(ingredient->name); dsq->continuity.removeEmptyIngredients(); dsq->game->refreshFoodSlots(true); } bool FoodSlot::isCursorIn() { return (core->mouse.position - getWorldPosition()).isLength2DIn(32); } void FoodSlot::onUpdate(float dt) { AquariaGuiQuad::onUpdate(dt); if (doubleClickDelay > 0) { doubleClickDelay -= dt; if (doubleClickDelay < 0) doubleClickDelay = 0; } if (alphaMod==1 && ingredient && ingredient->amount > 0) { if (foodSlotIndex == slot) { //grabTime += dt; if (!core->mouse.buttons.left) { foodSlotIndex = -1; //if (ingredient->type < IT_FOOD) //if (grabTime > 0.5f) if (!dsq->game->recipeMenu.on) { /* dsq->game->removeRenderObject(this); dsq->game->addRenderObject(this, LR_MENU); */ Vector wp = getWorldPosition(); if ((dsq->game->lips->getWorldPosition() - getWorldPosition()).isLength2DIn(32)) { dsq->menuSelectDelay = 0.5; eatMe(); } else if (wp.x < 40 || wp.y < 40 || wp.x > 760 || wp.y > 560) { discard(); } else { bool droppedIn = false; for (int i = 0; i < foodHolders.size(); i++) { bool in = (foodHolders[i]->getWorldPosition() - getWorldPosition()).isLength2DIn(32); if (in) { droppedIn = true; if (foodHolders[i]->isTrash()) { discard(); dsq->game->foodLabel->alpha.interpolateTo(0, 2); dsq->game->foodDescription->alpha.interpolateTo(0, 2); break; //return; } else if (foodHolders[i]->isEmpty()) { foodHolders[i]->setIngredient(ingredient); inCookSlot = true; refresh(true); break; } } } if (!droppedIn) { if (doubleClickDelay > 0) { dsq->menuSelectDelay = 0.5; doubleClickDelay = 0; eatMe(); //if (!originalPosition.isZero()) position = originalPosition; label->alpha = 1; grabTime = 0; if (dsq->inputMode == INPUT_JOYSTICK) { dsq->game->adjustFoodSlotCursor(); } return; } else { doubleClickDelay = DOUBLE_CLICK_DELAY; } } } } /* else { if (ingredient) debugLog(splitCamelCase(ingredient->name)); } */ //if (!originalPosition.isZero()) position = originalPosition; label->alpha = 1; grabTime = 0; } else { if (!dsq->game->recipeMenu.on) { if (dsq->inputMode == INPUT_MOUSE) { Vector diff = core->mouse.position - getWorldPosition(); position += diff; dsq->game->moveFoodSlotToFront = this; } } //position = parent->getWorldCollidePosition(core->mouse.position); //position = core->mouse.position; } } if ((core->mouse.position - getWorldPosition()).isLength2DIn(16)) //if (isCursorIn()) { dsq->game->foodLabel->setText(ingredient->displayName); dsq->game->foodLabel->alpha.interpolateTo(1, 0.2); dsq->game->foodDescription->setText(dsq->continuity.getIngredientAffectsString(ingredient)); dsq->game->foodDescription->alpha.interpolateTo(1, 0.2); if (core->mouse.buttons.left && foodSlotIndex == -1) { grabTime = 0; foodSlotIndex = slot; label->alpha = 0; /* dsq->game->removeRenderObject(this); dsq->game->addRenderObject(this, LR_HUD); */ if (!inCookSlot) { originalPosition = position; } } if (core->mouse.buttons.right && !rmb) { rmb = 1; } else if (!core->mouse.buttons.right && rmb) { rmb = 0; if (!game->recipeMenu.on) moveRight(); return; } /* if (core->mouse.buttons.right && !right) { right = true; } else if (!core->mouse.buttons.right && right) { right = false; bool dropped = false; for (int i = foodHolders.size()-1; i >= 0; i--) { if (foodHolders[i]->alpha.x > 0 && foodHolders[i]->alphaMod > 0 && foodHolders[i]->isEmpty() && !foodHolders[i]->isTrash()) { foodHolders[i]->setIngredient(ingredient); inCookSlot = true; refresh(); dropped = true; break; } } if (dropped) { } else { core->sound->playSfx("denied"); } } */ } else { if (!dsq->game->foodLabel->alpha.isInterpolating()) dsq->game->foodLabel->alpha.interpolateTo(0, 2); if (!dsq->game->foodDescription->alpha.isInterpolating()) dsq->game->foodDescription->alpha.interpolateTo(0, 2); rmb = 0; } } else { rmb = 0; } } SongSlot::SongSlot(int songSlot) : AquariaGuiQuad(), songSlot(songSlot) { songType = dsq->continuity.getSongTypeBySlot(songSlot); std::ostringstream os; os << "Song/SongSlot-" << songSlot; setTexture(os.str()); glow = new Quad("particles/glow", Vector(0,0)); glow->setWidthHeight(128, 128); glow->setBlendType(RenderObject::BLEND_ADD); glow->alpha = 0; addChild(glow, PM_POINTER); mbDown = false; if (dsq->continuity.isSongTypeForm((SongType)dsq->continuity.getSongTypeBySlot(songSlot))) scale = Vector(0.9, 0.9); else scale = Vector(0.6, 0.6); } void SongSlot::onUpdate(float dt) { AquariaGuiQuad::onUpdate(dt); if (alpha.x == 1 && alphaMod == 1 && (!parent || parent->alpha.x == 1)) { if ((core->mouse.position - getWorldPosition()).isLength2DIn(24)) { dsq->game->playSongInMenu(songType); dsq->game->songLabel->setText(dsq->continuity.getSongNameBySlot(songSlot)); dsq->game->songLabel->alpha.interpolateTo(1, 0.2); const bool anyButton = core->mouse.buttons.left || core->mouse.buttons.right; if (!mbDown && anyButton) { mbDown = true; } else if (mbDown && !anyButton) { mbDown = false; dsq->game->playSongInMenu(songType, 1); if (!dsq->sound->isPlayingVoice()) dsq->voice(dsq->continuity.getVoxForSongSlot(songSlot)); //dsq->game->songDescription->setText(dsq->continuity.getDescriptionForSongSlot(songSlot)); } glow->alpha.interpolateTo(0.2, 0.15); } else { mbDown = false; glow->alpha.interpolateTo(0, 0.2); if (!dsq->game->songLabel->alpha.isInterpolating()) { dsq->game->songLabel->alpha.interpolateTo(0, 2); /* dsq->game->songLabel->alpha.path.addPathNode(dsq->game->songLabel->alpha, 0); dsq->game->songLabel->alpha.path.addPathNode(dsq->game->songLabel->alpha, 0.5); dsq->game->songLabel->alpha.path.addPathNode(0, 1); dsq->game->songLabel->alpha.startPath(3); */ } } } } const int treasureFlagStart = 500; TreasureSlot::TreasureSlot(int index) : AquariaGuiQuad() { this->index = index; mbd = false; flag = 0; doubleClickTimer = 0; } void TreasureSlot::onUpdate(float dt) { AquariaGuiQuad::onUpdate(dt); doubleClickTimer -= dt; if (doubleClickTimer < 0) doubleClickTimer = 0; if (alphaMod == 1 && alpha.x == 1 && flag != 0) { if ((core->mouse.position - getWorldPosition()).isLength2DIn(18)) { scale.interpolateTo(Vector(1.2, 1.2), 0.1); if (core->mouse.buttons.left && !mbd) { mbd = true; } else if (!core->mouse.buttons.left && mbd) { mbd = false; if (doubleClickTimer > 0) { doubleClickTimer = 0; dsq->game->onUseTreasure(flag); } else { dsq->sound->playSfx("treasure-select", 0.5); dsq->spawnParticleEffect("menu-switch", worldRightCenter, 0, 0, LR_HUD3, 1); dsq->game->treasureLabel->setText(treasureName); dsq->game->treasureLabel->alpha = 1; dsq->game->treasureCloseUp->setTexture(dsq->continuity.treasureData[flag].gfx); //dsq->game->treasureCloseUp->scale = Vector(dsq->continuity.treasureData[flag].sz, dsq->continuity.treasureData[flag].sz); dsq->game->treasureCloseUp->alpha = 1; dsq->game->treasureDescription->setText(treasureDesc, Vector(400,450), 400); dsq->game->treasureDescription->alpha = 1; dsq->game->use->alpha = dsq->continuity.treasureData[flag].use; /* dsq->game->treasureCloseUp->scale = Vector(0.5,0.5); dsq->game->treasureCloseUp->scale.interpolateTo(Vector(1,1), 0.2); dsq->game->treasureCloseUp->alpha = 0.1; dsq->game->treasureCloseUp->alpha.interpolateTo(1, 0.2); */ selectedTreasureFlag = flag; doubleClickTimer = 0.2; std::ostringstream os; os << "treasure flag: " << flag << " desc: " << treasureDesc; debugLog(os.str()); } } } else { mbd = false; scale.interpolateTo(Vector(1, 1), 0.1); } } else { mbd = false; scale.interpolateTo(Vector(1, 1), 0.001); } } void TreasureSlot::refresh() { flag = (game->currentTreasurePage*treasurePageSize) + index + treasureFlagStart; if (flag >= FLAG_COLLECTIBLE_START && flag < FLAG_COLLECTIBLE_END && dsq->continuity.getFlag(flag)>0) { // get treasure image somehow setTexture(dsq->continuity.treasureData[flag].gfx); float scl = dsq->continuity.treasureData[flag].sz; float w = width; float h = height; float sz = 50; if (w > h) { w = sz; h = (height*sz)/width; } else { h = sz; w = (width*sz)/height; } setWidthHeight(w*scl, h*scl); std::string parse = dsq->continuity.stringBank.get(flag); int p1 = parse.find_first_of('['); if (p1 != std::string::npos) { p1++; int p2 = parse.find_first_of(']'); treasureName = parse.substr(p1,p2-p1); p1 = parse.find_last_of('['); if (p1 != std::string::npos) { p1++; p2 = parse.find_last_of(']'); treasureDesc = parse.substr(p1,p2-p1); } } alphaMod = 1; } else { flag = 0; alphaMod = 1; setTexture("gui/wok"); setWidthHeight(48); //alphaMod = 0; } } Ingredient *Game::getNearestIngredient(const Vector &pos, int radius) { int closest = -1; int r2 = sqr(radius); Ingredient *returnIngredient = 0; for (Ingredients::iterator i = ingredients.begin(); i != ingredients.end(); i++) { int len = (pos - (*i)->position).getSquaredLength2D(); if (len <= r2 && (closest == - 1 || len < closest)) { closest = len; returnIngredient = (*i); } } return returnIngredient; } Entity *Game::getNearestEntity(const Vector &pos, int radius, Entity *ignore, EntityType et, DamageType dt, int lrStart, int lrEnd) { int sqrRadius = radius*radius; Entity *closest = 0; int sml=-1; int dist = 0; FOR_ENTITIES(i) { Entity *e = *i; dist = (e->position - pos).getSquaredLength2D(); if (dist <= sqrRadius) { if (e != ignore && e->isPresent()) { if (lrStart == -1 || lrEnd == -1 || (e->layer >= lrStart && e->layer <= lrEnd)) { if (et == ET_NOTYPE || e->getEntityType() == et) { if (dt == DT_NONE || e->isDamageTarget(dt)) { if (sml == -1 || dist < sml) { closest = e; sml = dist; } } } } } } } return closest; } /* class Avatar : public Entity { public: Vector position, myZoom; void clampPosition(); Entity *convoEntity; std::string convoToRun; Entity *attachedTo; Quad *burstBar; int health; bool isCharging(); bool isEntityDead(); int maxHealth, mana, maxMana; bool zoomOverriden; }; */ /* #include "JetStream.h" #include "Rock.h" #include "SchoolFish.h" */ /* #include "Game.h" #include "AfterEffect.h" #include "Button.h" #include "TextBox.h" #include "LightShaft.h" #include "Item.h" #include "Elements.h" #include "WavyWeed.h" #include "BitmapFont.h" #include "ParticleEffects.h" // SPECIAL */ Vector menuBgScale; const int ITEMS_PER_PAGE = 12; ObsRow::ObsRow(int tx, int ty, int len) : tx(tx), ty(ty), len(len) { } int Game::getNumberOfEntitiesNamed(const std::string &name) { int c = 0; FOR_ENTITIES(i) { Entity *e = *i; if (e->life == 1 && (nocasecmp(e->name, name)==0)) c++; } return c; } void Game::playSongInMenu(int songType, bool override) { if (playingSongInMenu == -1 || override) { playingSongInMenu = songType; currentSongMenuNote = 0; songMenuPlayDelay = 0.5; } } void Game::flipRenderObjectVertical(RenderObject *r, int flipY) { if (r->position.y < flipY) r->position.y = flipY + (flipY-r->position.y); else r->position.y = flipY - (r->position.y-flipY); } bool Game::isSceneFlipped() { return sceneFlipped; } void Game::flipSceneVertical(int flipY) { sceneFlipped = !sceneFlipped; dsq->screenTransition->capture(); dsq->render(); dsq->screenTransition->go(1); FOR_ENTITIES(itr) { Entity *e = *itr; flipRenderObjectVertical(e, flipY); } int i = 0; int flipTY = (flipY/TILE_SIZE)-1; for (i = 0; i < obsRows.size(); i++) { if (obsRows[i].ty < flipTY) obsRows[i].ty = flipTY + (flipTY - obsRows[i].ty); else obsRows[i].ty = flipTY - (obsRows[i].ty - flipTY); } for (i = 0; i < dsq->getNumElements(); i++) { Element *e = dsq->getElement(i); e->rotation.z = 180-e->rotation.z; flipRenderObjectVertical(e, flipY); } /* // DUMBASS: avatar is an entity.. it has already been flipped! if (dsq->game->avatar) { flipRenderObjectVertical(dsq->game->avatar, flipY); dsq->game->avatar->clampPosition(); dsq->game->avatar->update(0.03); } */ reconstructGrid(); FOR_ENTITIES(i) { Entity *e = *i; e->onSceneFlipped(); } reconstructGrid(); if (cameraFollow) warpCameraTo(*cameraFollow); dsq->resetTimer(); } void Game::setMenuDescriptionText(const std::string &text) { menuDescription->setText(text); } Game *game = 0; Ingredient *Game::spawnIngredient(const std::string &ing, const Vector &pos, int times, int out) { std::string use = ing; Ingredient *i = 0; for (int c = 0; c < times; c++) { //HACK: if (nocasecmp(ing, "poultice")==0) use = "LeafPoultice"; IngredientData *d = dsq->continuity.getIngredientDataByName(use); if (d) { i = new Ingredient(pos, d); ingredients.push_back(i); if (out) { /* if (i->velocity.y > i->velocity.x) { i->velocity.x = i->velocity.y; i->velocity.y = -500; } if (i->velocity.y > 0) i->velocity.y *= -1; */ i->velocity.x = 0; i->velocity.y = -500; } establishEntity(i); //addRenderObject(i, LR_ENTITIES); } else { debugLog("Could not find ingredient data for [" + use + "]"); } } return i; } void Game::spawnIngredientFromEntity(Entity *ent, IngredientData *data) { Ingredient *i = new Ingredient(ent->position, data); ingredients.push_back(i); establishEntity(i); //addRenderObject(i, LR_ENTITIES); } Game::Game() : StateObject() { applyingState = false; blurEffectsCheck = 0; ripplesCheck = 0; cookDelay = 0; #if defined(AQUARIA_DEMO) allowedMaps.push_back("naijacave"); allowedMaps.push_back("trainingcave"); allowedMaps.push_back("mainarea"); allowedMaps.push_back("vedhacave"); allowedMaps.push_back("openwater02"); allowedMaps.push_back("energytemple01"); allowedMaps.push_back("energytemple02"); allowedMaps.push_back("energytemple03"); allowedMaps.push_back("energytemple04"); allowedMaps.push_back("energytemple05"); allowedMaps.push_back("energytemple06"); allowedMaps.push_back("songcave"); allowedMaps.push_back("songcave02"); allowedMaps.push_back("title"); allowedMaps.push_back("energytemplevision"); #endif hasPlayedLow = false; invincibleOnNested = true; activation = false; invinciblity = false; active = false; registerState(this, "Game"); optionsOnly = false; toFlip = -1; shuttingDownGameState = false; dsq->loops.bg = BBGE_AUDIO_NOCHANNEL; dsq->loops.bg2 = BBGE_AUDIO_NOCHANNEL; loadingScene = false; controlHint_mouseLeft = controlHint_mouseRight = controlHint_mouseMiddle = controlHint_mouseBody = controlHint_bg = 0; controlHint_text = 0; avatar = 0; fromVel = Vector(0,-1); currentInventoryPage = 0; deathTimer = 0; game = this; elementWithMenu = 0; cameraFollow = 0; worldMapRender = 0; for (int i = 0; i < PATH_MAX; i++) firstPathOfType[i] = 0; loadEntityTypeList(); lastCollideMaskIndex = -1; worldPaused = false; } Game::~Game() { tileCache.clean(); game = 0; } /* void Game::doChoiceMenu(Vector position, std::vector choices) { dsq->gui.openChoiceMenu(position); for (int i = 0; i < choices.size(); i++) { dsq->gui.choiceMenu.addEntry(choices[i]); } selectedChoice = ""; while (selectedChoice.empty()) { dsq->delay(10); } dsq->gui.closeChoiceMenu(); } */ /* void Game::onAssignMenuScreenItemToSlot0() { if (!dsq->continuity.hudVisible) return; if (!selectedMenuScreenItem) return; dsq->continuity.setItemSlot(0, selectedMenuScreenItem->getItemIndex()); } void Game::onAssignMenuScreenItemToSlot1() { if (!dsq->continuity.hudVisible) return; if (!selectedMenuScreenItem) return; dsq->continuity.setItemSlot(1, selectedMenuScreenItem->getItemIndex()); } void Game::onAssignMenuScreenItemToSlot2() { if (!dsq->continuity.hudVisible) return; if (!selectedMenuScreenItem) return; dsq->continuity.setItemSlot(2, selectedMenuScreenItem->getItemIndex()); } void Game::onAssignMenuScreenItemToSlot3() { if (!dsq->continuity.hudVisible) return; if (!selectedMenuScreenItem) return; dsq->continuity.setItemSlot(3, selectedMenuScreenItem->getItemIndex()); } */ Quad *menu_blackout = 0; void Game::showInGameMenu(bool ignoreInput, bool optionsOnly, MenuPage menuPage) { if (avatar && core->getNestedMains()==1 && !avatar->isSinging() && (ignoreInput || avatar->isInputEnabled())) { //dsq->toggleInputGrabPlat(false); dsq->game->clearControlHint(); selectedTreasureFlag = -1; this->optionsOnly = optionsOnly; core->sound->playSfx("Menu-Open"); dropIngrNames.clear(); if (avatar->isEntityDead()) return; if (dsq->game->autoMap && dsq->game->autoMap->isOn()) dsq->game->autoMap->toggle(false); toggleOptionsMenu(false); dsq->overlay->alpha.interpolateTo(0, 0.1); float t = 0.3; if (!optionsOnly) { togglePause(true); } if (optionsOnly) { menu_blackout = new Quad; menu_blackout->color = 0; menu_blackout->autoWidth = AUTO_VIRTUALWIDTH; menu_blackout->autoHeight = AUTO_VIRTUALHEIGHT; menu_blackout->followCamera = 1; menu_blackout->position = Vector(400,300); menu_blackout->alphaMod = 0.75; menu_blackout->alpha = 0; menu_blackout->alpha.interpolateTo(1, 0.5); addRenderObject(menu_blackout, LR_AFTER_EFFECTS); menuBg2->alpha = 0; } else { menuBg2->alpha = 0; menuBg2->alpha.interpolateTo(1, t*0.5f); } if (dsq->continuity.hasFormUpgrade(FORMUPGRADE_ENERGY2)) energyIdol->alphaMod = 1; else energyIdol->alphaMod = 0; if (dsq->continuity.getFlag(FLAG_LI) >= 100) liCrystal->alphaMod = 1; else liCrystal->alphaMod = 0; int i = 0; for (i = 0; i < songSlots.size(); i++) { if (dsq->continuity.hasSong(dsq->continuity.getSongTypeBySlot(i))) songSlots[i]->alpha.interpolateTo(1, t); else songSlots[i]->alpha = 0; } /* std::ostringstream os; os << "Exp: " << dsq->continuity.exp; menuEXP->setText(os.str()); menuEXP->alpha.interpolateTo(1, 0.5); std::ostringstream os2; os2 << "Money: " << dsq->continuity.money; menuMoney->setText(os2.str()); menuMoney->alpha.interpolateTo(1, 0.5); */ menuDescription->setText(""); menuDescription->alpha.interpolateTo(1, t); menuBg->scale = menuBgScale*0.5f; menuBg->scale.interpolateTo(menuBgScale, t); menuBg->alpha.interpolateTo(1, t*0.5f); menuBg->setHidden(false); // FIXME: This gets a little verbose because of all the // individual non-child objects. Is there a reason they // can't all be children of menuBg? --achurch opt_save->setHidden(false); opt_cancel->setHidden(false); options->setHidden(false); keyConfigButton->setHidden(false); cook->setHidden(false); foodSort->setHidden(false); recipes->setHidden(false); use->setHidden(false); prevFood->setHidden(false); nextFood->setHidden(false); prevTreasure->setHidden(false); nextTreasure->setHidden(false); circlePageNum->setHidden(false); previewRecipe->setHidden(false); showRecipe->setHidden(false); recipeMenu.scroll->setHidden(false); recipeMenu.scrollEnd->setHidden(false); recipeMenu.header->setHidden(false); recipeMenu.page->setHidden(false); recipeMenu.prevPage->setHidden(false); recipeMenu.nextPage->setHidden(false); menuDescription->setHidden(false); eAre->setHidden(false); eYes->setHidden(false); eNo->setHidden(false); menuIconGlow->setHidden(false); for (int i = 0; i < menu.size(); i++) menu[i]->setHidden(false); for (int i = 0; i < treasureSlots.size(); i++) treasureSlots[i]->setHidden(false); treasureDescription->setHidden(false); for (int i = 0; i < foodSlots.size(); i++) foodSlots[i]->setHidden(false); if (dsq->game->miniMapRender) { dsq->game->miniMapRender->slide(1); } toggleMainMenu(false); dsq->main(t); dsq->screenTransition->capture(); //toggleMiniMapRender(0); MenuPage useMenuPage = MENUPAGE_NONE; if (!optionsOnly) { if (menuPage != MENUPAGE_NONE) { useMenuPage = menuPage; } else if (dsq->continuity.lastMenuPage != MENUPAGE_NONE) { //errorLog("setting last menu page"); useMenuPage = dsq->continuity.lastMenuPage; } } switch(useMenuPage) { case MENUPAGE_FOOD: toggleFoodMenu(true); ((AquariaMenuItem*)menu[6])->setFocus(true); break; case MENUPAGE_TREASURES: toggleTreasureMenu(true); break; case MENUPAGE_PETS: togglePetMenu(true); break; case MENUPAGE_SONGS: default: { if (optionsOnly) { toggleOptionsMenu(true); } else { float t = 0.1; toggleMainMenu(true); songBubbles->alpha.interpolateTo(1, t); if (menuSongs) { menuSongs->alpha.interpolateTo(1, t); } for (i = 0; i < menu.size(); i++) { menu[i]->scale = Vector(0,0); menu[i]->alpha = 0; } ((AquariaMenuItem*)menu[5])->setFocus(true); } } } if (!optionsOnly) { for (i = 0; i < menu.size(); i++) { menu[i]->scale.interpolateTo(Vector(1, 1), 0.15); menu[i]->alpha.interpolateTo(1, 0.15); } menuIconGlow->alpha.interpolateTo(1, 0.5); } menuOpenTimer = 0; inGameMenu = true; dsq->routeShoulder = false; dsq->screenTransition->transition(MENUPAGETRANSTIME); if (optionsOnly) { dsq->main(-1); } } } void Game::pickupIngredientEffects(IngredientData *data) { Quad *q = new Quad("gfx/ingredients/" + data->gfx, Vector(800-20 + core->getVirtualOffX(), (570-2*(100*miniMapRender->scale.y))+ingOffY)); q->scale = Vector(0.8, 0.8); q->followCamera = 1; q->alpha.ensureData(); q->alpha.data->path.addPathNode(0, 0); q->alpha.data->path.addPathNode(1.0, 0.1); q->alpha.data->path.addPathNode(0, 1.0); q->alpha.startPath(2); q->setLife(1); q->setDecayRate(0.5); addRenderObject(q, LR_HELP); ingOffY -= 40; ingOffYTimer = 2; } void Game::hideInGameMenu(bool effects) { if (isCooking) return; if (FoodSlot::foodSlotIndex != -1) return; if (effects && !this->isInGameMenu()) return; if (avatar) { if (resBox) resBox->close(); //dsq->toggleInputGrabPlat(true); if (effects) core->sound->playSfx("Menu-Close"); hideInGameMenuExitCheck(false); playingSongInMenu = -1; float t = 0.3; if (!effects) t = 0; //if (avatar->isEntityDead()) return; int i = 0; for (i = 0; i < foodHolders.size(); i++) { foodHolders[i]->dropFood(); } dsq->continuity.lastMenuPage = currentMenuPage; toggleOptionsMenu(false); if (!optionsOnly) { toggleFoodMenu(false); toggleTreasureMenu(false); togglePetMenu(false); toggleMainMenu(false); toggleKeyConfigMenu(false); } menuIconGlow->alpha = 0; for (i = 0; i < menu.size(); i++) { menu[i]->alpha = 0; //menu[i]->alpha.interpolateTo(0, t*0.5f); //menu[i]->scale.interpolateTo(Vector(0, 0), t); } for (i = 0; i < spellIcons.size(); i++) spellIcons[i]->alpha.interpolateTo(0, t); for (i = 0; i < songSlots.size(); i++) songSlots[i]->alpha.interpolateTo(0, t); songBubbles->alpha.interpolateTo(0, t); /* menuEXP->alpha.interpolateTo(0, t); menuMoney->alpha.interpolateTo(0, t); */ if (dsq->game->miniMapRender) dsq->game->miniMapRender->slide(0); menuDescription->alpha.interpolateTo(0, t); menuBg->alpha.interpolateTo(0, t); menuBg->scale.interpolateTo(menuBg->scale*0.5f, t); menuBg2->alpha.interpolateTo(0, t); if (menuSongs) menuSongs->alpha.interpolateTo(0, t); if (menu_blackout) { menu_blackout->alpha.interpolateTo(0, t); } if (showRecipe) { showRecipe->alpha.interpolateTo(0, t); } if (effects) core->main(t); if (menu_blackout) { menu_blackout->safeKill(); menu_blackout = 0; } if (effects) togglePause(false); inGameMenu = false; //toggleMiniMapRender(1); for (int i = 0; i < songTips.size(); i++) songTips[i]->alpha = 0; for (int i = 0; i < dropIngrNames.size(); i++) { dsq->game->spawnIngredient(dropIngrNames[i], avatar->position + Vector(0,-96), 1, 1); } dropIngrNames.clear(); if (effects) dsq->quitNestedMain(); dsq->routeShoulder = true; } menuBg->setHidden(true); opt_save->setHidden(true); opt_cancel->setHidden(true); options->setHidden(true); keyConfigButton->setHidden(true); cook->setHidden(true); foodSort->setHidden(true); recipes->setHidden(true); use->setHidden(true); prevFood->setHidden(true); nextFood->setHidden(true); prevTreasure->setHidden(true); nextTreasure->setHidden(true); circlePageNum->setHidden(true); previewRecipe->setHidden(true); showRecipe->setHidden(true); recipeMenu.scroll->setHidden(true); recipeMenu.scrollEnd->setHidden(true); recipeMenu.header->setHidden(true); recipeMenu.page->setHidden(true); recipeMenu.prevPage->setHidden(true); recipeMenu.nextPage->setHidden(true); menuDescription->setHidden(true); eAre->setHidden(true); eYes->setHidden(true); eNo->setHidden(true); menuIconGlow->setHidden(true); for (int i = 0; i < menu.size(); i++) menu[i]->setHidden(true); for (int i = 0; i < treasureSlots.size(); i++) treasureSlots[i]->setHidden(true); treasureDescription->setHidden(true); for (int i = 0; i < foodSlots.size(); i++) foodSlots[i]->setHidden(true); } void Game::onLeftMouseButton() { // hud button /* if (avatar && !avatar->isCharging()) { if ((core->mouse.position - Vector(20, 20)).getSquaredLength2D() < sqr(40)) { if (paused) hideInGameMenu(); else showInGameMenu(); } } */ } /* void Game::onActivate() { if (!dsq->gui.isInteractionSelectorOpen() && avatar->isInputEnabled()) { Element * e = dsq->getElementAtVector(dsq->cursor->position); if (e) { // open a pop-up menu // how? // gui system // embed menu control in all elements? // if in all elements -> stupid, because you can only have on menu at once elementWithMenu = e; dsq->gui.openInteractionSelectorForElement(e); } } if (dsq->gui.isInteractionSelectorOpen()) { if (dsq->gui.menu.getSelectedEntry() > -1) { Interaction::Type type = elementWithMenu->interactions[dsq->gui.menu.getSelectedEntry()].getType(); dsq->gui.closeInteractionSelector(); // will crash sometime elementWithMenu->interact(type, avatar); elementWithMenu = 0; avatar->enableInput(); //dsq->gui.menu.clearEntries(); } } else if (dsq->gui.isChoiceMenuOpen()) { if (dsq->gui.choiceMenu.getSelectedEntry() > -1) { selectedChoice = dsq->gui.choiceMenu.getSelectedEntryName(); dsq->gui.closeChoiceMenu(); if (core->getNestedMains() > 1) { core->quitNestedMain(); } } } else if(core->getNestedMains()) { core->quitNestedMain(); } } */ void Game::spawnManaBall(Vector pos, float a) { ManaBall *m = new ManaBall(pos, a); addRenderObject(m, LR_PARTICLES); } void Game::refreshItemSlotIcons() { /* for (int i = 0; i < itemSlotIcons.size(); i++) { if (dsq->continuity.itemSlots[i] != -1) { itemSlotIcons[i]->setTexture(dsq->getItemTexture(dsq->continuity.itemSlots[i])); int n = dsq->continuity.getNumberOf(dsq->continuity.itemSlots[i]); if (n > 0) itemSlotIcons[i]->alpha = 1; else itemSlotIcons[i]->alpha = 0; } else itemSlotIcons[i]->alpha = 0; itemSlotIcons[i]->setWidthHeight(32, 32); } */ /* if (n > 0) itemSlotIcons[i]->alpha.interpolateTo(1,0.2); else itemSlotIcons[i]->alpha.interpolateTo(0,0.2); */ } void Game::clearPointers() { bg = 0; bg2 = 0; avatar = 0; } void Game::warpPrep() { avatar->onWarp(); fromVel = avatar->vel; fromVel.setLength2D(10); fromPosition = avatar->position; } void Game::warpToSceneNode(std::string scene, std::string node) { warpPrep(); sceneToLoad = scene; toNode = node; stringToLower(sceneToLoad); stringToLower(toNode); if (avatar->isfh()) toFlip = 1; core->enqueueJumpState("Game"); } void Game::warpToSceneFromNode( Path *p) { warpPrep(); sceneToLoad = p->warpMap; toNode = ""; if (!p->warpNode.empty()) { toNode = p->warpNode; toFlip = p->toFlip; stringToLower(toNode); } else { fromScene = sceneName; fromWarpType = p->warpType; } stringToLower(fromScene); stringToLower(sceneToLoad); core->enqueueJumpState("Game"); } void Game::transitionToScene(std::string scene) { if (avatar) { avatar->onWarp(); } sceneToLoad = scene; stringToLower(sceneToLoad); core->enqueueJumpState("Game", false); } ElementTemplate *Game::getElementTemplateByIdx(int idx) { for (int i = 0; i < elementTemplates.size(); i++) { if (elementTemplates[i].idx == idx) { return &elementTemplates[i]; } } return 0; } Element* Game::createElement(int idx, Vector position, int bgLayer, RenderObject *copy, ElementTemplate *et) { if (idx == -1) return 0; if (!et) et = this->getElementTemplateByIdx(idx); Element *element = new Element(); if (et) { element->setTexture(et->gfx); element->alpha = et->alpha; } element->position = position; element->position.z = -0.05; element->templateIdx = idx; element->bgLayer = bgLayer; if (et) { if (et->w != -1 && et->h != -1) element->setWidthHeight(et->w, et->h); } if (et) { if (et->tu1 != 0 || et->tu2 != 0 || et->tv1 != 0 || et->tv2 != 0) { element->upperLeftTextureCoordinates = Vector(et->tu1, et->tv1); element->lowerRightTextureCoordinates = Vector(et->tu2, et->tv2); } } if (copy) { element->scale = copy->scale; if (copy->isfh()) element->flipHorizontal(); if (copy->isfv()) element->flipVertical(); element->rotation = copy->rotation; Quad *q = dynamic_cast(copy); if (q) { element->repeatTextureToFill(q->isRepeatingTextureToFill()); } } addRenderObject(element, LR_ELEMENTS1+bgLayer); dsq->addElement(element); //element->updateCullVariables(); return element; } void Game::addObsRow(int tx, int ty, int len) { ObsRow obsRow(tx, ty, len); obsRows.push_back(obsRow); } void Game::clearObsRows() { obsRows.clear(); } void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim) { #ifdef BBGE_BUILD_OPENGL if (q->texture) { std::vector obs; TileVector tpos(q->position); int widthscale = q->getWidth()*q->scale.x; int heightscale = q->getHeight()*q->scale.y; int w2 = widthscale/2; int h2 = heightscale/2; w2/=TILE_SIZE; h2/=TILE_SIZE; tpos.x -= w2; tpos.y -= h2; int w = 0, h = 0; unsigned int size = 0; unsigned char *data = q->texture->getBufferAndSize(&w, &h, &size); if (!data) { debugLog("Failed to get buffer in Game::fillGridFromQuad()"); return; } int szx = TILE_SIZE/q->scale.x; int szy = TILE_SIZE/q->scale.y; if (szx < 1) szx = 1; if (szy < 1) szy = 1; for (int tx = 0; tx < widthscale; tx+=TILE_SIZE) { for (int ty = 0; ty < heightscale; ty+=TILE_SIZE) { int num = 0; for (int x = 0; x < szx; x++) { for (int y = 0; y < szy; y++) { // starting position = // tx / scale.x unsigned int px = int(tx/q->scale.x) + x; unsigned int py = int(ty/q->scale.y) + y; if (px < unsigned(w) && py < unsigned(h)) { unsigned int p = (py*unsigned(w)*4) + (px*4) + 3; // position of alpha component if (p < size && data[p] >= 254) { num ++; } else { break; } } } } if (num >= int((szx*szy)*0.8f)) //if (num >= int((szx*szy))) { // add tile //dsq->game->setGrid(TileVector(int(tx/TILE_SIZE)+tpos.x, int(ty/TILE_SIZE)+tpos.y), 1); obs.push_back(TileVector(int(tx/TILE_SIZE), int(ty/TILE_SIZE))); } } } free(data); if (trim) { std::vector obsCopy; obsCopy.swap(obs); // obs now empty int sides = 0; for (int i = 0; i < obsCopy.size(); i++) { sides = 0; for (int j = 0; j < obsCopy.size(); j++) { if (i != j) { if ( (obsCopy[j].x == obsCopy[i].x-1 && obsCopy[j].y == obsCopy[i].y) || (obsCopy[j].x == obsCopy[i].x+1 && obsCopy[j].y == obsCopy[i].y) || (obsCopy[j].y == obsCopy[i].y-1 && obsCopy[j].x == obsCopy[i].x) || (obsCopy[j].y == obsCopy[i].y+1 && obsCopy[j].x == obsCopy[i].x) ) { sides++; } if (sides>=4) { obs.push_back(obsCopy[i]); break; } } } } } glPushMatrix(); for (int i = 0; i < obs.size(); i++) { glLoadIdentity(); glRotatef(q->rotation.z, 0, 0, 1); if (q->isfh()) { glRotatef(180, 0, 1, 0); } //glTranslatef((obs[i].x-w2)*TILE_SIZE+TILE_SIZE/2, (obs[i].y-h2)*TILE_SIZE + TILE_SIZE/2, 0); glTranslatef((obs[i].x-w2), (obs[i].y-h2), 0); float m[16]; glGetFloatv(GL_MODELVIEW_MATRIX, m); float x = m[12]; float y = m[13]; //dsq->game->setGrid(TileVector(tpos.x+(w2*TILE_SIZE)+(x/TILE_SIZE), tpos.y+(h2*TILE_SIZE)+(y/TILE_SIZE)), obsType); TileVector tvec(tpos.x+w2+x, tpos.y+h2+y); if (dsq->game->getGrid(tvec) == OT_EMPTY) dsq->game->setGrid(tvec, obsType); } glPopMatrix(); } #endif } std::string Game::getNoteName(int n, const std::string &pre) { std::ostringstream os; os << pre << "Note" << n; if (n == 6 && bNatural) { os << "b"; } //debugLog(os.str()); return os.str(); } void Game::clearDynamicGrid(unsigned char maskbyte /* = OT_MASK_BLACK */) { // just to be sure in case the grid/type sizes change, // otherwise there is a chance to write a few bytes over the end of the buffer -- FG compile_assert(sizeof(grid) % sizeof(uint32) == 0); signed char *gridstart = &grid[0][0]; uint32 *gridend = (uint32*)(gridstart + sizeof(grid)); uint32 *gridptr = (uint32*)gridstart; // mask out specific bytes // use full uint32 rounds instead of single-bytes to speed things up. const uint32 mask = maskbyte | (maskbyte << 8) | (maskbyte << 16) | (maskbyte << 24); do { *gridptr &= mask; ++gridptr; } while(gridptr < gridend); } void Game::reconstructEntityGrid() { clearDynamicGrid(~OT_INVISIBLEENT); FOR_ENTITIES(i) { Entity *e = *i; e->fillGrid(); } } void Game::reconstructGrid(bool force) { if (!force && isSceneEditorActive()) return; clearGrid(); int i = 0; for (i = 0; i < dsq->getNumElements(); i++) { Element *e = dsq->getElement(i); e->fillGrid(); } ObsRow *o; for (i = 0; i < obsRows.size(); i++) { o = &obsRows[i]; for (int tx = 0; tx < o->len; tx++) { setGrid(TileVector(o->tx + tx, o->ty), OT_BLACK); } } FOR_ENTITIES(i) { Entity *e = *i; e->fillGrid(); } trimGrid(); dsq->pathFinding.generateZones(); } void Game::trimGrid() { // Prevent the left- and rightmost column of black tiles // from beeing drawn. (The maps were designed with this mind...) for (int x = 0; x < MAX_GRID; x++) { const signed char *curCol = dsq->game->getGridColumn(x); const signed char *leftCol = dsq->game->getGridColumn(x-1); const signed char *rightCol = dsq->game->getGridColumn(x+1); for (int y = 0; y < MAX_GRID; y++) { if (curCol[y] & OT_MASK_BLACK) { if (!(leftCol[y] & OT_MASK_BLACK) || !(rightCol[y] & OT_MASK_BLACK)) setGrid(TileVector(x, y), OT_BLACKINVIS); } } } } float Game::getCoverage(Vector pos, int sampleArea) { TileVector t(pos); int total = 0, covered = 0; for (int x = t.x-sampleArea; x <= t.x+sampleArea; x++) { for (int y = t.y-sampleArea; y <= t.y+sampleArea; y++) { if (x == t.x && y == t.y) continue; TileVector ct(x,y); Vector vt = ct.worldVector(); if (isObstructed(ct)) { covered++; } total++; } } return float(covered)/float(total); } float Game::getPercObsInArea(Vector pos, int sampleArea, int obs) { int sz = sampleArea * sampleArea; int c = 0; TileVector t(pos); for (int x = t.x-sampleArea; x <= t.x+sampleArea; x++) { for (int y = t.y-sampleArea; y <= t.y+sampleArea; y++) { if (isObstructed(TileVector(x, y), obs)) { c++; } } } return float(c)/float(sz); } Vector Game::getWallNormal(Vector pos, int sampleArea, float *dist, int obs) { TileVector t(pos); //Vector p = t.worldVector(); Vector avg; int c = 0; //float maxLen = -1; std::vector vs; if (dist != NULL) *dist = -1; for (int x = t.x-sampleArea; x <= t.x+sampleArea; x++) { for (int y = t.y-sampleArea; y <= t.y+sampleArea; y++) { if (x == t.x && y == t.y) continue; TileVector ct(x,y); Vector vt = ct.worldVector(); if (isObstructed(ct, obs)) { /* int xDiff = abs(t.x - x); int yDiff = abs(t.y - y); float xv = float(sampleArea-xDiff)/float(sampleArea); if (x < t.x) xv = -xv; float yv = float(sampleArea-yDiff)/float(sampleArea); if (y < t.y) yv = -yv; Vector v(-xv, -yv); */ /* int xDiff = t.x-x; int yDiff = t.y-y; */ int xDiff = pos.x-vt.x; int yDiff = pos.y-vt.y; /* float xEffect = (sampleArea*TILE_SIZE - abs(xDiff))*1.0f; float yEffect = (sampleArea*TILE_SIZE - abs(yDiff))*1.0f; */ //Vector v(xDiff*xEffect, yDiff*yEffect); Vector v(xDiff, yDiff); vs.push_back (v); if (dist!=NULL) { float d = (vt-pos).getLength2D(); if (*dist == -1 || d < *dist) { *dist = d; } } /* float len = v.getLength2D(); if (len > maxLen || maxLen == -1) maxLen = len; */ //Vector v(xDiff, yDiff); //avg += v; //c++; } } } int sz = (TILE_SIZE*(sampleArea-1)); for (int i = 0; i < vs.size(); i++) { float len = vs[i].getLength2D(); if (len < sz) { vs[i].setLength2D(sz - len); c++; avg += vs[i]; } } if (avg != 0) { avg /= c; if (avg.x != 0 || avg.y != 0) { avg.normalize2D(); avg.z = 0; } } else { avg.x = avg.y = 0; } /* avg.x = -avg.x; avg.y = -avg.y; */ return avg; } Entity *Game::getEntityAtCursor() { int minDist = -1; Entity *selected = 0; FOR_ENTITIES(i) { Entity *e = *i; int dist = (e->position - dsq->getGameCursorPosition()).getSquaredLength2D(); if (dist < sqr(64) && (minDist == -1 || dist < minDist)) { selected = e; dist = minDist; } } return selected; } // WARNING: will remove from save file, if present! bool Game::removeEntityAtCursor() { Entity *selected = getEntityAtCursor(); if (selected) { return removeEntity(selected); } return false; } bool Game::removeEntity(Entity *selected) { selected->setState(Entity::STATE_DEAD); selected->safeKill(); TiXmlElement *e = this->saveFile->FirstChildElement("Enemy"); while (e) { int x = atoi(e->Attribute("x")); int y = atoi(e->Attribute("y")); if (int(selected->startPos.x) == x && int(selected->startPos.y) == y) { this->saveFile->RemoveChild(e); //delete e; return true; } e = e->NextSiblingElement("Enemy"); } for (int i = 0; i < entitySaveData.size(); i++) { if (entitySaveData[i].x == int(selected->startPos.x) && entitySaveData[i].y == int(selected->startPos.y)) { std::vector copy = entitySaveData; entitySaveData.clear(); for (int j = 0; j < copy.size(); j++) { if (j != i) entitySaveData.push_back(copy[j]); } return true; } } return false; } void Game::removeIngredient(Ingredient *i) { ingredients.remove(i); } void Game::bindIngredients() { for (Ingredients::iterator i = ingredients.begin(); i != ingredients.end(); ++ i) { Vector v = avatar->position - (*i)->position; if (!v.isLength2DIn(16)) { v.setLength2D(500); (*i)->vel += v; } } } /* void Game::getEntityTypeName(int entityType) { switch(entityType) { case ET_NAUTILUS: return "Nautilus"; case ET_CENTIPEDE: return "Centipede"; case ET_WATERBUG: return "WaterBug"; case ET_CRAWLER: return "Crawler"; case ET_HELLBEASTHEAD: return "HellBeastHead"; case ET_SPINNER: return "Spinner"; case ET_SQUID: return "Squid"; case ET_JELLYFISH: return "JellyFish"; case ET_ROCKHEAD: return "RockHead"; case ET_SPIKE: return "Spike"; case ET_MEGASHRIMP: return "MegaShrimp"; case ET_ZUNNA: return "Zunna"; case ET_PICKUPITEM: return "PickupItem"; case ET_HERETICSKULL: return "HereticSkull"; case ET_RATTLEOYSTER: return "RattleOyster"; case ET_LEACH: return "Leach"; case ET_QUEENHYDRA: return "QueenHydra"; case ET_HYDRALARVA: return "Lumite"; case ET_BARRIER: return "Barrier"; } } */ void Game::loadEntityTypeList() // and group list! { entityTypeList.clear(); InStream in("scripts/entities/entities.txt"); std::string line; if(!in) { core->messageBox(dsq->continuity.stringBank.get(2008), dsq->continuity.stringBank.get(2016)); exit(1); } while (std::getline(in, line)) { std::string name, prevGfx; int idx; float scale; std::istringstream is(line); is >> idx >> name >> prevGfx >> scale; //errorLog(line); /* std::ostringstream os; os << "adding entity [" << name << "] idx[" << idx << "] prevGfx [" << prevGfx << "] scale [" << scale << "]"; debugLog(os.str()); */ entityTypeList.push_back(EntityClass(name, 1, idx, prevGfx, scale)); } in.close(); #ifdef AQUARIA_BUILD_SCENEEDITOR entityGroups.clear(); std::string fn = "scripts/entities/entitygroups.txt"; if (dsq->mod.isActive()) { fn = dsq->mod.getPath() + "entitygroups.txt"; } InStream in2(fn.c_str()); int curGroup=0; while (std::getline(in2, line)) { if (line.find("GROUP:")!=std::string::npos) { line = line.substr(6, line.size()); //debugLog("****** NEWGROUP: " + line); EntityGroup newGroup; newGroup.name = line; //entityGroups[line] = newGroup; // entityGroups.push_back(newGroup); curGroup = entityGroups.size()-1; } else if (!line.empty()) { EntityGroupEntity ent; std::istringstream is(line); std::string addLine, graphic; is >> ent.name >> ent.gfx; stringToLower(ent.name); //debugLog("**adding: " + addLine); entityGroups[curGroup].entities.push_back(ent); } } in2.close(); game->sceneEditor.entityPageNum = 0; //game->sceneEditor.page = entityGroups.begin(); #endif } EntityClass *Game::getEntityClassForEntityType(const std::string &type) { for (int i = 0; i < entityTypeList.size(); i++) { /* std::ostringstream os; os << "Comparing entityTypeList [" << entityTypeList[i].name << "] with type [" << type << "]"; debugLog(os.str()); */ if (nocasecmp(entityTypeList[i].name, type)==0) return &entityTypeList[i]; } return 0; } int Game::getIdxForEntityType(std::string type) { //if (!type.empty() && type[0] == '@') return -1; for (int i = 0; i < entityTypeList.size(); i++) { if (nocasecmp(entityTypeList[i].name, type)==0) return entityTypeList[i].idx; } return -1; } Entity *Game::createEntity(int idx, int id, Vector position, int rot, bool createSaveData, std::string name, EntityType et, bool doPostInit) { std::string type; for (int i = 0; i < dsq->game->entityTypeList.size(); i++) { EntityClass *ec = &dsq->game->entityTypeList[i]; if (ec->idx == idx) { type = ec->name; return createEntity(type, id, position, rot, createSaveData, name, et, doPostInit); } } return 0; } // ensure a limit of entity types in the current level // older entities with be culled if state is set to 0 // otherwise, the older entities will have the state set void Game::ensureLimit(Entity *e, int num, int state) { int idx = e->entityTypeIdx; int c = 0; std::list entityList; FOR_ENTITIES(i) { if ((*i)->entityTypeIdx == idx && (state == 0 || (*i)->getState() != state)) { entityList.push_back(*i); c++; } } int numDelete = c-(num+1); if (numDelete >= 0) { for (std::list::iterator i = entityList.begin(); i != entityList.end(); i++) { if (state == 0) (*i)->safeKill(); else (*i)->setState(state); numDelete--; if (numDelete <= 0) break; } } } Entity* Game::establishEntity(Entity *e, int id, Vector position, int rot, bool createSaveData, std::string name, EntityType et, bool doPostInit) { // e->layer must be set BEFORE calling this function! std::string type = e->name; stringToLower(type); // i'm thinking this *should* hold up for new files // it will mess up if you're importing an old file // the logic being that you're not going to load in an non-ID-specified entity in new files // so assignUniqueID should never be called // so what i'm going to do is have it bitch // note that when not loading a scene, it is valid to call assignUniqueID here if (id != 0) { e->setID(id); } else { if (loadingScene) { std::ostringstream os; os << "ERROR: Assigning Unique ID to a loaded Entity... if this is called from loadScene then Entity IDs may be invalid"; os << "\nEntityName: " << e->name; errorLog(os.str()); } else { e->assignUniqueID(); } } // NOTE: init cannot be called after "addRenderObject" for some unknown reason e->init(); Vector usePos = position; e->startPos = usePos; if (!name.empty()) e->name = name; e->rotation.z = rot; int idx = getIdxForEntityType(type); e->entityTypeIdx = idx; if (createSaveData) { int idx = dsq->game->getIdxForEntityType(type); entitySaveData.push_back(EntitySaveData(e, idx, usePos.x, usePos.y, rot, e->getID(), e->name)); } addRenderObject(e, e->layer); if (doPostInit) { e->postInit(); } return e; } Entity *Game::createEntity(const std::string &t, int id, Vector position, int rot, bool createSaveData, std::string name, EntityType et, bool doPostInit) { std::string type = t; stringToLower(type); ScriptedEntity *e; e = new ScriptedEntity(type, position, et); return establishEntity(e, id, position, rot, createSaveData, name, et, doPostInit); } void Game::initEntities() { FOR_ENTITIES(i) { Entity *e = *i; if (e) { e->init(); } } } void Game::assignEntitiesUniqueIDs() { FOR_ENTITIES(i) { Entity *e = *i; if (e && e->entityID == 0) { e->assignUniqueID(); } } } EntitySaveData *Game::getEntitySaveDataForEntity(Entity *e, Vector pos) { for (int i = 0; i < entitySaveData.size(); i++) { if (entitySaveData[i].e == e) { return &entitySaveData[i]; } /* if (entitySaveData[i].x == int(e->startPos.x) && entitySaveData[i].y == int(e->startPos.y)) { if (entitySaveData[i].idx == e->entityTypeIdx) { debugLog("found entity"); return &entitySaveData[i]; } } */ } return 0; } void Game::setTimerTextAlpha(float a, float t) { timerText->alpha.interpolateTo(a, t); } void Game::setTimerText(float time) { std::ostringstream os; int mins = int(time/60); int secs = time - (mins*60); os << mins; if (getTimer() > 0.5f) os << ":"; else os << "."; if (secs < 10) os << "0"; os << secs; timerText->setText(os.str()); } void Game::generateCollisionMask(Quad *q, int overrideCollideRadius) { #ifdef BBGE_BUILD_OPENGL if (q->texture) { q->collidePosition = Vector(0,0,0); if (overrideCollideRadius) q->collideRadius = overrideCollideRadius; else q->collideRadius = TILE_SIZE/2; q->collisionMask.clear(); TileVector tpos(q->position); int widthscale = q->getWidth()*q->scale.x; int heightscale = q->getHeight()*q->scale.y; int w2 = widthscale/2; int h2 = heightscale/2; w2/=TILE_SIZE; h2/=TILE_SIZE; tpos.x -= w2; tpos.y -= h2; int w = 0, h = 0; unsigned int size = 0; unsigned char *data = q->texture->getBufferAndSize(&w, &h, &size); if (!data) { debugLog("Failed to get buffer in Game::generateCollisionMask()"); return; } q->collisionMaskRadius = 0; Vector collisionMaskHalfVector = Vector(q->getWidth()/2, q->getHeight()/2); int szx = TILE_SIZE/q->scale.x; int szy = TILE_SIZE/q->scale.y; if (szx < 1) szx = 1; if (szy < 1) szy = 1; for (int tx = 0; tx < widthscale; tx+=TILE_SIZE) { for (int ty = 0; ty < heightscale; ty+=TILE_SIZE) { int num = 0; for (int x = 0; x < szx; x++) { for (int y = 0; y < szy; y++) { // starting position = // tx / scale.x unsigned int px = int(tx/q->scale.x) + x; unsigned int py = int(ty/q->scale.y) + y; if (px < unsigned(w) && py < unsigned(h)) { unsigned int p = (py*unsigned(w)*4) + (px*4) + 3; // position of alpha component if (p < size && data[p] >= 250) { num ++; } } } } if (num >= int((szx*szy)*0.25f)) { TileVector tile(int((tx+TILE_SIZE/2)/TILE_SIZE), int((ty+TILE_SIZE/2)/TILE_SIZE)); // + Vector(0,TILE_SIZE) q->collisionMask.push_back(tile.worldVector() - collisionMaskHalfVector); } } } q->collisionMaskRadius = 512; free(data); /* for (int i = 0; i < q->collisionMask.size(); i++) { float xsz = q->collisionMask[i].x; float ysz = q->collisionMask[i].y; if (xsz < 0) xsz = -xsz; if (ysz < 0) ysz = -ysz; if (xsz > q->collisionMaskRadius) q->collisionMaskRadius = xsz; if (ysz > q->collisionMaskRadius) q->collisionMaskRadius = ysz; } q->collisionMaskRadius += TILE_SIZE/2; */ /* if (w2 > h2) q->collisionMaskRadius = w2*2; else q->collisionMaskRadius = h2*2; */ //q->collisionMaskRadius = sqrtf(sqr(w2)+sqr(h2)); /* int rot = rotation.z; while (rot > 360) rot -= 360; while (rot < 0) rot += 360; */ } #endif } void Game::addPath(Path *p) { paths.push_back(p); if (p->pathType >= 0 && p->pathType < PATH_MAX) { p->nextOfType = firstPathOfType[p->pathType]; firstPathOfType[p->pathType] = p; } } void Game::removePath(int idx) { if (idx >= 0 && idx < paths.size()) paths[idx]->destroy(); std::vector copy = this->paths; clearPaths(); for (int i = 0; i < copy.size(); i++) { if (i != idx) addPath(copy[i]); } } void Game::clearPaths() { paths.clear(); for (int i = 0; i < PATH_MAX; i++) firstPathOfType[i] = 0; } int Game::getIndexOfPath(Path *p) { for (int i = 0; i < paths.size(); i++) { if (paths[i] == p) return i; } return -1; } Path *Game::getPathAtCursor() { return getNearestPath(dsq->getGameCursorPosition(), ""); /* int range = 128; int sz = paths.size(); for (int i = 0; i < sz; i++) { Path *p = &(paths[i]); if (!p->nodes.empty()) { int dist = (p->nodes[0].position - dsq->getGameCursorPosition()).getSquaredLength2D(); if (dist < sqr(range)) { return p; } } } return 0; */ } Path *Game::getScriptedPathAtCursor(bool withAct) { //int range = 64; int sz = paths.size(); for (int i = 0; i < sz; i++) { Path *p = (paths[i]); if (!p->nodes.empty() && p->hasScript()) { if (!withAct || p->cursorActivation) { if (p->isCoordinateInside(dsq->getGameCursorPosition())) { return p; } } /* int dist = (p->nodes[0].position - dsq->getGameCursorPosition()).getSquaredLength2D(); if (dist < sqr(range)) { return p; } */ } } return 0; } Path *Game::getNearestPath(const Vector &pos, const std::string &s, const Path *ignore) { Path *closest = 0; float smallestDist = HUGE_VALF; std::string st = s; stringToLower(st); for (int i = 0; i < dsq->game->paths.size(); i++) { Path *cp = dsq->game->paths[i]; if (cp != ignore && !cp->nodes.empty() && (st.empty() || st == cp->label)) { const Vector v = cp->nodes[0].position - pos; const float dist = v.getSquaredLength2D(); if (dist < smallestDist) { smallestDist = dist; closest = cp; } } } return closest; } Path *Game::getNearestPath(const Vector &pos, PathType pathType) { Path *closest = 0; float smallestDist = HUGE_VALF; for (Path *cp = dsq->game->getFirstPathOfType(pathType); cp; cp = cp->nextOfType) { if (!cp->nodes.empty()) { const Vector v = cp->nodes[0].position - pos; const float dist = v.getSquaredLength2D(); if (dist < smallestDist) { smallestDist = dist; closest = cp; } } } return closest; } Path *Game::getNearestPath(Path *p, std::string s) { if (p->nodes.empty()) return 0; return getNearestPath(p->nodes[0].position, s); } Path *Game::getPathByName(std::string name) { stringToLowerUserData(name); for (int i = 0; i < paths.size(); i++) { if (paths[i]->label == name) return paths[i]; } return 0; } void Game::addKeyConfigLine(RenderObject *group, const std::string &label, const std::string &actionInputName, int y, int l1, int l2, int l3) { //DebugFont *lb = new DebugFont(6, label); TTFText *lb = new TTFText(&dsq->fontArialSmallest); lb->setText(label); lb->position = Vector(140,y); group->addChild(lb, PM_POINTER); AquariaKeyConfig *k1 = new AquariaKeyConfig(actionInputName, INPUTSET_KEY, 0); k1->position = Vector(350,y); k1->setLock(l1); group->addChild(k1, PM_POINTER); AquariaKeyConfig *k2 = new AquariaKeyConfig(actionInputName, INPUTSET_KEY, 1); k2->position = Vector(475,y); k2->setLock(l2); group->addChild(k2, PM_POINTER); AquariaKeyConfig *j1 = new AquariaKeyConfig(actionInputName, INPUTSET_JOY, 0); j1->position = Vector(600,y); j1->setLock(l3); group->addChild(j1, PM_POINTER); k1->setDirMove(DIR_RIGHT, k2); k2->setDirMove(DIR_RIGHT, j1); j1->setDirMove(DIR_LEFT, k2); k2->setDirMove(DIR_LEFT, k1); } AquariaKeyConfig *Game::addAxesConfigLine(RenderObject *group, const std::string &label, const std::string &actionInputName, int y, int offx) { /// DebugFont *lb = new DebugFont(6, label); TTFText *lb = new TTFText(&dsq->fontArialSmallest); lb->setText(label); lb->position = Vector(140+offx, y); group->addChild(lb, PM_POINTER); AquariaKeyConfig *i1 = new AquariaKeyConfig(actionInputName, INPUTSET_OTHER, 0); i1->position = Vector(140+80+offx,y); //i1->setLock(l1); group->addChild(i1, PM_POINTER); i1->setDirMove(DIR_RIGHT, 0); i1->setDirMove(DIR_LEFT, 0); return i1; } bool Game::doFlagCheck(const std::string &flagCheck, FlagCheckType type, bool lastTruth) { if (!flagCheck.empty()) { std::string flagName, comparison, next; int value=0; std::istringstream is(flagCheck); is >> flagName >> comparison >> value >> next; bool truth=false; if (comparison == "==") { if (dsq->continuity.getFlag(flagName) == value) truth = true; } else if (comparison == "<") { if (dsq->continuity.getFlag(flagName) < value) truth = true; } else if (comparison == ">") { if (dsq->continuity.getFlag(flagName) > value) truth = true; } else if (comparison == "<=") { if (dsq->continuity.getFlag(flagName) <= value) truth = true; } else if (comparison == ">=") { if (dsq->continuity.getFlag(flagName) >= value) truth = true; } if (type == AND) { truth = (lastTruth && truth); } else if (type == OR) { truth = (lastTruth || truth); } if (next == "AND") { std::string restOfIt; std::getline(is, restOfIt); return doFlagCheck(restOfIt, AND, truth); } else if (next == "OR") { std::string restOfIt; std::getline(is, restOfIt); return doFlagCheck(restOfIt, OR, truth); } return truth; } return true; } void Game::switchToSongMenu() { dsq->screenTransition->capture(); toggleOptionsMenu(false); toggleFoodMenu(false); togglePetMenu(false); toggleTreasureMenu(false); toggleMainMenu(true); dsq->screenTransition->transition(MENUPAGETRANSTIME); } void Game::switchToFoodMenu() { dsq->screenTransition->capture(); toggleOptionsMenu(false); togglePetMenu(false); toggleMainMenu(false); toggleTreasureMenu(false); toggleFoodMenu(true); dsq->screenTransition->transition(MENUPAGETRANSTIME); } void Game::switchToPetMenu() { dsq->screenTransition->capture(); toggleOptionsMenu(false); toggleFoodMenu(false); toggleMainMenu(false); toggleTreasureMenu(false); togglePetMenu(true); dsq->screenTransition->transition(MENUPAGETRANSTIME); } void Game::switchToTreasureMenu() { dsq->screenTransition->capture(); toggleOptionsMenu(false); toggleFoodMenu(false); toggleMainMenu(false); togglePetMenu(false); toggleTreasureMenu(true); dsq->screenTransition->transition(MENUPAGETRANSTIME); } /* IET_INVINCIBLE IET_HP IET_MAXHP IET_DEFENSE IET_SPEED IET_REGEN IET_ENERGY IET_BLIND IET_LIGHT IET_PETPOWER IET_WEB IET_LI IET_FISHPOISON IET_BITE IET_EAT IET_YUM IET_TRIP IET_RANDOM IET_POISON IET_ALLSTATUS */ typedef std::vector IngVec; void Game::sortFood() { /* if (dsq->continuity.foodSortType == FOODSORT_UNSORTED) { if (dsq->continuity.sortByUnsort.empty()) for (int i = 0; i < dsq->continuity.ingredients.size(); i++) dsq->continuity.sortByUnsort.push_back(FoodSortOrder(IT_NONE, IET_NONE, dsq->continuity.ingredients[i].name)); } */ std::vector foodHolderNames; foodHolderNames.resize(foodHolders.size()); for (int i = 0; i < foodHolders.size(); i++) { IngredientData *ing = foodHolders[i]->getIngredient(); if (ing) { foodHolderNames[i] = ing->name; //errorLog(foodHolderNames[i]); //foodHolders[i]->setIngredient(0); } } dsq->continuity.foodSortType++; if (dsq->continuity.foodSortType >= MAX_FOODSORT) dsq->continuity.foodSortType = 0; dsq->continuity.sortFood(); // rebuild the page refreshFoodSlots(false); /* toggleFoodMenu(false); toggleFoodMenu(true); */ dsq->sound->playSfx("shuffle"); dsq->sound->playSfx("menu-switch", 0.5); dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1); for (int i = 0; i < foodHolders.size(); i++) { if (!foodHolderNames[i].empty()) { IngredientData *ing = dsq->continuity.getIngredientHeldByName(foodHolderNames[i]); foodHolders[i]->setIngredient(ing, false); //foodHolders[i]->setIngredient(dsq->continuity.getIngredientByName(foodHolderNames[i])); /* if (!foodHolders[i]->foodHolderIngredient) { errorLog("not found"); } else { std::ostringstream os; os << "get: " << foodHolders[i]->foodHolderIngredient->name; errorLog(os.str()); } */ } } } void Game::createInGameMenu() { float menuz = 4; int i = 0; menuBg = new Quad; menuBg->setTexture("menu"); //menuBg->setWidthHeight(800); //menuBg->scale = Vector(800.0f/1024.0f, 800.0f/1024.0f); menuBgScale = Vector(800.0f/1024.0f, 800.0f/1024.0f); menuBg->position = Vector(400,300,menuz); menuBg->followCamera = 1; //menuBg->shareAlphaWithChildren=true; addRenderObject(menuBg, LR_MENU); menuBg2 = new Quad; menuBg2->setTexture("menu2"); menuBg2->position = Vector(0, 240); menuBg->addChild(menuBg2, PM_POINTER); float scale = menuBg->scale.x; /* songDescription = new BitmapText(&dsq->font); songDescription->position = Vector(0,100); songDescription->parentManagedPointer = 1; menuBg->addChild(songDescription); */ options = new Quad; options->renderQuad = false; int sliderx = 250, slidery = 160, sliderd = 26; int checkx=660, checky = 160, checkd = 26; Quad *audio = new Quad("gui/audiovisual", Vector(200, 125)); options->addChild(audio, PM_POINTER); Quad *controls = new Quad("gui/controls", Vector(600, 125)); options->addChild(controls, PM_POINTER); /* Quad *visual = new Quad("gui/visual", Vector(170, 300)); visual->parentManagedPointer = 1; options->addChild(visual); */ /* Quad *blurEffectsLabel = new Quad("gui/blurEffectsLabel.png", visual->position + Vector(-20,40)); blurEffectsLabel->parentManagedPointer = 1; options->addChild(blurEffectsLabel); */ /* blurEffectsCheck = new AquariaCheckBox(); blurEffectsCheck->position = visual->position + Vector(60, 40); blurEffectsCheck->parentManagedPointer = 1; options->addChild(blurEffectsCheck); */ Quad *controllabels = new Quad("gui/controllabels", Vector(0,0,0)); int w = controllabels->getWidth(); int h = controllabels->getHeight(); controllabels->position = Vector(checkx-16-w/2.0f, checky + h/2.0f - 14); options->addChild(controllabels, PM_POINTER); int scheckx=270; int schecky=315; int sw,sh; int voptoffy = 26; Quad *subtitleslabel = new Quad("gui/subtitles", Vector(0,0,0)); sw = subtitleslabel->getWidth(); sh = subtitleslabel->getHeight(); subtitleslabel->position = Vector(scheckx-16-sw*0.5f, schecky + sh/2.0f - 14); options->addChild(subtitleslabel, PM_POINTER); subtitlesCheck = new AquariaCheckBox(); subtitlesCheck->setValue(dsq->user.audio.subtitles); subtitlesCheck->position = Vector(scheckx,schecky); options->addChild(subtitlesCheck, PM_POINTER); Quad *fullscreenLabel = new Quad("gui/fullscreen", Vector(0,0,0)); fullscreenLabel->position = Vector(scheckx-16-sw*0.5f, schecky + voptoffy + sh/2.0f - 14); options->addChild(fullscreenLabel, PM_POINTER); fullscreenCheck = new AquariaCheckBox(); fullscreenCheck->setValue(dsq->isFullscreen()); fullscreenCheck->position = Vector(scheckx,schecky + voptoffy); options->addChild(fullscreenCheck, PM_POINTER); Quad *resolutionLabel = new Quad("gui/resolution", Vector(0,0,0)); resolutionLabel->position = Vector(160, 260); options->addChild(resolutionLabel, PM_POINTER); resBox = new AquariaComboBox(); resBox->position = Vector(196, 285); for (i = 0; i < core->screenModes.size(); i++) { ostringstream os; os << core->screenModes[i].x << "x" << core->screenModes[i].y; resBox->addItem(os.str()); if (core->screenModes[i].x == dsq->user.video.resx && core->screenModes[i].y == dsq->user.video.resy) { resBox->enqueueSelectItem(i); } } options->addChild(resBox, PM_POINTER); Quad *audiolabels = new Quad("gui/audiolabels", Vector(0,0,0)); w = audiolabels->getWidth(); h = audiolabels->getHeight(); audiolabels->position = Vector(sliderx-64-w/2.0f, slidery + h/2.0f - 14); options->addChild(audiolabels, PM_POINTER); musslider = new AquariaSlider(); musslider->setValue(dsq->user.audio.musvol); musslider->position = Vector(sliderx,slidery+1*sliderd); options->addChild(musslider, PM_POINTER); sfxslider = new AquariaSlider(); sfxslider->setValue(dsq->user.audio.sfxvol); sfxslider->position = Vector(sliderx,slidery); options->addChild(sfxslider, PM_POINTER); voxslider = new AquariaSlider(); voxslider->setValue(dsq->user.audio.voxvol); voxslider->position = Vector(sliderx,slidery+2*sliderd); options->addChild(voxslider, PM_POINTER); flipInputButtonsCheck = new AquariaCheckBox(); flipInputButtonsCheck->setValue(dsq->user.control.flipInputButtons); flipInputButtonsCheck->position = Vector(checkx,checky); options->addChild(flipInputButtonsCheck, PM_POINTER); micInputCheck = 0; toolTipsCheck = new AquariaCheckBox(); toolTipsCheck->setValue(dsq->user.control.toolTipsOn); toolTipsCheck->position = Vector(checkx,checky+1*checkd); options->addChild(toolTipsCheck, PM_POINTER); autoAimCheck = new AquariaCheckBox(); autoAimCheck->setValue(dsq->user.control.autoAim); autoAimCheck->position = Vector(checkx,checky+2*checkd); options->addChild(autoAimCheck, PM_POINTER); targetingCheck = new AquariaCheckBox(); targetingCheck->setValue(dsq->user.control.targeting); targetingCheck->position = Vector(checkx,checky+3*checkd); options->addChild(targetingCheck, PM_POINTER); opt_save = new AquariaMenuItem; opt_save->useQuad("gui/Apply"); opt_save->useGlow("particles/glow", 100, 50); opt_save->event.set(MakeFunctionEvent(Game, onOptionsSave)); opt_save->position = opt_save_original; opt_save->alpha = 0; addRenderObject(opt_save, LR_MENU); opt_cancel = new AquariaMenuItem; opt_cancel->useQuad("gui/Cancel"); opt_cancel->useGlow("particles/glow", 100, 50); opt_cancel->event.set(MakeFunctionEvent(Game, onOptionsCancel)); opt_cancel->position = opt_cancel_original; opt_cancel->alpha = 0; addRenderObject(opt_cancel, LR_MENU); options->shareAlphaWithChildren = 1; options->alpha = 0; options->followCamera = 1; addRenderObject(options, LR_MENU); scale = 1; songSlots.clear(); //songSlots.resize(3); songSlots.resize(10); // rewrite this: so you can hide / ignore certain songs, etc //songSlots.resize(dsq->continuity.getSongBankSize()); //Vector center(-235, -50); Vector center(-230, -50), rightCenter(230, -50); energyIdol = new Quad("formupgrades/energyidol-charged", Vector(40,0)); menuBg->addChild(energyIdol, PM_POINTER); liCrystal = new Quad("gui/li-crystal", Vector(0,0)); menuBg->addChild(liCrystal, PM_POINTER); songBubbles = new Quad("gui/SongBubbles", Vector(-center.x, center.y)); menuBg->addChild(songBubbles, PM_POINTER); // Vector(575,250); songLabel = new BitmapText(&dsq->smallFont); { songLabel->alpha = 0; songLabel->setAlign(ALIGN_CENTER); songLabel->followCamera = 1; songLabel->setFontSize(20); songLabel->position = Vector(-center.x, center.y) + Vector(0, -15); //+ Vector(10, -10); songLabel->scale = Vector(1.2, 1.2); } menuBg->addChild(songLabel, PM_POINTER); ToolTip *tip = 0; foodTips.clear(); songTips.clear(); petTips.clear(); treasureTips.clear(); tip = new ToolTip; tip->alpha = 0; tip->setCircularAreaFromCenter(worldLeftCenter, 240); tip->setText(dsq->continuity.stringBank.get(0), Vector(200,450), 350); addRenderObject(tip, LR_HUD); foodTips.push_back(tip); tip = new ToolTip; tip->alpha = 0; tip->setCircularAreaFromCenter(worldRightCenter, 240); tip->setText(dsq->continuity.stringBank.get(1), Vector(600,450), 350); addRenderObject(tip, LR_HUD); foodTips.push_back(tip); tip = new ToolTip; tip->alpha = 0; tip->setCircularAreaFromCenter(worldLeftCenter, 240); tip->setText(dsq->continuity.stringBank.get(14), Vector(200,450), 350); addRenderObject(tip, LR_HUD); songTips.push_back(tip); /* tip = new ToolTip; tip->alpha = 0; tip->setAreaFromCenter(Vector(400,300), 800, 600); tip->setText(dsq->continuity.stringBank.get(16), Vector(400,300), 400); addRenderObject(tip, LR_HUD); petTips.push_back(tip); */ tip = new ToolTip; tip->alpha = 0; tip->setCircularAreaFromCenter(worldLeftCenter, 240); tip->setText(dsq->continuity.stringBank.get(17), Vector(200,450), 350); addRenderObject(tip, LR_HUD); petTips.push_back(tip); tip = new ToolTip; tip->alpha = 0; tip->setAreaFromCenter(Vector(400,350), 150, 50); tip->setText(dsq->continuity.stringBank.get(15), Vector(400,450), 450); addRenderObject(tip, LR_HUD); songTips.push_back(tip); foodTips.push_back(tip); petTips.push_back(tip); treasureTips.push_back(tip); int radius = 118; int food = 0; keyConfigButton = new AquariaMenuItem; keyConfigButton->useQuad("gui/keyconfig-button"); keyConfigButton->useGlow("particles/glow", 128, 40); keyConfigButton->position = worldRightCenter + Vector(0, 80); keyConfigButton->alpha = 0; keyConfigButton->scale = Vector(0.8, 0.8); keyConfigButton->event.set(MakeFunctionEvent(Game, onKeyConfig)); //keyConfigButton->setCanDirMove(false); addRenderObject(keyConfigButton, LR_MENU); group_keyConfig = new RenderObject; /* Quad *kbg = new Quad("gui/keyconfig-menu", Vector(400,300)); kbg->setWidthHeight(800, 800); group_keyConfig->addChild(kbg); */ //Quad *kcb = new Quad; RoundedRect *kcb = new RoundedRect(); //kcb->color = 0; //kcb->alphaMod = 0.75; kcb->position = Vector(400,276 - 10); kcb->setWidthHeight(580, 455, 10); group_keyConfig->addChild(kcb, PM_POINTER); int offy = -20; #define SB(x) dsq->continuity.stringBank.get(x) TTFText *header_action = new TTFText(&dsq->fontArialSmall); header_action->setText(SB(2101)); header_action->position = Vector(140, 80+offy); group_keyConfig->addChild(header_action, PM_POINTER); TTFText *header_key1 = new TTFText(&dsq->fontArialSmall); header_key1->setText(SB(2102)); header_key1->position = Vector(350, 80+offy); header_key1->setAlign(ALIGN_CENTER); group_keyConfig->addChild(header_key1, PM_POINTER); TTFText *header_key2 = new TTFText(&dsq->fontArialSmall); header_key2->setText(SB(2103)); header_key2->position = Vector(475, 80+offy); header_key2->setAlign(ALIGN_CENTER); group_keyConfig->addChild(header_key2, PM_POINTER); TTFText *header_joy = new TTFText(&dsq->fontArialSmall); header_joy->setText(SB(2104)); header_joy->position = Vector(600, 80+offy); header_joy->setAlign(ALIGN_CENTER); group_keyConfig->addChild(header_joy, PM_POINTER); addKeyConfigLine(group_keyConfig, SB(2105), "lmb", 100+offy, 0, 0, 0); addKeyConfigLine(group_keyConfig, SB(2106), "rmb", 120+offy, 0, 0, 0); addKeyConfigLine(group_keyConfig, SB(2107), "PrimaryAction", 140+offy); addKeyConfigLine(group_keyConfig, SB(2108), "SecondaryAction", 160+offy); addKeyConfigLine(group_keyConfig, SB(2109), "SwimUp", 180+offy); addKeyConfigLine(group_keyConfig, SB(2110), "SwimDown", 200+offy); addKeyConfigLine(group_keyConfig, SB(2111), "SwimLeft", 220+offy); addKeyConfigLine(group_keyConfig, SB(2112), "SwimRight", 240+offy); addKeyConfigLine(group_keyConfig, SB(2113), "Roll", 260+offy); addKeyConfigLine(group_keyConfig, SB(2114), "Revert", 280+offy); addKeyConfigLine(group_keyConfig, SB(2115), "WorldMap", 300+offy); addKeyConfigLine(group_keyConfig, SB(2116), "Escape", 320+offy, 1, 0, 0); AquariaKeyConfig* s1x = addAxesConfigLine(group_keyConfig, SB(2117), "s1ax", 340+offy, 0); AquariaKeyConfig* s1y = addAxesConfigLine(group_keyConfig, SB(2118), "s1ay", 340+offy, 130); AquariaKeyConfig* s2x = addAxesConfigLine(group_keyConfig, SB(2119), "s2ax", 340+offy, 260); AquariaKeyConfig* s2y = addAxesConfigLine(group_keyConfig, SB(2120), "s2ay", 340+offy, 380); s1x->setDirMove(DIR_LEFT, s1x); s1x->setDirMove(DIR_RIGHT, s1y); s1y->setDirMove(DIR_LEFT, s1x); s1y->setDirMove(DIR_RIGHT, s2x); s2x->setDirMove(DIR_LEFT, s1y); s2x->setDirMove(DIR_RIGHT, s2y); s2y->setDirMove(DIR_LEFT, s2x); s2y->setDirMove(DIR_RIGHT, s2y); offy += 20; addKeyConfigLine(group_keyConfig, SB(2121), "PrevPage", 340+offy); addKeyConfigLine(group_keyConfig, SB(2122), "NextPage", 360+offy); addKeyConfigLine(group_keyConfig, SB(2123), "CookFood", 380+offy); addKeyConfigLine(group_keyConfig, SB(2124), "FoodLeft", 400+offy); addKeyConfigLine(group_keyConfig, SB(2125), "FoodRight", 420+offy); addKeyConfigLine(group_keyConfig, SB(2126), "FoodDrop", 440+offy); addKeyConfigLine(group_keyConfig, SB(2127), "Look", 460+offy); addKeyConfigLine(group_keyConfig, SB(2128), "ToggleHelp", 480+offy); #undef SB group_keyConfig->shareAlphaWithChildren = 1; group_keyConfig->followCamera = 1; group_keyConfig->alpha = 0; group_keyConfig->setHidden(true); group_keyConfig->position = Vector(0, -40); addRenderObject(group_keyConfig, LR_OVERLAY); cook = new AquariaMenuItem; cook->useQuad("Gui/cook-button"); cook->useGlow("particles/glow", 128, 40); cook->position = worldRightCenter + Vector(0, -120); cook->alpha = 0; cook->scale = Vector(0.8, 0.8); cook->event.set(MakeFunctionEvent(Game, onCook)); cook->setCanDirMove(false); addRenderObject(cook, LR_MENU); foodSort = new AquariaMenuItem; foodSort->useQuad("gui/sort"); foodSort->useSound("click"); foodSort->useGlow("particles/glow", 32,32); foodSort->position = worldLeftCenter + Vector(-100, -100); foodSort->event.set(MakeFunctionEvent(Game, sortFood)); foodSort->alpha = 0; addRenderObject(foodSort, LR_MENU); recipes = new AquariaMenuItem; recipes->useQuad("Gui/recipes-button"); recipes->useGlow("particles/glow", 128, 32); recipes->position = worldLeftCenter + Vector(-40, 140); recipes->alpha = 0; recipes->scale = Vector(0.8, 0.8); recipes->event.set(MakeFunctionEvent(Game, onRecipes)); addRenderObject(recipes, LR_MENU); use = new AquariaMenuItem; use->useQuad("Gui/use-button"); use->useGlow("particles/glow", 128, 64); use->position = worldRightCenter + Vector(0, -120); use->alpha = 0; use->scale = Vector(0.8, 0.8); use->event.set(MakeFunctionEvent(Game, onUseTreasure)); addRenderObject(use, LR_MENU); prevFood = new AquariaMenuItem; prevFood->useQuad("Gui/arrow-left"); prevFood->useSound("click"); prevFood->useGlow("particles/glow", 64, 32); prevFood->position = worldLeftCenter + Vector(-50, -130); prevFood->alpha = 0; prevFood->event.set(MakeFunctionEvent(Game, onPrevFoodPage)); prevFood->scale = Vector(0.6, 0.6); prevFood->setCanDirMove(false); addRenderObject(prevFood, LR_MENU); nextFood = new AquariaMenuItem; nextFood->useQuad("Gui/arrow-right"); nextFood->useSound("click"); nextFood->useGlow("particles/glow", 64, 32); nextFood->position = worldLeftCenter + Vector(50, -130); nextFood->alpha = 0; nextFood->setCanDirMove(false); nextFood->event.set(MakeFunctionEvent(Game, onNextFoodPage)); nextFood->scale = Vector(0.6, 0.6); addRenderObject(nextFood, LR_MENU); prevTreasure = new AquariaMenuItem; prevTreasure->useQuad("Gui/arrow-left"); prevTreasure->useSound("click"); prevTreasure->useGlow("particles/glow", 64, 32); prevTreasure->position = worldLeftCenter + Vector(-50, -130); prevTreasure->alpha = 0; prevTreasure->setCanDirMove(false); prevTreasure->scale = Vector(0.6, 0.6); prevTreasure->event.set(MakeFunctionEvent(Game, onPrevTreasurePage)); prevTreasure->setCanDirMove(false); addRenderObject(prevTreasure, LR_MENU); nextTreasure = new AquariaMenuItem; nextTreasure->useQuad("Gui/arrow-right"); nextTreasure->useSound("click"); nextTreasure->useGlow("particles/glow", 64, 32); nextTreasure->position = worldLeftCenter + Vector(50, -130); nextTreasure->alpha = 0; nextTreasure->scale = Vector(0.6, 0.6); nextTreasure->event.set(MakeFunctionEvent(Game, onNextTreasurePage)); nextTreasure->setCanDirMove(false); addRenderObject(nextTreasure, LR_MENU); circlePageNum = new BitmapText(&dsq->smallFont); circlePageNum->color = Vector(0,0,0); circlePageNum->position = worldLeftCenter + Vector(0, -142); circlePageNum->alpha = 0; circlePageNum->followCamera = 1; addRenderObject(circlePageNum, LR_MENU); foodHolders.resize(3); int holders=0; for (i = 0; i < foodHolders.size(); i++) { foodHolders[i] = new FoodHolder(i); foodHolders[i]->alpha = 0; float angle = (float(holders)/float(foodHolders.size()))*PI*2; foodHolders[i]->position = rightCenter + Vector(sinf(angle), cosf(angle))*radius; holders ++; menuBg->addChild(foodHolders[i], PM_POINTER); } previewRecipe = new Quad; previewRecipe->alphaMod = 0.75; previewRecipe->followCamera = 1; previewRecipe->alpha = 0; previewRecipe->scale = Vector(0.7, 0.7); previewRecipe->scale.interpolateTo(Vector(0.9, 0.9), 0.5, -1, 1, 1); previewRecipe->position = worldRightCenter; addRenderObject(previewRecipe, LR_MENU); showRecipe = new Quad(); showRecipe->followCamera = 1; showRecipe->position = Vector(575,250); addRenderObject(showRecipe, LR_MENU); float scrollx = 555; recipeMenu.scroll = new Quad("gui/recipe-scroll", Vector(scrollx, 200)); recipeMenu.scroll->followCamera = 1; recipeMenu.scroll->alpha = 0; addRenderObject(recipeMenu.scroll, LR_RECIPES); // LR_HUD3 recipeMenu.scrollEnd = new Quad("gui/recipe-scroll-end", Vector(scrollx, 400)); recipeMenu.scrollEnd->followCamera = 1; recipeMenu.scrollEnd->alpha = 0; addRenderObject(recipeMenu.scrollEnd, LR_RECIPES); recipeMenu.header = new BitmapText(&dsq->font); recipeMenu.header->color = 0; recipeMenu.header->followCamera = 1; recipeMenu.header->setText(dsq->continuity.stringBank.get(2007)); recipeMenu.header->alpha = 0; recipeMenu.header->position = Vector(scrollx, 5); //10 addRenderObject(recipeMenu.header, LR_RECIPES); recipeMenu.page = new BitmapText(&dsq->smallFont); recipeMenu.page->color = 0; recipeMenu.page->followCamera = 1; recipeMenu.page->position = Vector(scrollx, 400); recipeMenu.page->setText(dsq->continuity.stringBank.get(2006)); recipeMenu.page->alpha = 0; addRenderObject(recipeMenu.page, LR_RECIPES); recipeMenu.prevPage = new AquariaMenuItem; recipeMenu.prevPage->useQuad("Gui/arrow-left"); recipeMenu.prevPage->useSound("click"); recipeMenu.prevPage->useGlow("particles/glow", 64, 32); recipeMenu.prevPage->position = Vector(scrollx - 150, 410); recipeMenu.prevPage->alpha = 0; recipeMenu.prevPage->event.set(MakeFunctionEvent(Game, onPrevRecipePage)); recipeMenu.prevPage->scale = Vector(0.8, 0.8); addRenderObject(recipeMenu.prevPage, LR_RECIPES); recipeMenu.nextPage = new AquariaMenuItem; recipeMenu.nextPage->useQuad("Gui/arrow-right"); recipeMenu.nextPage->useSound("click"); recipeMenu.nextPage->useGlow("particles/glow", 64, 32); recipeMenu.nextPage->position = Vector(scrollx + 150, 410); recipeMenu.nextPage->alpha = 0; recipeMenu.nextPage->event.set(MakeFunctionEvent(Game, onNextRecipePage)); recipeMenu.nextPage->scale = Vector(0.8, 0.8); addRenderObject(recipeMenu.nextPage, LR_RECIPES); petSlots.resize(dsq->continuity.petData.size()); for (i = 0; i < petSlots.size(); i++) { PetData *p = dsq->continuity.getPetData(i); if (p) { petSlots[i] = new PetSlot(i); petSlots[i]->alpha = 0; float angle = (float(i)/float(petSlots.size()))*PI*2; petSlots[i]->position = center + Vector(sinf(angle), cosf(angle))*(radius*0.9f); menuBg->addChild(petSlots[i], PM_POINTER); } } foodHolders.resize(4); foodHolders[3] = new FoodHolder(-1, true); foodHolders[3]->alpha = 0; foodHolders[3]->position = rightCenter + Vector(96, 150); menuBg->addChild(foodHolders[3], PM_POINTER); int outer = 0; int inner = 0; for (i = 0; i < songSlots.size(); i++) { songSlots[i] = new SongSlot(i); float angle = 0; SongType s = (SongType)dsq->continuity.getSongTypeBySlot(i); if (dsq->continuity.isSongTypeForm(s)) { angle = (float(outer)/float(numForms))*PI*2; songSlots[i]->position = center + Vector(sinf(angle), cosf(angle))*radius; outer ++; } else { angle = (float(inner)/float(songSlots.size()-numForms))*PI*2 + PI; songSlots[i]->position = center + Vector(sinf(angle), cosf(angle))*radius*0.4f; inner ++; } menuBg->addChild(songSlots[i], PM_POINTER); } menuSongs = 0; menuMoney = menuEXP = 0; menuDescription = new BitmapText(&dsq->smallFont); menuDescription->setFontSize(14); menuDescription->position = Vector(400, 450); menuDescription->setAlign(ALIGN_CENTER); menuDescription->setWidth(400); menuDescription->followCamera = 1; menuDescription->alpha = 0; addRenderObject(menuDescription, LR_MENU); currentInventoryPage = 0; int areYouShim = -25; eAre = new Quad; eAre->position = Vector(400,448+areYouShim); eAre->setTexture("AreYouSure"); eAre->alpha = 0; eAre->followCamera = 1; addRenderObject(eAre, LR_MENU); eYes = new AquariaMenuItem; eYes->position = Vector(400-100,516+areYouShim); eYes->useQuad("Yes"); eYes->useGlow("particles/glow", 100, 32); eYes->event.set(MakeFunctionEvent(Game, onExitCheckYes)); eYes->alpha = 0; eYes->shareAlpha = 1; addRenderObject(eYes, LR_MENU); eNo = new AquariaMenuItem; eNo->position = Vector(400+100,516+areYouShim); eNo->useQuad("No"); eNo->useGlow("particles/glow", 100, 32); eNo->event.set(MakeFunctionEvent(Game, onExitCheckNo)); eNo->alpha = 0; eNo->shareAlpha = 1; addRenderObject(eNo, LR_MENU); eNo->setDirMove(DIR_LEFT, eYes); eYes->setDirMove(DIR_RIGHT, eNo); menu.resize(10); for (i = 0; i < menu.size(); i++) menu[i] = new AquariaMenuItem; int ty = 530; //menu[0]->setLabel("Continue"); menu[0]->event.set(MakeFunctionEvent(Game, onInGameMenuContinue)); menu[0]->useGlow("particles/glow", 200, 100); //menu[0]->position = Vector(150, 550); menu[0]->position = Vector(150-30, ty-10); //menu[1]->setLabel("Exit"); menu[1]->useGlow("particles/glow", 200, 100); menu[1]->event.set(MakeFunctionEvent(Game, onInGameMenuExit)); //menu[1]->position = Vector(800-150, 550); //menu[1]->position = Vector(800-150+30, ty); menu[1]->position = Vector(800-150+20, ty-10); menu[2]->setLabel("DebugSave"); menu[2]->event.set(MakeFunctionEvent(Game, onDebugSave)); menu[2]->position = Vector(400,ty+60); if (!dsq->isDeveloperKeys()) menu[2]->position = Vector(400, 12000); menu[2]->setCanDirMove(false); menu[3]->event.set(MakeFunctionEvent(Game, onLips)); menu[3]->useGlow("particles/glow", 64, 64); //menu[0]->position = Vector(150, 550); menu[3]->position = Vector(400, 195); menu[3]->setCanDirMove(false); lips = menu[3]; // options menu[4]->event.set(MakeFunctionEvent(Game, onOptionsMenu)); menu[4]->useGlow("particles/glow", 200, 32); menu[4]->position = Vector(400,ty+10); int gs = 40; menu[5]->event.set(MakeFunctionEvent(Game, switchToSongMenu)); menu[5]->useQuad("gui/icon-songs"); menu[5]->useGlow("particles/glow", gs, gs); menu[5]->useSound("Click"); menu[5]->position = Vector(400-60, 350); menuIconGlow = new Quad("particles/glow", menu[5]->position); menuIconGlow->alphaMod = 0.4; menuIconGlow->alpha = 0; menuIconGlow->setWidthHeight(80, 80); menuIconGlow->setBlendType(RenderObject::BLEND_ADD); menuIconGlow->followCamera = 1; addRenderObject(menuIconGlow, LR_MENU); menu[6]->event.set(MakeFunctionEvent(Game, switchToFoodMenu)); menu[6]->useQuad("gui/icon-food"); menu[6]->useGlow("particles/glow", gs, gs); menu[6]->useSound("Click"); menu[6]->position = Vector(400-20, 350); menu[7]->event.set(MakeFunctionEvent(Game, switchToPetMenu)); menu[7]->useQuad("gui/icon-pets"); menu[7]->useGlow("particles/glow", gs, gs); menu[7]->useSound("Click"); menu[7]->position = Vector(400+20, 350); menu[8]->event.set(MakeFunctionEvent(Game, switchToTreasureMenu)); menu[8]->useQuad("gui/icon-treasures"); menu[8]->useGlow("particles/glow", gs, gs); menu[8]->useSound("Click"); menu[8]->position = Vector(400+60, 350); menu[9]->event.set(MakeFunctionEvent(Game, onToggleHelpScreen)); menu[9]->useQuad("gui/icon-help"); menu[9]->useGlow("particles/glow", gs, gs); menu[9]->useSound("Click"); menu[9]->position = Vector(400+60*3, 410); /* menu[9]->event.set(MakeFunctionEvent(Game, sortFood)); menu[9]->setLabel("sort food"); menu[9]->position = Vector(100,100); */ for (i = 0; i < menu.size(); i++) { addRenderObject(menu[i], LR_MENU); menu[i]->alpha = 0; } ((AquariaMenuItem*)menu[5])->setDirMove(DIR_DOWN, ((AquariaMenuItem*)menu[0])); ((AquariaMenuItem*)menu[6])->setDirMove(DIR_DOWN, ((AquariaMenuItem*)menu[4])); ((AquariaMenuItem*)menu[7])->setDirMove(DIR_DOWN, ((AquariaMenuItem*)menu[4])); ((AquariaMenuItem*)menu[8])->setDirMove(DIR_DOWN, ((AquariaMenuItem*)menu[1])); ((AquariaMenuItem*)menu[0])->setDirMove(DIR_UP, ((AquariaMenuItem*)menu[5])); ((AquariaMenuItem*)menu[1])->setDirMove(DIR_UP, ((AquariaMenuItem*)menu[8])); ((AquariaMenuItem*)menu[4])->setDirMove(DIR_UP, ((AquariaMenuItem*)menu[6])); // ---------- FOOD MENU foodSlots.resize(foodPageSize); Vector worldCenter(222, 252); int foodSlotRadius = 96; for (i = 0; i < foodSlots.size(); i++) { foodSlots[i] = new FoodSlot(i); float angle = (float(food)/float(foodSlots.size()))*PI*2; foodSlots[i]->position = worldCenter + Vector(sinf(angle), cosf(angle))*foodSlotRadius; foodSlots[i]->setOriginalPosition(foodSlots[i]->position); food ++; foodSlots[i]->alphaMod = 0; foodSlots[i]->followCamera = 1; foodSlots[i]->scaleFactor = 0.75; //foodSlots[i]->parentManagedPointer = 1; //menuBg->addChild(foodSlots[i]); //foodSlots[i]->position = menuBg->getWorldCollidePosition(foodSlots[i]->position); addRenderObject(foodSlots[i], LR_HUD2); } foodLabel = new BitmapText(&dsq->smallFont); { foodLabel->alpha = 0; foodLabel->setAlign(ALIGN_CENTER); foodLabel->followCamera = 1; foodLabel->setFontSize(20); foodLabel->position = center - Vector(0, 16) + Vector(0,-32); foodLabel->scale = Vector(1, 1); } menuBg->addChild(foodLabel, PM_POINTER); foodDescription = new BitmapText(&dsq->smallFont); { foodDescription->alpha = 0; foodDescription->setAlign(ALIGN_CENTER); foodDescription->followCamera = 1; foodDescription->position = center + Vector(0, 8) + Vector(0,-32); foodDescription->scale = Vector(0.8, 0.8); foodDescription->setWidth(240); } menuBg->addChild(foodDescription, PM_POINTER); // ---------- TREASURES int treasureSlotRadius = 96; treasureSlots.resize(treasurePageSize); for (i = 0; i < treasureSlots.size(); i++) { treasureSlots[i] = new TreasureSlot(i); float angle = (float(i)/float(treasureSlots.size()))*PI*2; treasureSlots[i]->position = worldCenter + Vector(sinf(angle), cosf(angle))*treasureSlotRadius; treasureSlots[i]->alphaMod = 0; treasureSlots[i]->followCamera = 1; //treasureSlots[i]->scaleFactor = 0.75; addRenderObject(treasureSlots[i], LR_MENU); } treasureLabel = new BitmapText(&dsq->smallFont); { treasureLabel->alpha = 0; treasureLabel->setAlign(ALIGN_CENTER); treasureLabel->followCamera = 1; treasureLabel->setFontSize(20); treasureLabel->position = center - Vector(0, 16); treasureLabel->scale = Vector(1, 1); } menuBg->addChild(treasureLabel, PM_POINTER); treasureDescription = new ToolTip(); treasureDescription->alpha = 0; treasureDescription->setAreaFromCenter(Vector(400,200), 800, 400); treasureDescription->required = true; addRenderObject(treasureDescription, LR_HUD); foodTips.push_back(tip); treasureCloseUp = new Quad(); treasureCloseUp->position = rightCenter; treasureCloseUp->alpha = 0; menuBg->addChild(treasureCloseUp, PM_POINTER); menuBg->alpha = 0; } void Game::onNextRecipePage() { game->recipeMenu.goNextPage(); } void Game::onPrevRecipePage() { game->recipeMenu.goPrevPage(); } void Game::toggleOverrideZoom(bool on) { if (avatar) { if (on ) { if (avatar->isEntityDead()) return; } if (!on && avatar->zoomOverriden == true) { dsq->globalScale.stop(); avatar->myZoom = dsq->globalScale; } avatar->zoomOverriden = on; } } void Game::addProgress() { if (progressBar) { progressBar->progress(); } } void Game::endProgress() { if (progressBar) { progressBar->setLife(1); progressBar->setDecayRate(1.0f/0.5f); progressBar->fadeAlphaWithLife = 1; progressBar = 0; } } bool Game::loadSceneXML(std::string scene) { bgSfxLoop = ""; airSfxLoop = ""; elementTemplatePack = "Main"; entitySaveData.clear(); std::string fn = getSceneFilename(scene); if (!exists(fn)) { //errorLog("Could not find [" + fn + "]"); //msg("Could not find map [" + fn + "]"); std::string s = "Could not find map [" + fn + "]"; debugLog(s); dsq->screenMessage(s); return false; } TiXmlDocument doc; doc.LoadFile(fn); if (saveFile) { delete saveFile; saveFile = 0; } if (!saveFile) { saveFile = new TiXmlDocument(); } addProgress(); clearObsRows(); warpAreas.clear(); TiXmlElement *lensFlare = doc.FirstChildElement("LensFlare"); while (lensFlare) { LensFlare *l = new LensFlare; SimpleIStringStream is(lensFlare->Attribute("tex")); int w = -1, h=-1; w = atoi(lensFlare->Attribute("w")); h = atoi(lensFlare->Attribute("h")); std::string tex; while (is >> tex) { if (!tex.empty()) l->addFlare(tex, Vector(1,1,1), w, h); } SimpleIStringStream is2(lensFlare->Attribute("inc")); is2 >> l->inc; l->maxLen = atoi(lensFlare->Attribute("maxLen")); /* l->addFlare("flares/flare0", Vector(1,1,0.5)); l->addFlare("flares/flare1", Vector(1,1,1)); l->addFlare("flares/flare2", Vector(0.5,1,1)); l->addFlare("flares/flare2", Vector(1,1,1)); */ l->position = Vector(atoi(lensFlare->Attribute("x")),atoi(lensFlare->Attribute("y"))); addRenderObject(l, LR_LIGHTING); TiXmlElement lSF("LensFlare"); lSF.SetAttribute("inc", lensFlare->Attribute("inc")); lSF.SetAttribute("x", lensFlare->Attribute("x")); lSF.SetAttribute("y", lensFlare->Attribute("y")); lSF.SetAttribute("tex", lensFlare->Attribute("tex")); lSF.SetAttribute("w", lensFlare->Attribute("w")); lSF.SetAttribute("h", lensFlare->Attribute("h")); lSF.SetAttribute("maxLen", lensFlare->Attribute("maxLen")); saveFile->InsertEndChild(lSF); lensFlare = lensFlare->NextSiblingElement("LensFlare"); } TiXmlElement *level = doc.FirstChildElement("Level"); if (level) { TiXmlElement levelSF("Level"); if (level->Attribute("tileset")) { elementTemplatePack = level->Attribute("tileset"); loadElementTemplates(elementTemplatePack); levelSF.SetAttribute("tileset", elementTemplatePack); } else if (level->Attribute("elementTemplatePack")) { elementTemplatePack = level->Attribute("elementTemplatePack"); loadElementTemplates(elementTemplatePack); levelSF.SetAttribute("tileset", elementTemplatePack); } else return false; if (level->Attribute("waterLevel")) { useWaterLevel = true; waterLevel = atoi(level->Attribute("waterLevel")); saveWaterLevel = atoi(level->Attribute("waterLevel")); levelSF.SetAttribute("waterLevel", waterLevel.x); } if (level->Attribute("worldMapIndex")) { worldMapIndex = atoi(level->Attribute("worldMapIndex")); levelSF.SetAttribute("worldMapIndex", worldMapIndex); } if (level->Attribute("bgSfxLoop")) { bgSfxLoop = level->Attribute("bgSfxLoop"); levelSF.SetAttribute("bgSfxLoop", bgSfxLoop); } if (level->Attribute("airSfxLoop")) { airSfxLoop = level->Attribute("airSfxLoop"); levelSF.SetAttribute("airSfxLoop", airSfxLoop); } if (level->Attribute("bnat")) { bNatural = atoi(level->Attribute("bnat")); levelSF.SetAttribute("bnat", 1); } else { bNatural = false; } /* if (level->Attribute("darkLayer")) { int v = (atoi(level->Attribute("darkLayer"))); levelSF.SetAttribute("darkLayer", v); } */ dsq->darkLayer.toggle(true); if (level->Attribute("bgRepeat")) { SimpleIStringStream is(level->Attribute("bgRepeat")); is >> backgroundImageRepeat; levelSF.SetAttribute("bgRepeat", level->Attribute("bgRepeat")); } if (level->Attribute("cameraConstrained")) { SimpleIStringStream is(level->Attribute("cameraConstrained")); is >> cameraConstrained; levelSF.SetAttribute("cameraConstrained", cameraConstrained); std::ostringstream os; os << "cameraConstrained: " << cameraConstrained; debugLog(os.str()); } if (level->Attribute("maxZoom")) { maxZoom = atof(level->Attribute("maxZoom")); std::ostringstream os; os << maxZoom; levelSF.SetAttribute("maxZoom", os.str()); } if (level->Attribute("natureForm")) { sceneNatureForm = level->Attribute("natureForm"); levelSF.SetAttribute("natureForm", sceneNatureForm); } if (level->Attribute("bg")) { std::string tex = std::string(level->Attribute("bg")); if (!tex.empty()) { /* if (tex.find('.') == std::string::npos) bg->setTexture(tex+""); else bg->setTexture(tex); */ bg->setTexture(tex); bg->setWidthHeight(900,600); levelSF.SetAttribute("bg", tex); } else { bg->alpha = 0; } } else { bg->alpha = 0; //grad->alpha =0; } gradTop = gradBtm = Vector(0,0,0); if (level->Attribute("gradient")) { if (level->Attribute("gradTop")) { SimpleIStringStream is(level->Attribute("gradTop")); is >> gradTop.x >> gradTop.y >> gradTop.z; levelSF.SetAttribute("gradTop", level->Attribute("gradTop")); } if (level->Attribute("gradBtm")) { SimpleIStringStream is(level->Attribute("gradBtm")); is >> gradBtm.x >> gradBtm.y >> gradBtm.z; levelSF.SetAttribute("gradBtm", level->Attribute("gradBtm")); } createGradient(); levelSF.SetAttribute("gradient", 1); } if (level->Attribute("parallax")) { SimpleIStringStream is(level->Attribute("parallax")); float x,y,z,r,g,b; is >> x >> y >> z >> r >> g >> b; RenderObjectLayer *l = 0; l = &dsq->renderObjectLayers[LR_ELEMENTS10]; l->followCamera = x; l = &dsq->renderObjectLayers[LR_ELEMENTS11]; l->followCamera = y; l = &dsq->renderObjectLayers[LR_ENTITIES_MINUS4_PLACEHOLDER]; l->followCamera = y; l = &dsq->renderObjectLayers[LR_ENTITIES_MINUS4]; l->followCamera = y; l = &dsq->renderObjectLayers[LR_ELEMENTS12]; l->followCamera = z; l = &dsq->renderObjectLayers[LR_ELEMENTS14]; l->followCamera = r; l = &dsq->renderObjectLayers[LR_ELEMENTS15]; l->followCamera = g; l = &dsq->renderObjectLayers[LR_ELEMENTS16]; l->followCamera = b; levelSF.SetAttribute("parallax", level->Attribute("parallax")); } if (level->Attribute("parallaxLock")) { int x, y, z, r, g, b; SimpleIStringStream is(level->Attribute("parallaxLock")); is >> x >> y >> z >> r >> g >> b; RenderObjectLayer *l = 0; l = &dsq->renderObjectLayers[LR_ELEMENTS10]; l->followCameraLock = x; l = &dsq->renderObjectLayers[LR_ELEMENTS11]; l->followCameraLock = y; l = &dsq->renderObjectLayers[LR_ELEMENTS12]; l->followCameraLock = z; l = &dsq->renderObjectLayers[LR_ELEMENTS14]; l->followCameraLock = r; l = &dsq->renderObjectLayers[LR_ELEMENTS15]; l->followCameraLock = g; l = &dsq->renderObjectLayers[LR_ELEMENTS16]; l->followCameraLock = b; levelSF.SetAttribute("parallaxLock", level->Attribute("parallaxLock")); } if (level->Attribute("bg2")) { std::string tex = std::string(level->Attribute("bg2")); if (!tex.empty()) { /* if (tex.find('.') == std::string::npos) bg2->setTexture(tex+""); else bg2->setTexture(tex); */ bg2->setTexture(tex); bg2->setWidthHeight(900,600); levelSF.SetAttribute("bg2", tex); } else bg2->alpha = 0; //createGradient(); bg2->alpha = 0; bg->alpha = 0; } else { bg2->alpha = 0; //grad->alpha =0; } if (level->Attribute("backdrop")) { std::string backdrop = level->Attribute("backdrop"); backdropQuad = new Quad; backdropQuad->setTexture(backdrop); backdropQuad->blendEnabled = false; if (level->Attribute("bd-x") && level->Attribute("bd-y")) { int x = atoi(level->Attribute("bd-x")); int y = atoi(level->Attribute("bd-y")); backdropQuad->position = Vector(x,y); levelSF.SetAttribute("bd-x", x); levelSF.SetAttribute("bd-y", y); } if (level->Attribute("bd-w") && level->Attribute("bd-h")) { int w = atoi(level->Attribute("bd-w")); int h = atoi(level->Attribute("bd-h")); backdropQuad->setWidthHeight(w, h); levelSF.SetAttribute("bd-w", w); levelSF.SetAttribute("bd-h", h); } backdropQuad->toggleCull(false); //backdropQuad->followCamera = 1; addRenderObject(backdropQuad, LR_SCENEBACKGROUNDIMAGE); // upper left justify backdropQuad->offset = Vector((backdropQuad->getWidth()*backdropQuad->scale.x)/2.0f, (backdropQuad->getHeight()*backdropQuad->scale.y)/2.0f); // save levelSF.SetAttribute("backdrop", backdrop.c_str()); //backdrop="cavebg" bd-w="2400" bd-h="2400" } musicToPlay = ""; if (level->Attribute("music")) { setMusicToPlay(level->Attribute("music")); saveMusic = level->Attribute("music"); levelSF.SetAttribute("music", level->Attribute("music")); /* // if using SDL_Mixer if (!core->sound->isPlayingMusic(musicToPlay)) { core->sound->fadeMusic(SFT_OUT, 1); } */ } if (level->Attribute("sceneColor")) { SimpleIStringStream in(level->Attribute("sceneColor")); in >> sceneColor.x >> sceneColor.y >> sceneColor.z; levelSF.SetAttribute("sceneColor", level->Attribute("sceneColor")); } saveFile->InsertEndChild(levelSF); } else return false; TiXmlElement *obs = doc.FirstChildElement("Obs"); if (obs) { int tx, ty, len; SimpleIStringStream is(obs->Attribute("d")); while (is >> tx) { is >> ty >> len; addObsRow(tx, ty, len); } addProgress(); } TiXmlElement *pathXml = doc.FirstChildElement("Path"); while (pathXml) { Path *path = new Path; path->name = pathXml->Attribute("name"); stringToLower(path->name); /* if (pathXml->Attribute("active")) { path.active = atoi(pathXml->Attribute("active")); } */ TiXmlElement *nodeXml = pathXml->FirstChildElement("Node"); while (nodeXml) { PathNode node; SimpleIStringStream is(nodeXml->Attribute("pos")); is >> node.position.x >> node.position.y; if (nodeXml->Attribute("ms")) { node.maxSpeed = atoi(nodeXml->Attribute("ms")); } if (nodeXml->Attribute("rect")) { SimpleIStringStream is(nodeXml->Attribute("rect")); int w,h; is >> w >> h; path->rect.setWidth(w); path->rect.setHeight(h); } if (nodeXml->Attribute("shape")) { path->pathShape = (PathShape)atoi(nodeXml->Attribute("shape")); } path->nodes.push_back(node); nodeXml = nodeXml->NextSiblingElement("Node"); } path->refreshScript(); addPath(path); addProgress(); pathXml = pathXml->NextSiblingElement("Path"); } TiXmlElement *quad = doc.FirstChildElement("Quad"); while (quad) { TiXmlElement qSF("Quad"); int x=0, y=0, z=0; int w=0,h=0; bool cull=true; bool solid = false; std::string justify; std::string tex; qSF.SetAttribute("x", x = atoi(quad->Attribute("x"))); qSF.SetAttribute("y", y = atoi(quad->Attribute("y"))); //qSF.SetAttribute("z", z = atoi(quad->Attribute("z"))); qSF.SetAttribute("w", w = atoi(quad->Attribute("w"))); qSF.SetAttribute("h", h = atoi(quad->Attribute("h"))); qSF.SetAttribute("tex", tex = (quad->Attribute("tex"))); qSF.SetAttribute("cull", cull = atoi(quad->Attribute("cull"))); qSF.SetAttribute("justify", justify = (quad->Attribute("justify"))); if (quad->Attribute("solid")) qSF.SetAttribute("solid", solid = atoi(quad->Attribute("solid"))); Quad *q = new Quad; q->position = Vector(x,y,z); /* if (solid) Texture::pngLoadHaloFix = false; */ q->setTexture(tex); /* if (solid) Texture::pngLoadHaloFix = true; */ q->toggleCull(cull); q->setWidthHeight(w, h); if (justify == "upperLeft") { q->offset = Vector((q->getWidth()*q->scale.x)/2.0f, (q->getHeight()*q->scale.y)/2.0f); } addRenderObject(q, LR_BACKGROUND); saveFile->InsertEndChild(qSF); quad = quad->NextSiblingElement("Quad"); } TiXmlElement *floater = doc.FirstChildElement("Floater"); while(floater) { TiXmlElement nSF("Floater"); if (!floater->Attribute("boxW") || !floater->Attribute("boxH")) { errorLog ("no boxW/boxH"); break; } int boxW, boxH, x, y, fx, fy; std::string tex; nSF.SetAttribute("boxW", boxW = atoi(floater->Attribute("boxW"))); nSF.SetAttribute("boxH", boxH = atoi(floater->Attribute("boxH"))); tex = floater->Attribute("tex"); nSF.SetAttribute("tex", tex); nSF.SetAttribute("x", x = atoi(floater->Attribute("x"))); nSF.SetAttribute("y", y = atoi(floater->Attribute("y"))); nSF.SetAttribute("fx", fx = atoi(floater->Attribute("fx"))); nSF.SetAttribute("fy", fy = atoi(floater->Attribute("fy"))); /* Floater *f = new Floater(Vector(x,y), Vector(fx, fy), boxW, boxH, tex); { } addRenderObject(f, LR_BACKGROUND); saveFile->InsertEndChild(nSF); */ floater = floater->NextSiblingElement("Floater"); } /* TiXmlElement *breakable = doc.FirstChildElement("Breakable"); while(breakable) { TiXmlElement nSF("Breakable"); if (!breakable->Attribute("boxW") || !breakable->Attribute("boxH")) { errorLog ("Breakable error.. no boxW/boxH"); break; } int boxW, boxH; std::string tex; nSF.SetAttribute("boxW", boxW = atoi(breakable->Attribute("boxW"))); nSF.SetAttribute("boxH", boxH = atoi(breakable->Attribute("boxH"))); tex = breakable->Attribute("tex"); nSF.SetAttribute("tex", tex); Breakable *n = new Breakable(boxW, boxH, tex); { nSF.SetAttribute("x", n->position.x = atoi(breakable->Attribute("x"))); nSF.SetAttribute("y", n->position.y = atoi(breakable->Attribute("y"))); int w=0, h=0; if (breakable->Attribute("w")) nSF.SetAttribute("w", w = atoi(breakable->Attribute("w"))); if (breakable->Attribute("h")) nSF.SetAttribute("h", h= atoi(breakable->Attribute("h"))); if (w != 0 && h != 0) { n->setWidthHeight(w, h); } } addRenderObject(n, LR_BACKGROUND); saveFile->InsertEndChild(nSF); breakable = breakable->NextSiblingElement("Breakable"); } */ TiXmlElement *warpArea = doc.FirstChildElement("WarpArea"); while(warpArea) { TiXmlElement waSF("WarpArea"); WarpArea a; waSF.SetAttribute("x", a.position.x = atoi(warpArea->Attribute("x"))); waSF.SetAttribute("y", a.position.y = atoi(warpArea->Attribute("y"))); if (warpArea->Attribute("radius")) waSF.SetAttribute("radius", a.radius = atoi(warpArea->Attribute("radius"))); bool isRect = false; if (warpArea->Attribute("w")) { isRect = true; waSF.SetAttribute("w", a.w = atoi(warpArea->Attribute("w"))); waSF.SetAttribute("h", a.h = atoi(warpArea->Attribute("h"))); } if (warpArea->Attribute("g")) { waSF.SetAttribute("g", a.generated = atoi(warpArea->Attribute("g"))); } std::string sceneString = warpArea->Attribute("scene"); waSF.SetAttribute("scene", sceneString.c_str()); /* waSF.SetAttribute("ax", a.avatarPosition.x = atoi(warpArea->Attribute("ax"))); waSF.SetAttribute("ay", a.avatarPosition.y = atoi(warpArea->Attribute("ay"))); */ SimpleIStringStream is(sceneString); std::string sceneName, warpAreaType, side; is >> sceneName >> warpAreaType >> a.spawnOffset.x >> a.spawnOffset.y; a.spawnOffset.normalize2D(); a.sceneName = sceneName; a.warpAreaType = warpAreaType; //a.side = side; // saveFile->InsertEndChild(waSF); bool add = true; std::string flagCheck; if (warpArea->Attribute("flagCheck")) { flagCheck = warpArea->Attribute("flagCheck"); add = doFlagCheck(flagCheck); } if (add) warpAreas.push_back(a); if (a.generated) { setWarpAreaSceneName(a); } warpArea = warpArea->NextSiblingElement("WarpArea"); } TiXmlElement *schoolFish = doc.FirstChildElement("SchoolFish"); while(schoolFish) { int num = atoi(schoolFish->Attribute("num")); int x, y; int id; x = atoi(schoolFish->Attribute("x")); y = atoi(schoolFish->Attribute("y")); id = atoi(schoolFish->Attribute("id")); std::string gfx, texture="flock-0001"; if (schoolFish->Attribute("gfx")) { gfx = schoolFish->Attribute("gfx"); texture = gfx; /* std::ostringstream os; os << "flock-" << gfx << ""; texture = os.str(); */ } int layer = 0; if (schoolFish->Attribute("layer")) { layer = atoi(schoolFish->Attribute("layer")); } float size = 1; if (schoolFish->Attribute("size")) { SimpleIStringStream is(schoolFish->Attribute("size")); is >> size; } int maxSpeed = 0; if (schoolFish->Attribute("maxSpeed")) maxSpeed = atoi(schoolFish->Attribute("maxSpeed")); int range = 0; if (schoolFish->Attribute("range")) range = atoi(schoolFish->Attribute("range")); for (int i = 0; i < num; i++) { SchoolFish *s = new SchoolFish(texture); { s->position = Vector(x+i*5,y+i*5); s->startPos = s->position; s->addToFlock(id); if (range != 0) s->range = range; if (maxSpeed != 0) s->setMaxSpeed(maxSpeed); std::ostringstream os; os << "adding schoolfish (" << s->position.x << ", " << s->position.y << ")"; debugLog(os.str()); } if (layer == -3) { addRenderObject(s, LR_ELEMENTS11); } else { if (chance(50)) addRenderObject(s, LR_ENTITIES2); else addRenderObject(s, LR_ENTITIES); } /*if (layer == 1) { addRenderObject(s, LR_ENTITIES); } else { // school fish layer hack // because we want all fish on top dammit //addRenderObject(s, LR_ENTITIES2); // or... not? //hrm.. why not? if (chance(50)) addRenderObject(s, LR_ENTITIES2); else addRenderObject(s, LR_ENTITIES); //s->setOverrideRenderPass(4); } */ s->applyLayer(layer); s->scale *= size; //s->update(0.033); } schoolFish = schoolFish->NextSiblingElement("SchoolFish"); TiXmlElement newSF("SchoolFish"); newSF.SetAttribute("x", x); newSF.SetAttribute("y", y); newSF.SetAttribute("id", id); newSF.SetAttribute("num", num); if (range != 0) newSF.SetAttribute("range", range); if (maxSpeed != 0) newSF.SetAttribute("maxSpeed", maxSpeed); if (layer != 0) newSF.SetAttribute("layer", layer); if (!gfx.empty()) newSF.SetAttribute("gfx", gfx.c_str()); if (size != 1) newSF.SetAttribute("size", size); saveFile->InsertEndChild(newSF); } /* TiXmlElement *boxElement = doc.FirstChildElement("BoxElement"); while (boxElement) { BoxElement *b = new BoxElement(atoi(boxElement->Attribute("w")), atoi(boxElement->Attribute("h"))); b->position = Vector(atoi(boxElement->Attribute("x")), atoi(boxElement->Attribute("y"))); addRenderObject(b, LR_BLACKGROUND); b->position.z = boxElementZ; dsq->addElement(b); boxElement = boxElement->NextSiblingElement("BoxElement"); } */ TiXmlElement *simpleElements = doc.FirstChildElement("SE"); while (simpleElements) { int idx, x, y, rot; float sz,sz2; if (simpleElements->Attribute("d")) { SimpleIStringStream is(simpleElements->Attribute("d")); while (is >> idx) { is >> x >> y >> rot; Element *e = createElement(idx, Vector(x,y), 4); e->rotation.z = rot; } } if (simpleElements->Attribute("e")) { SimpleIStringStream is2(simpleElements->Attribute("e")); int l = atoi(simpleElements->Attribute("l")); while(is2 >> idx) { is2 >> x >> y >> rot; Element *e = createElement(idx, Vector(x,y), l); e->rotation.z = rot; } } if (simpleElements->Attribute("f")) { SimpleIStringStream is2(simpleElements->Attribute("f")); int l = atoi(simpleElements->Attribute("l")); while(is2 >> idx) { is2 >> x >> y >> rot >> sz; Element *e = createElement(idx, Vector(x,y), l); e->scale = Vector(sz,sz); e->rotation.z = rot; } } if (simpleElements->Attribute("g")) { SimpleIStringStream is2(simpleElements->Attribute("g")); int l = atoi(simpleElements->Attribute("l")); while(is2 >> idx) { int fh, fv; is2 >> x >> y >> rot >> sz >> fh >> fv; Element *e = createElement(idx, Vector(x,y), l); if (fh) e->flipHorizontal(); if (fv) e->flipVertical(); e->scale = Vector(sz,sz); e->rotation.z = rot; } } if (simpleElements->Attribute("h")) { SimpleIStringStream is2(simpleElements->Attribute("h")); int l = atoi(simpleElements->Attribute("l")); while(is2 >> idx) { int fh, fv; int flags; is2 >> x >> y >> rot >> sz >> fh >> fv >> flags; Element *e = createElement(idx, Vector(x,y), l); e->elementFlag = (ElementFlag)flags; if (e->elementFlag >= EF_MAX || e->elementFlag < EF_NONE) e->elementFlag = EF_NONE; if (fh) e->flipHorizontal(); if (fv) e->flipVertical(); e->scale = Vector(sz,sz); e->rotation.z = rot; } } if (simpleElements->Attribute("i")) { SimpleIStringStream is2(simpleElements->Attribute("i")); int l = atoi(simpleElements->Attribute("l")); while(is2 >> idx) { int fh, fv; int flags; int efxIdx; is2 >> x >> y >> rot >> sz >> fh >> fv >> flags >> efxIdx; if (sz < MIN_SIZE) sz = MIN_SIZE; Element *e = createElement(idx, Vector(x,y), l); e->elementFlag = (ElementFlag)flags; if (fh) e->flipHorizontal(); if (fv) e->flipVertical(); e->scale = Vector(sz,sz); e->rotation.z = rot; e->setElementEffectByIndex(efxIdx); } } if (simpleElements->Attribute("j")) { SimpleIStringStream is2(simpleElements->Attribute("j")); int l = atoi(simpleElements->Attribute("l")); while(is2 >> idx) { int fh, fv; int flags; int efxIdx; int repeat; is2 >> x >> y >> rot >> sz >> fh >> fv >> flags >> efxIdx >> repeat; if (sz < MIN_SIZE) sz = MIN_SIZE; Element *e = createElement(idx, Vector(x,y), l); e->elementFlag = (ElementFlag)flags; if (fh) e->flipHorizontal(); if (fv) e->flipVertical(); e->scale = Vector(sz,sz); e->rotation.z = rot; e->setElementEffectByIndex(efxIdx); if (repeat) e->repeatTextureToFill(true); } } if (simpleElements->Attribute("k")) { SimpleIStringStream is2(simpleElements->Attribute("k")); int l = atoi(simpleElements->Attribute("l")); int c = 0; while(is2 >> idx) { int fh, fv; int flags; int efxIdx; int repeat; is2 >> x >> y >> rot >> sz >> sz2 >> fh >> fv >> flags >> efxIdx >> repeat; if (sz < MIN_SIZE) sz = MIN_SIZE; if (sz2 < MIN_SIZE) sz2 = MIN_SIZE; Element *e = createElement(idx, Vector(x,y), l); e->elementFlag = (ElementFlag)flags; if (fh) e->flipHorizontal(); if (fv) e->flipVertical(); e->scale = Vector(sz,sz2); e->rotation.z = rot; e->setElementEffectByIndex(efxIdx); if (repeat) e->repeatTextureToFill(true); c++; if (c> 100) { c=0; addProgress(); } } } simpleElements = simpleElements->NextSiblingElement("SE"); } TiXmlElement *element = doc.FirstChildElement("Element"); while (element) { if (element->Attribute("idx")) { int x = atoi(element->Attribute("x")); int y = atoi(element->Attribute("y")); int idx = atoi(element->Attribute("idx")); int layer=LR_ELEMENTS5; float rot =0; bool flipH = false, flipV = false; if (element->Attribute("flipH")) flipH = atoi(element->Attribute("flipH")); if (element->Attribute("flipV")) flipV = atoi(element->Attribute("flipV")); if (element->Attribute("rot")) rot = atof(element->Attribute("rot")); if (element->Attribute("lyr")) layer = atoi(element->Attribute("lyr")); if (idx != -1) { Element *e = createElement(idx, Vector(x,y), layer); e->rotation.z = rot; if (flipH) e->flipHorizontal(); if (flipV) e->flipVertical(); if (element->Attribute("sz")) { SimpleIStringStream is(element->Attribute("sz")); is >> e->scale.x >> e->scale.y; } } } element = element->NextSiblingElement("Element"); } this->reconstructGrid(true); /* TiXmlElement *enemyNode = doc.FirstChildElement("Enemy"); while(enemyNode) { Vector pos; pos.x = atoi(enemyNode->Attribute("x")); pos.y = atoi(enemyNode->Attribute("y")); std::string type = enemyNode->Attribute("type"); std::string flagCheck; if (enemyNode->Attribute("flagCheck")) { flagCheck = enemyNode->Attribute("flagCheck"); } if (doFlagCheck(flagCheck)) Entity *e = createEnemy(type, pos, true, enemyNode, flagCheck, -1); enemyNode = enemyNode->NextSiblingElement("Enemy"); } */ TiXmlElement *entitiesNode = doc.FirstChildElement("Entities"); while(entitiesNode) { if (entitiesNode->Attribute("j")) { SimpleIStringStream is(entitiesNode->Attribute("j")); int idx, x, y, rot, groupID, id; std::string name; while (is >> idx) { name=""; if (idx == -1) is >> name; is >> x >> y >> rot >> groupID >> id; if (!name.empty()) dsq->game->createEntity(name, id, Vector(x,y), rot, true, "", ET_ENEMY); else dsq->game->createEntity(idx, id, Vector(x,y), rot, true, "", ET_ENEMY); } } entitiesNode = entitiesNode->NextSiblingElement("Entities"); } //assignEntitiesUniqueIDs(); //initEntities(); FOR_ENTITIES(i) { Entity *e = *i; e->onSceneFlipped(); } this->reconstructGrid(true); rebuildElementUpdateList(); setElementLayerFlags(); // HACK: Don't try to optimize the barrier layer in Mithalas Cathedral // since elements are turned off dynamically. if (nocasecmp(scene, "cathedral02") == 0) dsq->getRenderObjectLayer(LR_ELEMENTS3)->setOptimizeStatic(false); findMaxCameraValues(); endProgress(); return true; } void Game::setMusicToPlay(const std::string &m) { musicToPlay = m; stringToLower(musicToPlay); } void Game::findMaxCameraValues() { cameraMin.x = 20; cameraMin.y = 20; cameraMax.x = -1; cameraMax.y = -1; int i = 0; for (i = 0; i < obsRows.size(); i++) { ObsRow *r = &obsRows[i]; TileVector t(r->tx + r->len, r->ty); Vector v = t.worldVector(); if (v.x > cameraMax.x) { cameraMax.x = v.x; } if (v.y > cameraMax.y) { cameraMax.y = v.y; } } /* for (i = 0; i < dsq->getNumElements(); i++) { Element *e = dsq->getElement(i); if (e->position.x > cameraMax.x) cameraMax.x = e->position.x; if (e->position.y > cameraMax.y) cameraMax.y = e->position.y; } */ if (backdropQuad) { if (backdropQuad->getWidth() > cameraMax.x) { cameraMax.x = backdropQuad->getWidth(); } if (backdropQuad->getHeight() > cameraMax.y) { cameraMax.y = backdropQuad->getHeight(); } } } void Game::setWarpAreaSceneName(WarpArea &warpArea) { InStream in("data/warpAreas.txt"); std::string color, area1, dir1, area2, dir2; std::string line; while (std::getline(in, line)) { std::istringstream is(line); is >> color >> area1 >> dir1 >> area2 >> dir2; /* errorLog (color + " : " + area1 + " : " + dir1 + " : " + area2 + " : " + dir2); */ if (area2 == dsq->game->sceneName && warpArea.warpAreaType == color) { area2 = area1; dir2 = dir1; area1 = dsq->game->sceneName; } if (area1 == dsq->game->sceneName && warpArea.warpAreaType == color) { if (dir2=="Left") warpArea.spawnOffset = Vector(-1,0); else if (dir2=="Right") warpArea.spawnOffset = Vector(1,0); else if (dir2=="Up") warpArea.spawnOffset = Vector(0,-1); else if (dir2=="Down") warpArea.spawnOffset = Vector(0,1); warpArea.sceneName = area2; break; } } if (warpArea.sceneName.empty()) { errorLog(warpArea.warpAreaType + " WarpArea for " + dsq->game->sceneName + " not found"); } } bool Game::loadScene(std::string scene) { stringToLower(scene); sceneName = scene; if (scene.empty()) { return false; } #ifdef AQUARIA_DEMO int i = 0; for (; i < allowedMaps.size(); i++) { if (allowedMaps[i] == scene) break; } if (i == allowedMaps.size()) { exit(-1); } #endif loadingScene = true; bool ret = loadSceneXML(scene); loadingScene = false; return ret; /* std::string fn = ("data/maps/"+scene+".xml"); if (!exists(fn)) { loadSceneDAT(scene); return; } loadSceneXML(scene); */ /* */ } bool Game::saveScene(std::string scene) { if (!this->saveFile) return false; std::string fn = getSceneFilename(scene); TiXmlDocument saveFile(*this->saveFile); //this->saveFile->CopyTo(&saveFile); TiXmlElement *level = saveFile.FirstChildElement("Level"); TiXmlElement levelLocal("Level"); bool addIt = false; if (!level) { level = &levelLocal; addIt = true; } if (level) { level->SetAttribute("waterLevel", dsq->game->saveWaterLevel); if (grad) { level->SetAttribute("gradient", 1); std::ostringstream os; os << gradTop.x << " " << gradTop.y << " " << gradTop.z; level->SetAttribute("gradTop", os.str()); std::ostringstream os2; os2 << gradBtm.x << " " << gradBtm.y << " " << gradBtm.z; level->SetAttribute("gradBtm", os2.str()); } if (!saveMusic.empty()) { level->SetAttribute("music", saveMusic); } } if (addIt) { saveFile.InsertEndChild(levelLocal); } /* TiXmlElement level("Level"); level.SetAttribute("elementTemplatePack", elementTemplatePack); if (bg) { int pos = bg->texture->name.find_last_of('/')+1; int pos2 = bg->texture->name.find_last_of('.'); level.SetAttribute("bg", bg->texture->name.substr(pos, pos2-pos)); std::ostringstream os; os << sceneColor.x << " " << sceneColor.y << " " << sceneColor.z; level.SetAttribute("sceneColor", os.str()); } saveFile->InsertEndChild(level); */ std::ostringstream obs; int i = 0; for (i = 0; i < obsRows.size(); i++) { obs << obsRows[i].tx << " " << obsRows[i].ty << " " << obsRows[i].len << " "; } TiXmlElement obsXml("Obs"); obsXml.SetAttribute("d", obs.str()); saveFile.InsertEndChild(obsXml); for (i = 0; i < dsq->game->getNumPaths(); i++) { TiXmlElement pathXml("Path"); Path *p = dsq->game->getPath(i); pathXml.SetAttribute("name", p->name); //pathXml.SetAttribute("active", p->active); for (int n = 0; n < p->nodes.size(); n++) { TiXmlElement nodeXml("Node"); std::ostringstream os; os << int(p->nodes[n].position.x) << " " << int(p->nodes[n].position.y); nodeXml.SetAttribute("pos", os.str().c_str()); std::ostringstream os2; os2 << p->rect.getWidth() << " " << p->rect.getHeight(); nodeXml.SetAttribute("rect", os2.str().c_str()); nodeXml.SetAttribute("shape", (int)p->pathShape); if (p->nodes[n].maxSpeed != -1) { nodeXml.SetAttribute("ms", p->nodes[n].maxSpeed); } pathXml.InsertEndChild(nodeXml); } saveFile.InsertEndChild(pathXml); } for (i = 0; i < dsq->game->warpAreas.size(); i++) { WarpArea a = dsq->game->warpAreas[i]; TiXmlElement waSF("WarpArea"); waSF.SetAttribute("x", a.position.x); waSF.SetAttribute("y", a.position.y); if (a.radius > 0) waSF.SetAttribute("radius", a.radius); else if (a.w > 0 && a.h > 0) { waSF.SetAttribute("w", a.w); waSF.SetAttribute("h", a.h); } if (a.generated) { waSF.SetAttribute("g", 1); } std::ostringstream os; os << a.sceneName << " " << a.warpAreaType << " " << a.spawnOffset.x << " " << a.spawnOffset.y; waSF.SetAttribute("scene", os.str().c_str()); saveFile.InsertEndChild(waSF); } std::ostringstream simpleElements[LR_MAX]; for (i = 0; i < dsq->getNumElements(); i++) { Element *e = dsq->getElement(i); simpleElements[e->bgLayer] << e->templateIdx << " " << int(e->position.x) << " " << int(e->position.y) << " " << int(e->rotation.z) << " " << e->scale.x << " " << e->scale.y << " " << int(e->isfh()) << " " << int(e->isfv()) << " " << e->elementFlag << " " << e->getElementEffectIndex() << " " << e->isRepeatingTextureToFill() << " "; } if (dsq->game->entitySaveData.size() > 0) { TiXmlElement entitiesNode("Entities"); std::ostringstream os; for (int i = 0; i < dsq->game->entitySaveData.size(); i++) { EntitySaveData *e = &dsq->game->entitySaveData[i]; os << e->idx << " "; if (e->idx == -1) { if (!e->name.empty()) os << e->name << " "; else os << "INVALID" << " "; } // group ID no longer used os << e->x << " " << e->y << " " << e->rot << " " << 0 << " " << e->id << " "; } entitiesNode.SetAttribute("j", os.str()); saveFile.InsertEndChild(entitiesNode); } for (i = 0; i < LR_MAX; i++) { std::string s = simpleElements[i].str(); if (!s.empty()) { TiXmlElement simpleElementsXML("SE"); simpleElementsXML.SetAttribute("k", s.c_str()); simpleElementsXML.SetAttribute("l", i); saveFile.InsertEndChild(simpleElementsXML); } } // HACK: fix this later (won't save light shafts) /* for (Core::RenderObjects::iterator i = core->renderObjects.begin(); i != core->renderObjects.end(); i++) { LightShaft *l = dynamic_cast(*i); if (l) { TiXmlElement lightShaft("LightShaft"); lightShaft.SetAttribute("x", l->position.x); lightShaft.SetAttribute("y", l->position.y); std::ostringstream os; os << l->getDir().x; lightShaft.SetAttribute("dirx", os.str()); std::ostringstream os2; os2 << l->getDir().y; lightShaft.SetAttribute("diry", os2.str()); std::ostringstream os3; os3 << l->shaftWidth; lightShaft.SetAttribute("w", os3.str()); //lightShaft.SetAttribute("dirx", int(l->getDir().x*1000)); //lightShaft.SetAttribute("diry", int(l->getDir().y*1000)); saveFile.InsertEndChild(lightShaft); } } */ bool result = saveFile.SaveFile(fn); if (result) debugLog("Successfully saved map: " + fn); else debugLog("Failed to save map: " + fn); return result; } void Game::warpToArea(WarpArea *area) { if (this->miniMapHint.scene == area->sceneName && this->miniMapHint.warpAreaType == area->warpAreaType) { miniMapHint.clear(); } //positionToAvatar = area->avatarPosition; dsq->game->warpAreaType = area->warpAreaType; dsq->game->spawnOffset = area->spawnOffset; //dsq->game->warpAreaSide = area->; dsq->game->transitionToScene(area->sceneName); } void Game::createGradient() { if (grad) { grad->safeKill(); grad = 0; } if (!grad) { grad = new Gradient; { //grad->makeVertical(Vector(0.6, 0.75, 0.65), Vector(0.4, 0.6, 0.5)); //grad->makeVertical(Vector(0.6, 0.8, 0.65), Vector(0.1, 0.2, 0.4)); grad->makeVertical(gradTop, gradBtm); grad->autoWidth = AUTO_VIRTUALWIDTH; grad->autoHeight = AUTO_VIRTUALHEIGHT; //grad->scale = Vector(core->getVirtualWidth(), core->getVirtualHeight()); grad->position = Vector(400,300,-4); grad->followCamera = 1; grad->alpha = 1; grad->toggleCull(false); } addRenderObject(grad, LR_BACKDROP); if (bg) bg->blendEnabled = true; if (bg2) bg2->blendEnabled = true; } } bool Game::isInGameMenu() { return inGameMenu; } bool Game::isValidTarget(Entity *e, Entity *me) { //(e->layer == LR_ENTITIES0 || e->layer == LR_ENTITIES || e->layer == LR_ENTITIES2) //&& true return (e != me && e->isNormalLayer() && e->isPresent() && e->getEntityType() == ET_ENEMY && e->isAvatarAttackTarget()); } void Game::updateMiniMapHintPosition() { miniMapHintPosition = Vector(0,0,0); for (int i = 0; i < warpAreas.size(); i++) { if (this->sceneName == miniMapHint.scene) { if (warpAreas[i].warpAreaType == miniMapHint.warpAreaType) { miniMapHintPosition = warpAreas[i].position; } } else { if (warpAreas[i].sceneName == miniMapHint.scene) { miniMapHintPosition = warpAreas[i].position; } } } } void Game::createPets() { setActivePet(dsq->continuity.getFlag(FLAG_PET_ACTIVE)); } Entity* Game::setActivePet(int flag) { if (currentPet) { currentPet->safeKill(); currentPet = 0; } dsq->continuity.setFlag(FLAG_PET_ACTIVE, flag); if (flag != 0) { int petv = flag - FLAG_PET_NAMESTART; PetData *p = dsq->continuity.getPetData(petv); if (p) { std::string name = p->namePart; Entity *e = createEntity("Pet_" + name, -1, avatar->position, 0, false, ""); if (e) { currentPet = e; e->setState(Entity::STATE_FOLLOW, -1, true); e->postInit(); } } } return currentPet; } void Game::createLi() { int liFlag = dsq->continuity.getFlag(FLAG_LI); std::ostringstream os; os << "liFlag: " << liFlag; debugLog(os.str()); if (liFlag == 100) { debugLog("Creating Li"); li = createEntity("Li", 0, Vector(0,0), 0, false, ""); //li->skeletalSprite.animate("idle"); } } void Game::colorTest() { // test element coloring // possibly useful for darker maps /* std::vector quadLights; quadLights.push_back(QuadLight(Vector(400, 300), Vector(1, 0, 0), 2000)); for (int i = 0; i < dsq->getNumElements(); i++) { Element *e = dsq->getElement(i); //e->color = Vector(rand()%100, rand()%100, rand()%100); for (int i = 0; i < quadLights.size(); i++) { QuadLight *q = &quadLights[i]; Vector dist = e->position - q->position; if (dist.isLength2DIn(q->dist)) { float fract = float(dist.getLength2D())/float(quadLights[i].dist); float amb = fract; fract = 1.0f - fract; e->color = Vector(1,1,1)*amb + q->color*fract; } else { e->color = Vector(1,1,0); } } //e->color.normalize2D(); } */ } void Game::showImage(const std::string &gfx) { if (!image) { //float t = lua_tonumber(L, 2); dsq->overlay->color = Vector(1,1,1); dsq->fade(1, 0.5); dsq->watch(0.5); image = new Quad; image->setTexture(gfx); image->position = Vector(400,300); image->setWidthHeight(800, 800); image->offset = Vector(0,100); image->alpha = 0; image->followCamera = 1; core->addRenderObject(image, LR_HUD); image->scale = Vector(1,1); image->scale.interpolateTo(Vector(1.1, 1.1), 12); image->alpha = 1; dsq->fade(0, 0.5); } } void Game::hideImage() { if (image) { image->setLife(1); image->setDecayRate(1.0f/2.0f); image->fadeAlphaWithLife = 1; } image = 0; dsq->overlay->color = 0; } void Game::switchBgLoop(int v) { if (v != lastBgSfxLoop) { if (dsq->loops.bg != BBGE_AUDIO_NOCHANNEL) { core->sound->fadeSfx(dsq->loops.bg, SFT_OUT, 0.5); dsq->loops.bg = BBGE_AUDIO_NOCHANNEL; } switch(v) { case 0: if (!bgSfxLoop.empty()) { PlaySfx sfx; sfx.name = bgSfxLoop; sfx.vol = bgSfxVol; sfx.loops = -1; sfx.priority = 0.8; dsq->loops.bg = core->sound->playSfx(sfx); } break; case 1: if (!airSfxLoop.empty()) { PlaySfx sfx; sfx.name = airSfxLoop; sfx.vol = bgSfxVol; sfx.loops = -1; sfx.priority = 0.8; dsq->loops.bg = core->sound->playSfx(sfx); } break; } lastBgSfxLoop = v; } } void Game::entityDied(Entity *eDead) { Entity *e = 0; FOR_ENTITIES(i) { e = *i; if (e != eDead && e->isv(EV_ENTITYDIED,1)) { e->entityDied(eDead); } } dsq->continuity.entityDied(eDead); } void Game::postInitEntities() { FOR_ENTITIES(i) { Entity *e = *i; if (e) { e->postInit(); } } core->resetTimer(); } void Game::updateParticlePause() { if (this->isPaused()) { core->particlesPaused = 2; } else if (this->isWorldPaused()) { core->particlesPaused = 1; } else { core->particlesPaused = 0; } } int game_collideParticle(Vector pos) { bool aboveWaterLine = (pos.y <= dsq->game->waterLevel.x+20); bool inWaterBubble = false; if (!aboveWaterLine) { Path *p = dsq->game->getNearestPath(pos, PATH_WATERBUBBLE); if (p) { if (p->isCoordinateInside(pos)) { inWaterBubble = true; } } } if (!inWaterBubble && aboveWaterLine) { return 1; } TileVector t(pos); return dsq->game->isObstructed(t); } void game_wibbleParticle(Particle *p) { /* if (dsq->game->avatar->getNotesOpen() > 0 && (p->position - dsq->game->avatar->position).isLength2DIn(256)) { if (!p->offset.isInterpolating()) { p->offset.interpolateTo(Vector(10,0), (8-dsq->game->avatar->getLastNote())/10.0f, -1, 1); //if (dsq->game->avatar->isSinging()) //{ // p->influenceVariable = 1; // p->color.interpolateTo(dsq->getNoteColor(dsq->game->avatar->getLastNote()), 1.0); //} } else { } } else { p->offset.stop(); //if (p->influenceVariable) // p->color.interpolateTo(Vector(1,1,1), 1); } */ } void Game::rebuildElementUpdateList() { for (int i = LR_ELEMENTS1; i <= LR_ELEMENTS8; i++) dsq->getRenderObjectLayer(i)->update = false; elementUpdateList.clear(); for (int i = 0; i < dsq->getNumElements(); i++) //for (int i = LR_ELEMENTS1; i <= LR_ELEMENTS8; i++) { //RenderObjectLayer *rl = dsq->getRenderObjectLayer(i); Element *e = dsq->getElement(i); if (e && e->layer >= LR_ELEMENTS1 && e->layer <= LR_ELEMENTS8) { if (e->getElementEffectIndex() != -1) { elementUpdateList.push_back(e); } } } } void Game::setElementLayerFlags() { for (int i = LR_ELEMENTS1; i <= LR_ELEMENTS16; i++) { // FIXME: Background SchoolFish get added to ELEMENTS11, so // we can't optimize that layer. (Maybe create a new layer?) if (i == LR_ELEMENTS11) continue; dsq->getRenderObjectLayer(i)->setOptimizeStatic(!isSceneEditorActive() && dsq->user.video.displaylists); } } float Game::getTimer(float mod) { return timer*mod; } float Game::getHalf2WayTimer(float mod) { float t=timer; if (t > 0.5f) t = 1 - t; return timer*2*mod; } float Game::getHalfTimer(float mod) { return halfTimer*mod; } void Game::adjustFoodSlotCursor() { // using visible slots now, don't need this atm return; /* for (int i = 0; i < foodSlots.size(); i++) { if (foodSlots[i]->isCursorIn()) { if (!foodSlots[i]->getIngredient() || foodSlots[i]->getIngredient()->amount <= 0) { foodSlots[i]->setFocus(false); i--; while (i >= 0) { if (foodSlots[i]->getIngredient() && foodSlots[i]->getIngredient()->amount > 0) { //cursor->position = foodSlots[i]->getWorldPosition(); foodSlots[i]->setFocus(true); break; } i--; } if (i <= -1) { menu[5]->setFocus(true); //cursor->position = menu[5]->getWorldPosition(); } } break; } } */ } void Game::action(int id, int state) { for (int i = 0; i < paths.size(); i++) { if (paths[i]->catchActions) { if (!paths[i]->action(id, state)) break; } } if (id == ACTION_TOGGLEHELPSCREEN && !state) { onToggleHelpScreen(); //toggleHelpScreen(!inHelpScreen); } if (id == ACTION_ESC && !state) onPressEscape(); if (id == ACTION_PRIMARY && !state) onLeftMouseButton(); if (id == ACTION_TOGGLEWORLDMAP && !state) { if (foodMenu) { recipes->setFocus(true); recipeMenu.toggle(!recipeMenu.on, true); } else if (!core->isStateJumpPending()) { toggleWorldMap(); } } #ifdef AQUARIA_BUILD_SCENEEDITOR if (id == ACTION_TOGGLESCENEEDITOR && !state) toggleSceneEditor(); #endif if (dsq->isDeveloperKeys() || isSceneEditorActive()) { if (id == ACTION_TOGGLEGRID && !state) toggleGridRender(); } if (isInGameMenu()) { if (treasureMenu) { if (!state && !dsq->isNested()) { if (dsq->menuSelectDelay == 0) { if (id == ACTION_PREVPAGE) { dsq->menuSelectDelay = MENUSELECTDELAY; onPrevTreasurePage(); //menu[5]->setFocus(true); } if (id == ACTION_NEXTPAGE) { dsq->menuSelectDelay = MENUSELECTDELAY; onNextTreasurePage(); //menu[5]->setFocus(true); } } } } else if (foodMenu) { if (!state && !dsq->isNested()) { if (dsq->menuSelectDelay == 0) { if (id == ACTION_PREVPAGE) { dsq->menuSelectDelay = MENUSELECTDELAY; if (recipeMenu.on) recipeMenu.goPrevPage(); else onPrevFoodPage(); } if (id == ACTION_NEXTPAGE) { dsq->menuSelectDelay = MENUSELECTDELAY; if (recipeMenu.on) recipeMenu.goNextPage(); else onNextFoodPage(); } } if (id == ACTION_COOKFOOD) { if (!recipeMenu.on) onCook(); } if (id == ACTION_FOODLEFT) { if (recipeMenu.on) { } else { for (int i = 0; i < foodHolders.size(); i++) { if (!foodHolders[i]->isTrash() && !foodHolders[i]->isEmpty()) { foodHolders[i]->dropFood(); break; } } } } if (id == ACTION_FOODRIGHT) { if (recipeMenu.on) { } else { for (int i = 0; i < foodSlots.size(); i++) { if (foodSlots[i]->isCursorIn() && foodSlots[i]->getIngredient()) { foodSlots[i]->moveRight(); adjustFoodSlotCursor(); break; } } } } if (id == ACTION_FOODDROP) { if (recipeMenu.on) { } else { int trashIndex = -1; for (int i = 0; i < foodHolders.size(); i++) { if (foodHolders[i]->alpha.x > 0 && foodHolders[i]->alphaMod > 0 && foodHolders[i]->isTrash()) { trashIndex = i; break; } } if (trashIndex >= 0) { int ingrIndex = -1; for (int i = 0; i < foodSlots.size(); i++) { if (foodSlots[i]->isCursorIn() && foodSlots[i]->getIngredient()) { ingrIndex = i; break; } } if (ingrIndex >= 0) { foodSlots[ingrIndex]->discard(); adjustFoodSlotCursor(); } } } } } } } } void Game::toggleWorldMap() { if (worldMapRender) { worldMapRender->toggle(!worldMapRender->isOn()); } } void Game::applyState() { bool verbose = true; applyingState = true; helpText = 0; helpUp = helpDown = 0; inHelpScreen = false; helpBG = 0; helpBG2 = 0; dsq->returnToScene = ""; // new place where mods get stopped! // this lets recaching work // (presumably because there has been time for the garbage to be cleared) if (sceneToLoad == "title" && dsq->mod.isShuttingDown()) { if (dsq->mod.isActive()) { dsq->mod.stop(); dsq->continuity.reset(); } } dsq->collectScriptGarbage(); isCooking = false; enqueuedPreviewRecipe = 0; dsq->toggleBlackBars(false); dsq->setTexturePointers(); moveFoodSlotToFront = 0; cameraOffBounds = false; ingOffY = 0; ingOffYTimer = 0; AquariaGuiElement::canDirMoveGlobal = true; cookDelay = 0; dsq->toggleVersionLabel(false); activation = true; active = true; hasPlayedLow = false; firstSchoolFish = true; invincibleOnNested = true; controlHintNotes.clear(); worldMapIndex = -1; particleManager->setNumSuckPositions(10); dropIngrNames.clear(); foodMenu = optionsMenu = petMenu = treasureMenu = false; currentPet = 0; bgSfxLoopPlaying2 = ""; lastBgSfxLoop = -1; saveMusic = ""; timer = 0; halfTimer = 0; cameraFollowObject = 0; cameraFollowEntity = 0; shuttingDownGameState = false; core->particlesPaused = false; bNatural = false; songLineRender = 0; image = 0; core->particleManager->collideFunction = game_collideParticle; core->particleManager->specialFunction = game_wibbleParticle; controlHint_ignoreClear = false; inGameMenuExitState = 0; int i = 0; debugLog("Entering Game::applyState"); dsq->overlay->alpha = 1; dsq->overlay->color = 0; for (i = LR_ELEMENTS1; i <= LR_ELEMENTS12; i++) // LR_ELEMENTS13 is darkness, stop before that { dsq->game->setElementLayerVisible(i-LR_ELEMENTS1, true); } dsq->applyParallaxUserSettings(); controlHintTimer = 0; cameraConstrained = true; // reset parallax RenderObjectLayer *l = 0; for (i = LR_ELEMENTS10; i <= LR_ELEMENTS16; i++) { l = &dsq->renderObjectLayers[i]; l->followCamera = 0; l->followCameraLock = 0; } cameraLerpDelay = 0; playingSongInMenu = -1; sceneColor2 = Vector(1,1,1); sceneColor3 = Vector(1,1,1); if (core->afterEffectManager) { core->afterEffectManager->clear(); //core->afterEffectManager->addEffect(new RippleEffect()); } Shot::shots.clear(); // the shots were deleted elsewhere, drop any remaining pointers Shot::deleteShots.clear(); backdropQuad = 0; clearObsRows(); inGameMenu = false; sceneFlipped = false; useWaterLevel = false; waterLevel = saveWaterLevel = 0; //miniMapHintPosition = Vector(8900, 14520); currentInventoryPage = 0; dsq->getRenderObjectLayer(LR_BLACKGROUND)->update = false; //dsq->getRenderObjectLayer(LR_ELEMENTS5)->update = false; backgroundImageRepeat = 1; grad = 0; maxZoom = -1; saveFile = 0; deathTimer = 0.9; runGameOverScript = false; paused = false; //sceneColor = Vector(0.75, 0.75, 0.8); sceneColor = Vector(1,1,1); sceneName = ""; elementTemplatePack =""; clearGrid(); clearPointers(); SkeletalSprite::clearCache(); StateObject::applyState(); //core->enable2D(800); dsq->clearEntities(); dsq->clearElements(); elementWithMenu = 0; //dsq->gui.menu.clearEntries(); progressBar = 0; /* progressBar = new AquariaProgressBar(); { progressBar->position = Vector(400,300); } addRenderObject(progressBar, LR_PROGRESS); */ damageSprite = new Quad; { damageSprite->setTexture("damage"); damageSprite->alpha = 0; damageSprite->autoWidth = AUTO_VIRTUALWIDTH; damageSprite->autoHeight = AUTO_VIRTUALHEIGHT; damageSprite->position = Vector(400,300); damageSprite->followCamera = true; damageSprite->scale.interpolateTo(Vector(1.1, 1.1), 0.75, -1, 1, 1); } addRenderObject(damageSprite, LR_DAMAGESPRITE); bg2 = new Quad; { bg2->position = Vector(400, 300, -3/*-0.09f*/); //bg2->color = Vector(0.9, 0.9, 0.9); bg2->setTexture("missingImage"); bg2->setWidthHeight(900,600); //bg2->blendEnabled = false; bg2->followCamera =1; bg2->alpha = 0.8; } addRenderObject(bg2, LR_BACKGROUND); bg = new Quad; { bg->blendEnabled = false; bg->position = Vector(400, 300, -2/*-0.09f*/); //bg->color = Vector(0.9, 0.9, 0.9); bg->setTexture("missingImage"); bg->setWidthHeight(900,600); //bg->blendEnabled = true; bg->followCamera =1; bg->alpha = 1; } addRenderObject(bg, LR_BACKGROUND); Vector mousePos(400,490); controlHint_bg = new Quad; { controlHint_bg->followCamera = 1; controlHint_bg->position = Vector(400,500); controlHint_bg->color = 0; controlHint_bg->alphaMod = 0.7; //controlHint_bg->setTexture("HintBox"); controlHint_bg->setWidthHeight(core->getVirtualWidth(), 100); controlHint_bg->autoWidth = AUTO_VIRTUALWIDTH; controlHint_bg->alpha = 0; } addRenderObject(controlHint_bg, LR_HELP); controlHint_text = new BitmapText(&dsq->smallFont); { controlHint_text->alpha = 0; controlHint_text->setWidth(700); controlHint_text->setAlign(ALIGN_LEFT); controlHint_text->followCamera = 1; controlHint_text->scale = Vector(0.9, 0.9); //controlHint_text->setFontSize(14); } addRenderObject(controlHint_text, LR_HELP); controlHint_image = new Quad; { controlHint_image->followCamera = 1; controlHint_image->position = mousePos; controlHint_image->alpha = 0; } addRenderObject(controlHint_image, LR_HELP); controlHint_mouseLeft = new Quad; { controlHint_mouseLeft->followCamera = 1; controlHint_mouseLeft->setTexture("Mouse-LeftButton"); controlHint_mouseLeft->position = mousePos; controlHint_mouseLeft->alpha = 0; } addRenderObject(controlHint_mouseLeft, LR_HELP); controlHint_mouseRight = new Quad; { controlHint_mouseRight->followCamera = 1; controlHint_mouseRight->setTexture("Mouse-RightButton"); controlHint_mouseRight->position = mousePos; controlHint_mouseRight->alpha = 0; } addRenderObject(controlHint_mouseRight, LR_HELP); controlHint_mouseMiddle = new Quad; { controlHint_mouseMiddle->followCamera = 1; controlHint_mouseMiddle->setTexture("Mouse-MiddleButton"); controlHint_mouseMiddle->position = mousePos; controlHint_mouseMiddle->alpha = 0; } addRenderObject(controlHint_mouseMiddle, LR_HELP); controlHint_mouseBody = new Quad; { controlHint_mouseBody->followCamera = 1; controlHint_mouseBody->setTexture("Mouse-Body"); controlHint_mouseBody->position = mousePos; controlHint_mouseBody->alpha = 0; } addRenderObject(controlHint_mouseBody, LR_HELP); controlHint_shine = new Quad; { //controlHint_shine->setTexture("spiralglow"); controlHint_shine->color = Vector(1,1,1); controlHint_shine->followCamera = 1; controlHint_shine->position = Vector(400,500); controlHint_shine->alphaMod = 0.3; controlHint_shine->setWidthHeight(core->getVirtualWidth(), 100); controlHint_shine->alpha = 0; controlHint_shine->setBlendType(RenderObject::BLEND_ADD); } addRenderObject(controlHint_shine, LR_HELP); li = 0; #ifdef AQUARIA_BUILD_SCENEEDITOR if (dsq->canOpenEditor()) { sceneEditor.init(); } #endif /* if (liFlag == 100) */ if (verbose) debugLog("Creating Avatar"); avatar = new Avatar(); if (verbose) debugLog("Done new Avatar"); if (warpAreaType.empty()) { if (positionToAvatar.x == 0 && positionToAvatar.y == 0) avatar->position = Vector(dsq->avStart.x,dsq->avStart.y); else avatar->position = positionToAvatar; positionToAvatar = Vector(0,0); } if (verbose) debugLog("Done warp"); if (verbose) debugLog("Create Li"); createLi(); if (verbose) debugLog("Done"); if (toFlip == 1) { dsq->game->avatar->flipHorizontal(); toFlip = -1; } // li //if (true) if (verbose) debugLog("WarpKeys"); if (verbose) debugLog("Done WarpKeys"); bindInput(); shapeDebug = 0; /* shapeDebug = new Quad; shapeDebug->setWidthHeight(80, 80); shapeDebug->color = Vector(1,1,0); addRenderObject(shapeDebug, LR_ENTITIES); */ if (verbose) debugLog("Loading Scene"); if (!loadScene(sceneToLoad)) { loadElementTemplates(elementTemplatePack); } if (verbose) debugLog("...Done"); backupSceneColor = sceneColor; dsq->continuity.worldMap.revealMap(sceneName); colorTest(); if (!warpAreaType.empty()) { for (int i = 0; i < warpAreas.size(); i++) { WarpArea *a = &warpAreas[i]; if (a->warpAreaType == warpAreaType) { int extra=96; if (a->radius) avatar->position = a->position + (spawnOffset*(a->radius+extra)); else { Vector s(spawnOffset.x*(a->w+extra), spawnOffset.y*(a->h+extra)); avatar->position = a->position + s; } break; } } warpAreaType = ""; } if (verbose) debugLog("Adding Avatar"); addRenderObject(avatar, LR_ENTITIES); //cameraFollow = &avatar->position; setCameraFollowEntity(avatar); if (verbose) debugLog("...Done"); currentRender = new CurrentRender(); addRenderObject(currentRender, LR_ELEMENTS3); steamRender = new SteamRender(); addRenderObject(steamRender, LR_ELEMENTS9); songLineRender = new SongLineRender(); addRenderObject(songLineRender, LR_HUD); gridRender = new GridRender(OT_INVISIBLE); addRenderObject(gridRender, LR_DEBUG_TEXT); gridRender->alpha = 0; gridRender2 = new GridRender(OT_HURT); addRenderObject(gridRender2, LR_DEBUG_TEXT); gridRender2->alpha = 0; gridRender3 = new GridRender(OT_INVISIBLEIN); addRenderObject(gridRender3, LR_DEBUG_TEXT); gridRender3->alpha = 0; edgeRender = new GridRender(OT_BLACKINVIS); addRenderObject(edgeRender, LR_DEBUG_TEXT); edgeRender->alpha = 0; gridRenderEnt = new GridRender(OT_INVISIBLEENT); addRenderObject(gridRenderEnt, LR_DEBUG_TEXT); gridRenderEnt->alpha = 0; waterSurfaceRender = new WaterSurfaceRender(); //waterSurfaceRender->setRenderPass(-1); addRenderObject(waterSurfaceRender, LR_WATERSURFACE); GridRender *blackRender = new GridRender(OT_BLACK); //blackRender->alpha = 0; blackRender->blendEnabled = false; addRenderObject(blackRender, LR_ELEMENTS4); hudUnderlay = new Quad; hudUnderlay->color = 0; hudUnderlay->position = Vector(400,300); //hudUnderlay->scale = Vector(800, 600); hudUnderlay->autoWidth = AUTO_VIRTUALWIDTH; hudUnderlay->autoHeight = AUTO_VIRTUALHEIGHT; hudUnderlay->alpha = 0; hudUnderlay->followCamera = 1; addRenderObject(hudUnderlay, LR_HUDUNDERLAY); autoMap = 0; /* autoMap = new AutoMap; addRenderObject(autoMap, LR_MESSAGEBOX); */ miniMapRender = 0; //miniMapRender->position = Vector(400,300); miniMapRender = new MiniMapRender; //miniMapRender->position = Vector(740,540); // position = (vw,vh) - (scale*100) // set in minimaprender::onupdate miniMapRender->scale = Vector(0.55, 0.55); /* miniMapRender->position = Vector(750,550); miniMapRender->scale = Vector(0.5, 0.5); */ //miniMapRender->scale = Vector(8,8); addRenderObject(miniMapRender, LR_MINIMAP); timerText = new BitmapText(&dsq->smallFont); timerText->position = Vector(745, 550); timerText->alpha = 0; timerText->followCamera = 1; addRenderObject(timerText, LR_MINIMAP); worldMapRender = 0; if(dsq->mod.isActive() && dsq->mod.mapRevealMethod != REVEAL_UNSPECIFIED) WorldMapRender::setRevealMethod(dsq->mod.mapRevealMethod); else WorldMapRender::setRevealMethod((WorldMapRevealMethod)dsq->user.video.worldMapRevealMethod); worldMapRender = new WorldMapRender; addRenderObject(worldMapRender, LR_WORLDMAP); // to hide minimap //miniMapRender->position += Vector(800,0); sceneToLoad=""; if (!fromScene.empty()) { stringToLower(fromScene); debugLog("fromScene: " + fromScene + " fromWarpType: " + fromWarpType); float smallestDist = HUGE_VALF; Path *closest = 0; Vector closestPushOut; bool doFlip = false; for (int i = 0; i < dsq->game->getNumPaths(); i++) { Path *p = dsq->game->getPath(i); Vector pos = p->nodes[0].position; if (p && (nocasecmp(p->warpMap, fromScene)==0)) { float dist = -1; bool go = false; Vector pushOut; switch(fromWarpType) { case CHAR_RIGHT: go = (p->warpType == CHAR_LEFT); pushOut = Vector(1,0); dist = fabsf(fromPosition.y - pos.y); doFlip = true; break; case CHAR_LEFT: go = (p->warpType == CHAR_RIGHT); pushOut = Vector(-1,0); dist = fabsf(fromPosition.y - pos.y); break; case CHAR_UP: go = (p->warpType == CHAR_DOWN); pushOut = Vector(0, -1); dist = fabsf(fromPosition.x - pos.x); break; case CHAR_DOWN: go = (p->warpType == CHAR_UP); pushOut = Vector(0, 1); dist = fabsf(fromPosition.x - pos.x); break; } if (go) { if (dist == -1) { debugLog(p->warpMap + ": warpType is wonky"); } else if (dist < smallestDist) { smallestDist = dist; closest = p; closestPushOut = pushOut; } } } } if (closest) { debugLog("warping avatar to node: " + closest->name); // this value of 8 is just nothing really // it short work with default value 1 // just gives the player some room to move without heading straight back // into the warp // LOL to the above!!! :DDDDD avatar->position = closest->getEnterPosition(50); if (doFlip) avatar->flipHorizontal(); /* avatar->position = closest->nodes[0].position; avatar->position += closestPushOut * 80; */ /* fromVel = Vector(0,1); avatar->rotateToVec(fromVel, 0.001); */ } else { debugLog("ERROR: Could not find a node to warp the player to!"); } fromScene = ""; } else if (!toNode.empty()) { Path *p = dsq->game->getPathByName(toNode); if (p) { avatar->position = p->nodes[0].position; } toNode = ""; } /* if (!fromVel.isZero()) { //avatar->vel = fromVel; avatar->rotateToVec(fromVel, 0.001); } */ avatar->setWasUnderWater(); if (!avatar->isUnderWater()) { avatar->setMaxSpeed(dsq->v.maxOutOfWaterSpeed); avatar->currentMaxSpeed = dsq->v.maxOutOfWaterSpeed; } if (avatar->position.isZero() || avatar->position == Vector(1,1)) { Path *p = 0; if ((p = getPathByName("NAIJASTART")) != 0 || (p = getPathByName("NAIJASTART L")) != 0) { avatar->position = p->nodes[0].position; } else if ((p = getPathByName("NAIJASTART R")) != 0) { avatar->position = p->nodes[0].position; avatar->flipHorizontal(); } } //positionLi if (li) { li->position = avatar->position + Vector(8,8); } toNode = ""; createInGameMenu(); hideInGameMenu(false); core->cacheRender(); core->cameraPos.stop(); cameraInterp.stop(); core->globalScale = dsq->continuity.zoom; avatar->myZoom = dsq->continuity.zoom; cameraInterp = getCameraPositionFor(avatar->position); core->cameraPos = getCameraPositionFor(avatar->position); core->sort(); if (dsq->mod.isActive()) dsq->runScript(dsq->mod.getPath() + "scripts/premap_" + sceneName + ".lua", "init", true); else dsq->runScript("scripts/maps/premap_"+sceneName+".lua", "init", true); std::string musicToPlay = this->musicToPlay; if (!overrideMusic.empty()) { musicToPlay = overrideMusic; } //INFO: this used to be here to start fading out the music // before the level had begun /* if (dsq->sound->isPlayingMusic()) { if (dsq->sound->currentMusic.find(musicToPlay) != std::string::npos) { } else { dsq->sound->fadeMusic(SFT_CROSS, 1); } } */ /* // HACK: to get the player on the map if there's an error with the warp coords while(dsq->game->collideCircleWithGrid(avatar->position, 32)) { if (avatar->position.y < 200) avatar->position.y += 200; avatar->position += Vector(40,0); avatar->clampPosition(); } */ updateMiniMapHintPosition(); createPets(); postInitEntities(); /* core->sound->musicVolume(1.0, 0.5); core->sound->sfxVolume(1.0, 0.5); */ bool musicchanged = updateMusic(); dsq->loops.bg = BBGE_AUDIO_NOCHANNEL; if (!bgSfxLoop.empty()) { core->sound->loadLocalSound(bgSfxLoop); } if (!airSfxLoop.empty()) { core->sound->loadLocalSound(airSfxLoop); } if (dsq->continuity.getWorldType() != WT_NORMAL) dsq->continuity.applyWorldEffects(dsq->continuity.getWorldType(), 0, musicchanged); if (verbose) debugLog("initAvatar"); dsq->continuity.initAvatar(avatar); if (verbose) debugLog("Done initAvatar"); if (verbose) debugLog("reset timer"); core->resetTimer(); if (verbose) debugLog("paths init"); int pathSz = getNumPaths(); for (i = 0; i < pathSz; i++) { getPath(i)->init(); } debugLog("Updating bgSfxLoop"); updateBgSfxLoop(); // Must be _before_ the init script, since some init scripts run // cutscenes immediately. --achurch dsq->subtitlePlayer.show(0.25); if (verbose) debugLog("loading map init script"); if (dsq->mod.isActive()) dsq->runScript(dsq->mod.getPath() + "scripts/map_" + sceneName + ".lua", "init", true); else dsq->runScript("scripts/maps/map_"+sceneName+".lua", "init", true); if (!dsq->doScreenTrans && (dsq->overlay->alpha != 0 && !dsq->overlay->alpha.isInterpolating())) { if (verbose) debugLog("fading in"); debugLog("FADEIN"); //dsq->overlay->alpha = 1; dsq->overlay->alpha.interpolateTo(0, 1); core->resetTimer(); avatar->disableInput(); core->main(0.5); avatar->enableInput(); core->resetTimer(); } if (dsq->doScreenTrans) { debugLog("SCREENTRANS!"); core->resetTimer(); dsq->toggleCursor(false, 0); dsq->doScreenTrans = false; dsq->transitionSaveSlots(); dsq->overlay->alpha = 0; dsq->main(0.5); dsq->toggleCursor(true); dsq->tfader->alpha.interpolateTo(0, 0.2); dsq->main(0.21); dsq->clearSaveSlots(false); } if (verbose) debugLog("reset timer"); applyingState = false; if (!dsq->doScreenTrans) { dsq->toggleCursor(true, 0.5); } dsq->forceInputGrabOff(); debugLog("Game::applyState Done"); } void Game::bindInput() { if (!(this->applyingState || this->isActive())) return; ActionMapper::clearActions(); //ActionMapper::clearCreatedEvents(); #ifdef AQUARIA_BUILD_SCENEEDITOR if (dsq->canOpenEditor()) { addAction(ACTION_TOGGLESCENEEDITOR, KEY_TAB); } #endif dsq->user.control.actionSet.importAction(this, "PrimaryAction", ACTION_PRIMARY); dsq->user.control.actionSet.importAction(this, "Escape", ACTION_ESC); dsq->user.control.actionSet.importAction(this, "WorldMap", ACTION_TOGGLEWORLDMAP); dsq->user.control.actionSet.importAction(this, "ToggleHelp", ACTION_TOGGLEHELPSCREEN); // used for scrolling help text dsq->user.control.actionSet.importAction(this, "SwimUp", ACTION_SWIMUP); dsq->user.control.actionSet.importAction(this, "SwimDown", ACTION_SWIMDOWN); /* dsq->user.control.actionSet.importAction(this, "SwimLeft", ACTION_SWIMLEFT); dsq->user.control.actionSet.importAction(this, "SwimRight", ACTION_SWIMRIGHT); */ dsq->user.control.actionSet.importAction(this, "PrevPage", ACTION_PREVPAGE); dsq->user.control.actionSet.importAction(this, "NextPage", ACTION_NEXTPAGE); dsq->user.control.actionSet.importAction(this, "CookFood", ACTION_COOKFOOD); dsq->user.control.actionSet.importAction(this, "FoodLeft", ACTION_FOODLEFT); dsq->user.control.actionSet.importAction(this, "FoodRight", ACTION_FOODRIGHT); dsq->user.control.actionSet.importAction(this, "FoodDrop", ACTION_FOODDROP); if (dsq->canOpenEditor()) { //addAction(MakeFunctionEvent(Game, toggleMiniMapRender), KEY_M, 0); addAction(ACTION_TOGGLEGRID, KEY_F9); } /* addAction(ACTION_MENULEFT, KEY_LEFT); addAction(ACTION_MENURIGHT, KEY_RIGHT); addAction(ACTION_MENUUP, KEY_UP); addAction(ACTION_MENUDOWN, KEY_DOWN); dsq->user.control.actionSet.importAction(this, "SwimLeft", ACTION_MENULEFT); dsq->user.control.actionSet.importAction(this, "SwimRight", ACTION_MENURIGHT); dsq->user.control.actionSet.importAction(this, "SwimUp", ACTION_MENUUP); dsq->user.control.actionSet.importAction(this, "SwimDown", ACTION_MENUDOWN); addAction(ACTION_MENULEFT, JOY1_DPAD_LEFT); addAction(ACTION_MENURIGHT, JOY1_DPAD_RIGHT); addAction(ACTION_MENUUP, JOY1_DPAD_UP); addAction(ACTION_MENUDOWN, JOY1_DPAD_DOWN); */ addAction(ACTION_MENULEFT, JOY1_STICK_LEFT); addAction(ACTION_MENURIGHT, JOY1_STICK_RIGHT); addAction(ACTION_MENUUP, JOY1_STICK_UP); addAction(ACTION_MENUDOWN, JOY1_STICK_DOWN); // To capture quick song keys via script dsq->user.control.actionSet.importAction(this, "SongSlot1", ACTION_SONGSLOT1); dsq->user.control.actionSet.importAction(this, "SongSlot2", ACTION_SONGSLOT2); dsq->user.control.actionSet.importAction(this, "SongSlot3", ACTION_SONGSLOT3); dsq->user.control.actionSet.importAction(this, "SongSlot4", ACTION_SONGSLOT4); dsq->user.control.actionSet.importAction(this, "SongSlot5", ACTION_SONGSLOT5); dsq->user.control.actionSet.importAction(this, "SongSlot6", ACTION_SONGSLOT6); dsq->user.control.actionSet.importAction(this, "SongSlot7", ACTION_SONGSLOT7); dsq->user.control.actionSet.importAction(this, "SongSlot8", ACTION_SONGSLOT8); dsq->user.control.actionSet.importAction(this, "SongSlot9", ACTION_SONGSLOT9); dsq->user.control.actionSet.importAction(this, "SongSlot10", ACTION_SONGSLOT10); dsq->user.control.actionSet.importAction(this, "Revert", ACTION_REVERT); if (avatar) avatar->bindInput(); if (worldMapRender) worldMapRender->bindInput(); } bool ingType(const std::vector &list, IngredientType type, int amount=1) { int c = 0; for (int i = 0; i < list.size(); i++) { IngredientData *data = list[i]; if ((data->marked < data->held) && (data->type == type || type == IT_ANYTHING)) { if (type != IT_ANYTHING) data->marked++; c++; if (c == amount) return true; } } return false; } bool ingName(const std::vector &list, const std::string &name, int amount=1) { int c = 0; for (int i = 0; i < list.size(); i++) { IngredientData *data = list[i]; if ((data->marked < data->held) && (nocasecmp(data->name, name)==0))//data->name == name) { data->marked++; c++; if (c == amount) return true; } } return false; } const int numTreasures = 16*2; void Game::onPrevTreasurePage() { if (currentTreasurePage > 0) { dsq->sound->playSfx("menu-switch", 0.5); dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1); currentTreasurePage--; refreshTreasureSlots(); } else { if (numTreasures > 0) { dsq->sound->playSfx("menu-switch", 0.5); dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1); currentTreasurePage = ((numTreasures-1)/treasurePageSize); refreshTreasureSlots(); } } } void Game::onNextTreasurePage() { if ((currentTreasurePage+1)*treasurePageSize < numTreasures) { dsq->sound->playSfx("menu-switch", 0.5); dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1); currentTreasurePage++; refreshTreasureSlots(); } else { if (currentTreasurePage != 0) { dsq->sound->playSfx("menu-switch", 0.5); dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1); currentTreasurePage = 0; refreshTreasureSlots(); } } } void Game::onPrevFoodPage() { int lastFoodPage = currentFoodPage; if (currentFoodPage > 0) { currentFoodPage--; refreshFoodSlots(false); } else { if (dsq->continuity.hasIngredients()) { currentFoodPage = ((dsq->continuity.ingredientCount()-1)/foodPageSize); refreshFoodSlots(false); } } std::ostringstream os; os << "food page: " << currentFoodPage; debugLog(os.str()); if (currentFoodPage != lastFoodPage) { dsq->sound->playSfx("menu-switch", 0.5); dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1); } } void Game::onNextFoodPage() { int lastFoodPage = currentFoodPage; if ((currentFoodPage+1)*foodPageSize < dsq->continuity.ingredientCount()) { currentFoodPage++; refreshFoodSlots(false); } else { if (currentFoodPage != 0) { currentFoodPage = 0; refreshFoodSlots(false); } } if (currentFoodPage != lastFoodPage) { dsq->sound->playSfx("menu-switch", 0.5); dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1); } } void Game::onUseTreasure() { debugLog("Use Treasure!"); if (selectedTreasureFlag != -1) { onUseTreasure(selectedTreasureFlag); } } void Game::onUseTreasure(int flag) { if(dsq->mod.isActive()) dsq->runScriptNum(dsq->mod.getPath() + "scripts/menu-treasures.lua", "useTreasure", flag); else dsq->runScriptNum("scripts/global/menu-treasures.lua", "useTreasure", flag); } Recipe *Game::findRecipe(const std::vector &list) { if (list.size() < 2) return 0; // there will be a number of types and a number of names // the types and names DO NOT overlap int rc = 0; Recipe *r = 0; Recipe *tr = 0; int q = 0, q2 = 0; for ( rc = 0; rc < dsq->continuity.recipes.size(); rc++) { for (int i = 0; i < list.size(); i++) list[i]->marked = 0; tr = 0; r = &dsq->continuity.recipes[rc]; tr = r; q = 0; // get the amount of ingredients provided by the player int listAmount = list.size(); // get the amount of ingredients required int recipeAmount = 0; for (int i = 0; i < r->types.size(); i++) recipeAmount += r->types[i].amount; for (int i = 0; i < r->names.size(); i++) recipeAmount += r->names[i].amount; if (listAmount != recipeAmount) continue; for (int c = 0; c < r->types.size(); c++) { RecipeType *t = &r->types[c]; if (ingType(list, t->type, t->amount)) q++; else break; } /* // if all the types are checked // AND there are no names to check // then you found it! if (q == r->types.size() && q > 0 && r->names.empty()) { return tr; } */ // this check is _kinda_ unnecessary... but we'll see if (q == r->types.size()) { q2 = 0; for (int c = 0; c < r->names.size(); c++) { RecipeName *n = &r->names[c]; if (ingName(list, n->name, n->amount)) q2++; else break; } if (q2 == r->names.size()) { return r; } /* // if there were actually types to check // and they were checked successfully // (being in this section of code implies that there were no types OR there was a successful full check) else if (q>0 && tr) { // return the ingredient we found in types // but this is kind of silly. // would make more sense to return earlier return tr; } */ } } for (int i = 0; i < list.size(); i++) list[i]->marked = 0; if (rc == dsq->continuity.recipes.size()) { /* data = dsq->continuity.getIngredientByName("SeaLoaf"); if (data) { dsq->continuity.pickupIngredient(data); } */ } return 0; } void Game::updateCookList() { cookList.clear(); for (int i = 0; i < foodHolders.size(); i++) { IngredientData *ing = foodHolders[i]->getIngredient(); if (!foodHolders[i]->isTrash() && ing) { std::ostringstream os; os << "cooklist: " << ing->name; debugLog(os.str()); cookList.push_back(ing); } } } void Game::onRecipes() { if (foodMenu) { toggleRecipeList(!recipeMenu.on); } } void Game::onKeyConfig() { dsq->screenTransition->capture(); toggleKeyConfigMenu(true); dsq->screenTransition->transition(MENUPAGETRANSTIME); } #define DEBUG_COOK void Game::onCook() { if (recipeMenu.on) return; if (cookDelay > 0) return; debugLog("Cook!"); //std::vector list; updateCookList(); if (cookList.size() < 2 || recipeMenu.on) return; AquariaGuiElement::canDirMoveGlobal = false; cookDelay = 0.4; bool cooked = false; isCooking = true; IngredientData *data=0; Recipe *r = findRecipe(cookList); if (r) data = dsq->continuity.getIngredientDataByName(r->result); else { dsq->sound->playSfx("Denied"); data = dsq->continuity.getIngredientDataByName("SeaLoaf"); bool tooMany = data && dsq->continuity.isIngredientFull(data); if (!tooMany) { int f = dsq->continuity.getFlag(FLAG_SEALOAFANNOYANCE); f++; if (f >= 3) { dsq->voiceInterupt("naija_sealoaf"); f = 0; } dsq->continuity.setFlag(FLAG_SEALOAFANNOYANCE, f); } } if (data) { cooked = !dsq->continuity.isIngredientFull(data); } if (cooked) { debugLog("Cooked something!"); // do animationy stuff. core->mouse.buttonsEnabled = false; bool longAnim = true; int cooks = dsq->continuity.getFlag(FLAG_COOKS); if (cooks >= 4) longAnim = false; for (int i = foodHolders.size()-1; i >= 0; i--) if (foodHolders[i]->alpha.x > 0 && !foodHolders[i]->isEmpty() && !foodHolders[i]->isTrash()) foodHolders[i]->animateLid(true, longAnim); //dsq->main(0.2); if (longAnim) { float ft = 0.8; float nt = 0.1; float nt2 = 0.2; void *handle = NULL; /* if (!longAnim) { float factor = 0.3; ft *= factor; nt *= factor; nt2 *= factor; } */ PlaySfx note1; note1.name = getNoteName(0); PlaySfx note2; note2.name = getNoteName(4); PlaySfx note3; note3.name = getNoteName(3); handle = dsq->sound->playSfx(note1); dsq->main(nt2); dsq->sound->fadeSfx(handle, SFT_OUT, ft); dsq->main(nt); handle = dsq->sound->playSfx(note2); dsq->main(nt2); dsq->sound->fadeSfx(handle, SFT_OUT, ft); dsq->main(nt); handle = dsq->sound->playSfx(note3); dsq->main(nt2); dsq->sound->fadeSfx(handle, SFT_OUT, ft); dsq->main(nt); } dsq->sound->playSfx("boil"); for (int i = 0; i < foodHolders.size(); i++) { if (!foodHolders[i]->isEmpty()) dsq->spawnParticleEffect("cook-ingredient", foodHolders[i]->getWorldPosition(), 0, 0, LR_HUD3, 1); } if (longAnim) dsq->main(0.5); else dsq->main(0.2); bool haveLeftovers = true; for (int i = 0; i < foodHolders.size(); i++) { if (!foodHolders[i]->isEmpty()) { IngredientData *ing = foodHolders[i]->getIngredient(); if (!ing || ing->amount < ing->held) { haveLeftovers = false; break; } } } for (int i = 0; i < foodHolders.size(); i++) { IngredientData *ing = foodHolders[i]->getIngredient(); if (ing) { ing->amount--; } if (!haveLeftovers) { foodHolders[i]->setIngredient(0, false); } } dsq->sound->playSfx("Cook"); for (int i = 0; i < foodHolders.size(); i++) if (foodHolders[i]->alpha.x > 0 && !foodHolders[i]->isTrash()) foodHolders[i]->animateLid(false); dsq->spawnParticleEffect("cook-food", Vector(575,250), 0, 0, LR_HUD3, 1); if (longAnim) dsq->main(0.5); else dsq->main(0.2); if (data) { float t = 3; std::string n = "Ingredients/" + data->gfx; //Quad *e = new Quad(); showRecipe->setTexture(n); showRecipe->scale = Vector(0.5, 0.5); showRecipe->scale.interpolateTo(Vector(1.2, 1.2), t); showRecipe->alpha.ensureData(); showRecipe->alpha.data->path.clear(); showRecipe->alpha.data->path.addPathNode(0, 0); showRecipe->alpha.data->path.addPathNode(1, 0.1); showRecipe->alpha.data->path.addPathNode(1, 0.6); showRecipe->alpha.data->path.addPathNode(0, 1); showRecipe->alpha.startPath(t); } dsq->continuity.pickupIngredient(data, 1); dsq->continuity.removeEmptyIngredients(); dsq->main(0.5); dsq->continuity.setFlag(FLAG_COOKS, dsq->continuity.getFlag(FLAG_COOKS)+1); if (r) { dsq->continuity.learnRecipe(r); if (haveLeftovers) updatePreviewRecipe(); } core->mouse.buttonsEnabled = true; } else { dsq->sound->playSfx("Denied"); dsq->centerMessage(dsq->continuity.stringBank.get(27)); } refreshFoodSlots(true); AquariaGuiElement::canDirMoveGlobal = true; isCooking = false; } void Game::overrideZoom(float sz, float t) { if (sz == 0) { dsq->game->toggleOverrideZoom(false); } else { dsq->game->toggleOverrideZoom(true); dsq->globalScale.interpolateTo(Vector(sz, sz), t); } } FoodSlot* getFoodSlotFromIndex() { for (int i = 0; i < dsq->game->foodSlots.size(); i++) { if (dsq->game->foodSlots[i]->slot == FoodSlot::foodSlotIndex) { return dsq->game->foodSlots[i]; } } return 0; } void Game::onLips() { if (!foodMenu) { if (dsq->lastVoiceFile.find("NAIJA_SONG_") != std::string::npos) { dsq->stopVoice(); } } } const float hintTransTime = 0.5; void Game::clearControlHint() { if (!controlHint_ignoreClear) { controlHintTimer = 0; if (controlHint_bg) { controlHint_mouseLeft->alpha.interpolateTo(0, hintTransTime); controlHint_mouseRight->alpha.interpolateTo(0, hintTransTime); controlHint_mouseMiddle->alpha.interpolateTo(0, hintTransTime); controlHint_mouseBody->alpha.interpolateTo(0, hintTransTime); controlHint_text->alpha.interpolateTo(0, hintTransTime); controlHint_bg->alpha.interpolateTo(0, hintTransTime); controlHint_image->alpha.interpolateTo(0, hintTransTime); } for (int i = 0; i < controlHintNotes.size(); i++) { controlHintNotes[i]->alpha.interpolateTo(0, hintTransTime); } controlHintNotes.clear(); } } float Game::getWaterLevel() { return waterLevel.x; } void Game::setControlHint(const std::string &h, bool left, bool right, bool middle, float time, std::string image, bool ignoreClear, int songType, float scale) { if (!h.empty()) dsq->sound->playSfx("controlhint"); controlHint_ignoreClear = false; clearControlHint(); std::string hint = h; controlHintTimer = time; if (core->flipMouseButtons) { if (h.find("Left")!=std::string::npos && h.find("Right")==std::string::npos) { std::string sought = "Left"; std::string replacement = "Right"; hint.replace(hint.find(sought), sought.size(), replacement); } else if (h.find("Left")==std::string::npos && h.find("Right")!=std::string::npos) { std::string sought = "Right"; std::string replacement = "Left"; hint.replace(hint.find(sought), sought.size(), replacement); } std::swap(left, right); } std::ostringstream os; os << "set control hint: (" << hint << ", " << left << ", " << right << ", " << middle << " t: " << time << " )"; debugLog(os.str()); if (songType > 0) { //Song *song = getSongByIndex(num); Song *song = dsq->continuity.getSongByIndex(songType); controlHintNotes.clear(); Vector p = controlHint_mouseLeft->position + Vector(-100,0); char sbuf[32]; sprintf(sbuf, "song/songslot-%d", dsq->continuity.getSongSlotByType(songType)); Quad *q = new Quad(sbuf, p); q->followCamera = 1; q->scale = Vector(0.7, 0.7); q->alpha = 0; addRenderObject(q, controlHint_bg->layer); controlHintNotes.push_back(q); p += Vector(100, 0); for (int i = 0; i < song->notes.size(); i++) { int note = song->notes[i]; sprintf(sbuf, "song/notebutton-%d", note); Quad *q = new Quad(sbuf, p); q->color = dsq->getNoteColor(note)*0.5f + Vector(1, 1, 1)*0.5f; q->followCamera = 1; q->scale = Vector(1.0, 1.0); q->alpha = 0; if (i % 2) q->offset = Vector(0, -10); else q->offset = Vector(0, 10); addRenderObject(q, controlHint_bg->layer); controlHintNotes.push_back(q); p += Vector(40, 0); } } float alphaOn = 0.8, alphaOff = 0.5; controlHint_bg->alpha.interpolateTo(1, hintTransTime); controlHint_bg->scale = Vector(1,1); //controlHint_bg->scale = Vector(0,1); //controlHint_bg->scale.interpolateTo(Vector(1,1), hintTransTime); controlHint_text->setText(hint); controlHint_text->alpha.interpolateTo(1, hintTransTime); if (!image.empty()) { controlHint_image->setTexture(image); controlHint_image->alpha.interpolateTo(1, hintTransTime); controlHint_image->scale = Vector(scale, scale); //controlHint_image->scale = Vector(0.5, 0.5); } else { controlHint_image->alpha.interpolateTo(0, hintTransTime); } controlHint_text->position.x = 400 - controlHint_text->getSetWidth()/2 + 25; //400 - controlHint_bg->getWidth()/2 + 25; controlHint_text->setAlign(ALIGN_LEFT); if (!left && !right && !middle) { controlHint_mouseRight->alpha.interpolateTo(0, hintTransTime); controlHint_mouseLeft->alpha.interpolateTo(0, hintTransTime); controlHint_mouseMiddle->alpha.interpolateTo(0, hintTransTime); if (image.empty() && controlHintNotes.empty()) { controlHint_text->position.y = 470; } else { controlHint_text->position.y = 520; controlHint_text->position.x = 400; controlHint_text->setAlign(ALIGN_CENTER); } } else { controlHint_text->position.y = 520; controlHint_text->position.x = 400; controlHint_text->setAlign(ALIGN_CENTER); if (left) controlHint_mouseLeft->alpha.interpolateTo(alphaOn, hintTransTime); else controlHint_mouseLeft->alpha.interpolateTo(alphaOff, hintTransTime); if (right) controlHint_mouseRight->alpha.interpolateTo(alphaOn, hintTransTime); else controlHint_mouseRight->alpha.interpolateTo(alphaOff, hintTransTime); if (middle) controlHint_mouseMiddle->alpha.interpolateTo(alphaOn, hintTransTime); else controlHint_mouseMiddle->alpha.interpolateTo(alphaOff, hintTransTime); controlHint_mouseBody->alpha.interpolateTo(0.5, hintTransTime); } for (int i = 0; i < controlHintNotes.size(); i++) { controlHintNotes[i]->alpha.interpolateTo(alphaOn, hintTransTime); } controlHint_ignoreClear = ignoreClear; controlHint_shine->alpha.ensureData(); controlHint_shine->alpha.data->path.clear(); controlHint_shine->alpha.data->path.addPathNode(0.001, 0.0); controlHint_shine->alpha.data->path.addPathNode(1.000, 0.3); controlHint_shine->alpha.data->path.addPathNode(0.001, 1.0); controlHint_shine->alpha.startPath(0.4); } void Game::onFlipTest() { flipSceneVertical(14960); } void appendFileToString(std::string &string, const std::string &file) { InStream inf(file.c_str()); if (inf.is_open()) { while (!inf.eof()) { std::string read; std::getline(inf, read); #if BBGE_BUILD_UNIX read = stripEndlineForUnix(read); #endif read = dsq->user.control.actionSet.insertInputIntoString(read); string += read + "\n"; } } inf.close(); } void Game::onToggleHelpScreen() { if (inHelpScreen) toggleHelpScreen(false); else if (core->isStateJumpPending()) return; else { if (worldMapRender->isOn()) { toggleHelpScreen(true, "[World Map]"); } else if (currentMenuPage == MENUPAGE_FOOD) { toggleHelpScreen(true, "[Food]"); } else if (currentMenuPage == MENUPAGE_TREASURES) { toggleHelpScreen(true, "[Treasures]"); } /* else if (currentMenuPage == MENUPAGE_SONGS) { toggleHelpScreen(true, "[Singing]"); } */ else if (currentMenuPage == MENUPAGE_PETS) { toggleHelpScreen(true, "[Pets]"); } else { toggleHelpScreen(true); } } } void Game::toggleHelpScreen(bool on, const std::string &label) { if (dsq->game->isSceneEditorActive()) return; if (inHelpScreen == on) return; if (core->getShiftState()) return; if (dsq->screenTransition->isGoing()) return; if (dsq->isNested()) return; if (dsq->saveSlotMode != SSM_NONE) return; if (on) { AquariaGuiElement::currentGuiInputLevel = 100; dsq->screenTransition->capture(); helpWasPaused = isPaused(); togglePause(true); std::string data; // These say "Mac" but we use them on Linux, too. #if defined(BBGE_BUILD_UNIX) std::string fname = localisePath("data/help_header_mac.txt"); appendFileToString(data, fname); #else std::string fname = localisePath("data/help_header.txt"); appendFileToString(data, fname); #endif if (dsq->continuity.hasSong(SONG_BIND)) { fname = localisePath("data/help_bindsong.txt"); appendFileToString(data, fname); } if (dsq->continuity.hasSong(SONG_ENERGYFORM)) { fname = localisePath("data/help_energyform.txt"); appendFileToString(data, fname); } fname = localisePath("data/help_start.txt"); appendFileToString(data, fname); // These say "Mac" but we use them on Linux, too. #if defined(BBGE_BUILD_UNIX) fname = localisePath("data/help_end_mac.txt"); appendFileToString(data, fname); #else fname = localisePath("data/help_end.txt"); appendFileToString(data, fname); #endif // !!! FIXME: this is such a hack. data += "\n\n" + dsq->continuity.stringBank.get(2032) + "\n\n"; dsq->continuity.statsAndAchievements->appendStringData(data); helpBG = new Quad; //helpBG->color = 0; helpBG->setTexture("brick"); helpBG->repeatTextureToFill(true); helpBG->repeatToFillScale = Vector(2, 2); //helpBG->alphaMod = 0.75; helpBG->autoWidth = AUTO_VIRTUALWIDTH; helpBG->autoHeight = AUTO_VIRTUALHEIGHT; helpBG->position = Vector(400,300); helpBG->followCamera = 1; addRenderObject(helpBG, LR_HELP); helpBG2 = new Quad; helpBG2->color = 0; helpBG2->alphaMod = 0.5; helpBG2->setWidth(620); helpBG2->autoHeight = AUTO_VIRTUALHEIGHT; helpBG2->position = Vector(400,300); helpBG2->followCamera = 1; addRenderObject(helpBG2, LR_HELP); helpText = new TTFText(&dsq->fontArialSmall); //test->setAlign(ALIGN_CENTER); helpText->setWidth(600); helpText->setText(data); //test->setAlign(ALIGN_CENTER); helpText->cull = false; helpText->followCamera = 1; helpText->position = Vector(100, 20); if (!label.empty()) { int line = helpText->findLine(label); helpText->offset.interpolateTo(Vector(0, -helpText->getLineHeight()*line), -1200); } //helpText->offset.interpolateTo(Vector(0, -400), 4, -1, 1); //test->position = Vector(400,300); addRenderObject(helpText, LR_HELP); helpUp = new AquariaMenuItem; helpUp->useQuad("Gui/arrow-left"); helpUp->useSound("click"); helpUp->useGlow("particles/glow", 64, 32); helpUp->position = Vector(50, 40); helpUp->followCamera = 1; helpUp->rotation.z = 90; helpUp->event.set(MakeFunctionEvent(Game, onHelpUp)); helpUp->scale = Vector(0.6, 0.6); helpUp->guiInputLevel = 100; addRenderObject(helpUp, LR_HELP); helpDown = new AquariaMenuItem; helpDown->useQuad("Gui/arrow-right"); helpDown->useSound("click"); helpDown->useGlow("particles/glow", 64, 32); helpDown->position = Vector(50, 600-40); helpDown->followCamera = 1; helpDown->rotation.z = 90; helpDown->event.set(MakeFunctionEvent(Game, onHelpDown)); helpDown->scale = Vector(0.6, 0.6); helpDown->guiInputLevel = 100; addRenderObject(helpDown, LR_HELP); helpCancel = new AquariaMenuItem; helpCancel->useQuad("Gui/cancel"); helpCancel->useSound("click"); helpCancel->useGlow("particles/glow", 128, 40); helpCancel->position = Vector(750, 600-20); helpCancel->followCamera = 1; //helpCancel->rotation.z = 90; helpCancel->event.set(MakeFunctionEvent(Game, onToggleHelpScreen)); helpCancel->scale = Vector(0.9, 0.9); helpCancel->guiInputLevel = 100; addRenderObject(helpCancel, LR_HELP); for (int i = 0; i < LR_HELP; i++) { core->getRenderObjectLayer(i)->visible = false; } core->resetTimer(); dsq->screenTransition->transition(MENUPAGETRANSTIME); } else { if (!helpWasPaused) togglePause(false); dsq->screenTransition->capture(); if (helpText) { helpText->alpha = 0; helpText->setLife(1); helpText->setDecayRate(1000); helpText = 0; } if (helpBG) { helpBG->alpha = 0; helpBG->setLife(1); helpBG->setDecayRate(1000); helpBG = 0; } if (helpBG2) { helpBG2->alpha = 0; helpBG2->setLife(1); helpBG2->setDecayRate(1000); helpBG2 = 0; } if (helpUp) { helpUp->alpha = 0; helpUp->setLife(1); helpUp->setDecayRate(1000); helpUp = 0; } if (helpDown) { helpDown->alpha = 0; helpDown->setLife(1); helpDown->setDecayRate(1000); helpDown = 0; } if (helpCancel) { helpCancel->alpha = 0; helpCancel->setLife(1); helpCancel->setDecayRate(1000); helpCancel = 0; } for (int i = 0; i < LR_HELP; i++) { core->getRenderObjectLayer(i)->visible = true; } dsq->applyParallaxUserSettings(); dsq->screenTransition->transition(MENUPAGETRANSTIME); AquariaGuiElement::currentGuiInputLevel = 0; } inHelpScreen = on; } bool Game::updateMusic() { std::string musicToPlay = this->musicToPlay; if (!overrideMusic.empty()) { musicToPlay = overrideMusic; } if (!musicToPlay.empty()) { if (musicToPlay == "none") core->sound->fadeMusic(SFT_OUT, 1); else { bool play = true; /* std::string originalFile = musicToPlay; std::string file = originalFile; if (!exists(file, false) && file.find('.') == std::string::npos) { file = originalFile + ".ogg"; if (!exists(file, false)) { file = originalFile + ".mp3"; if (!exists(file, false)) { errorLog ("music file not found [" + originalFile + "]"); play = false; } } } */ if (play) { /* if (core->sound->isStreamingMusic()) core->sound->crossfadeOutMusic(1); */ return core->sound->playMusic(musicToPlay, SLT_LOOP, SFT_CROSS, 1, SCT_ISNOTPLAYING); } } } else { core->sound->fadeMusic(SFT_OUT, 1); } return false; } void Game::onPressEscape() { if (dsq->isInCutscene()) { // do nothing (moved to dsq:: } else { if (inHelpScreen) { toggleHelpScreen(false); return; } if (dsq->game->worldMapRender->isOn() && !dsq->isNested()) { dsq->game->worldMapRender->toggle(false); return; } if (dsq->game->isInGameMenu()) { if (!AquariaKeyConfig::waitingForInput) { if (dsq->game->menuOpenTimer > 0.5f) { if (optionsMenu || keyConfigMenu) onOptionsCancel(); else hideInGameMenu(); } } return; } if (!paused) { if (core->getNestedMains() == 1 && !core->isStateJumpPending()) showInGameMenu(); } else { if (autoMap) { if (paused && autoMap->isOn()) autoMap->toggle(false); } } if ((dsq->saveSlotMode != SSM_NONE || dsq->inModSelector) && core->isNested()) { dsq->selectedSaveSlot = 0; core->quitNestedMain(); } } } void Game::onDebugSave() { hideInGameMenu(); clearControlHint(); core->main(0.5); dsq->game->togglePause(true); dsq->doSaveSlotMenu(SSM_SAVE); dsq->game->togglePause(false); //dsq->continuity.saveFile(0); } void Game::onInGameMenuInventory() { } void Game::onInGameMenuSpellBook() { } void Game::onInGameMenuContinue() { hideInGameMenu(); } void Game::onInGameMenuOptions() { } void Game::onInGameMenuSave() { } void Game::onExitCheckYes() { dsq->sound->stopAllVoice(); dsq->toggleCursor(0, 0.25); dsq->title(); } void Game::onExitCheckNo() { hideInGameMenuExitCheck(true); } void Game::showInGameMenuExitCheck() { recipeMenu.toggle(false); inGameMenuExitState = 1; eYes->alpha.interpolateTo(1, 0.2); eNo->alpha.interpolateTo(1, 0.2); eAre->alpha.interpolateTo(1, 0.2); eNo->setFocus(true); } void Game::hideInGameMenuExitCheck(bool refocus) { inGameMenuExitState = 0; eYes->alpha.interpolateTo(0, 0.2); eNo->alpha.interpolateTo(0, 0.2); eAre->alpha.interpolateTo(0, 0.2); if (refocus) ((AquariaMenuItem*)menu[1])->setFocus(true); } void Game::onInGameMenuExit() { if (!dsq->user.demo.warpKeys || (core->getCtrlState() && core->getAltState())) { if (inGameMenuExitState == 0) { // show yes/no showInGameMenuExitCheck(); } } } void Game::toggleDamageSprite(bool on) { if (on) { damageSprite->alphaMod = 1; } else damageSprite->alphaMod = 0; } void Game::togglePause(bool v) { paused = v; if (paused) { dsq->cursorGlow->alpha = 0; dsq->cursorBlinker->alpha = 0; //dsq->overlay->alpha.interpolateTo(0.5, 0.5); } //core->particlesPaused = v; /* else dsq->overlay->alpha.interpolateTo(0, 0.5); */ } bool Game::isPaused() { return paused; } void Game::playBurstSound(bool wallJump) { int freqBase = 950; if (wallJump) freqBase += 100; sound->playSfx("Burst", 1, 0);//, (freqBase+rand()%25)/1000.0f); if (chance(50)) { switch (dsq->continuity.form) { case FORM_BEAST: sound->playSfx("BeastBurst", (128+rand()%64)/256.0f, 0);//, (freqBase+rand()%25)/1000.0f); break; } } } bool Game::collideCircleVsCircle(Entity *a, Entity *b) { return (a->position - b->position).isLength2DIn(a->collideRadius + b->collideRadius); } bool Game::collideHairVsCircle(Entity *a, int num, const Vector &pos2, int radius, float perc, int *colSegment) { if (perc == 0) perc = 1; bool c = false; if (a && a->hair) { if (num == 0) num = a->hair->hairNodes.size(); // HACK: minus 2 for (int i = 0; i < num; i++) { // + a->hair->position c = ((a->hair->hairNodes[i].position) - pos2).isLength2DIn(a->hair->hairWidth*perc + radius); if (c) { if (colSegment) *colSegment = i; return true; } } } return c; } // NOTE THIS FUNCTION ASSUMES THAT IF A BONE ISN'T AT FULL ALPHA (1.0) IT IS DISABLED Bone *Game::collideSkeletalVsCircle(Entity *skeletal, Entity *circle) { Vector pos = circle->position; return collideSkeletalVsCircle(skeletal, pos, circle->collideRadius); } Bone *Game::collideSkeletalVsLine(Entity *skeletal, Vector start, Vector end, float radius) { //float smallestDist = HUGE_VALF; Bone *closest = 0; for (int i = 0; i < skeletal->skeletalSprite.bones.size(); i++) { Bone *b = skeletal->skeletalSprite.bones[i]; /* int checkRadius = sqr(radius+b->collisionMaskRadius); Vector bonePos = b->getWorldCollidePosition(); float dist = (bonePos - pos).getSquaredLength2D(); */ // MULTIPLE CIRCLES METHOD if (!b->collisionMask.empty() && b->alpha.x == 1 && b->renderQuad) { for (int i = 0; i < b->transformedCollisionMask.size(); i++) { if (isTouchingLine(start, end, b->transformedCollisionMask[i], radius+b->collideRadius)) { closest = b; //smallestDist = dist; break; } } } if (closest != 0) { break; } /* // ONE CIRCLE PER BONE METHOD else if (b->collideRadius && b->alpha.x == 1) { if (dist < checkRadius) { if (dist < smallestDist) { closest = b; smallestDist = dist; } } } */ } return closest; } bool Game::collideCircleVsLine(RenderObject *r, Vector start, Vector end, float radius) { bool collision = false; if (isTouchingLine(start, end, r->position, radius+r->collideRadius, &lastCollidePosition)) { collision = true; } return collision; } bool Game::collideCircleVsLineAngle(RenderObject *r, float angle, float startLen, float endLen, float radius, Vector basePos) { bool collision = false; float rads = MathFunctions::toRadians(angle); float sinv = sinf(rads); float cosv = cosf(rads); Vector start=Vector(sinv,cosv)*startLen + basePos; Vector end=Vector(sinv,cosv)*endLen + basePos; if (isTouchingLine(start, end, r->position, radius+r->collideRadius, &lastCollidePosition)) { collision = true; } if (shapeDebug) { shapeDebug->position = end; } return collision; } Bone *Game::collideSkeletalVsCircle(Entity *skeletal, Vector pos, float radius) { float smallestDist = HUGE_VALF; Bone *closest = 0; if (!(pos - skeletal->position).isLength2DIn(2000)) return 0; for (int i = 0; i < skeletal->skeletalSprite.bones.size(); i++) { Bone *b = skeletal->skeletalSprite.bones[i]; if (b->alpha.x == 1 && b->renderQuad) { float checkRadius = sqr(radius+b->collisionMaskRadius); Vector bonePos = b->getWorldCollidePosition(); float dist = (bonePos - pos).getSquaredLength2D(); // BOUND RECT METHOD if (!b->collisionRects.empty()) { for (int i = 0; i < b->collisionRects.size(); i++) { b->collisionRects[i].isCoordinateInside(pos, radius); } } // MULTIPLE CIRCLES METHOD else if (!b->collisionMask.empty()) { if (dist < checkRadius) { for (int i = 0; i < b->transformedCollisionMask.size(); i++) { if ((b->transformedCollisionMask[i] - pos).isLength2DIn(radius+b->collideRadius*skeletal->scale.x)) { closest = b; smallestDist = dist; lastCollideMaskIndex = i; break; } } } } // ONE CIRCLE PER BONE METHOD else if (b->collideRadius) { if (dist < sqr(radius+b->collideRadius)) { if (dist < smallestDist) { closest = b; smallestDist = dist; } } } } } return closest; } void Game::preLocalWarp(LocalWarpType localWarpType) { // won't work if you start the map inside a local warp area... but that doesn't happen much for collecting gems if (localWarpType == LOCALWARP_IN) { dsq->game->avatar->warpInLocal = dsq->game->avatar->position; } else if (localWarpType == LOCALWARP_OUT) { dsq->game->avatar->warpInLocal = Vector(0,0,0); } dsq->screenTransition->capture(); core->resetTimer(); } void Game::postLocalWarp() { if (dsq->game->li && dsq->continuity.hasLi()) dsq->game->li->position = dsq->game->avatar->position; if (dsq->game->avatar->pullTarget) dsq->game->avatar->pullTarget->position = dsq->game->avatar->position; dsq->game->snapCam(); dsq->screenTransition->transition(0.6); } void Game::registerSporeDrop(const Vector &pos, int t) { FOR_ENTITIES(i) { Entity *e = *i; if ((e->position - pos).isLength2DIn(1024)) { e->sporesDropped(pos, t); } } } bool Game::isEntityCollideWithShot(Entity *e, Shot *shot) { if (!shot->isHitEnts() || shot->firer == e) { return false; } if (shot->shotData && shot->shotData->checkDamageTarget) { if (!e->isDamageTarget(shot->getDamageType())) return false; } if (e->getEntityType() == ET_ENEMY) { if (shot->getDamageType() == DT_AVATAR_BITE) { Avatar::BittenEntities::iterator i; for (i = avatar->bittenEntities.begin(); i != avatar->bittenEntities.end(); i++) { if (e == (*i)) { return false; } } return true; } } else if (e->getEntityType() == ET_AVATAR) { // this used to be stuff != ET_AVATAR.. but what else would do that return !dsq->game->isDamageTypeAvatar(shot->getDamageType()) && (!shot->firer || shot->firer->getEntityType() == ET_ENEMY); } else if (e->getEntityType() == ET_PET) { bool go = shot->firer != e; if (shot->firer && shot->firer->getEntityType() != ET_ENEMY) go = false; return go; } return true; } void Game::handleShotCollisions(Entity *e, bool hasShield) { BBGE_PROF(Game_handleShotCollisions); bool isRegValid=true; for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++) { Shot *shot = *i; if (shot->isActive() && isEntityCollideWithShot(e, shot) && (!hasShield || (!shot->shotData || !shot->shotData->ignoreShield))) { Vector collidePoint = e->position+e->offset; if (e->getNumTargetPoints()>0) { collidePoint = e->getTargetPoint(0); } if ((collidePoint - shot->position).isLength2DIn(shot->collideRadius + e->collideRadius)) { lastCollidePosition = shot->position; shot->hitEntity(e,0,isRegValid); } } } } bool Game::isDamageTypeAvatar(DamageType dt) { return (dt >= DT_AVATAR && dt < DT_TOUCH); } bool Game::isDamageTypeEnemy(DamageType dt) { return (dt >= DT_ENEMY && dt < DT_AVATAR); } void Game::handleShotCollisionsSkeletal(Entity *e) { BBGE_PROF(Game_HSSKELETAL); for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++) { Shot *shot = *i; if (shot->isActive() && isEntityCollideWithShot(e, shot)) { Bone *b = collideSkeletalVsCircle(e, shot->position, shot->collideRadius); if (b) { lastCollidePosition = shot->position; shot->hitEntity(e, b); } } } } void Game::handleShotCollisionsHair(Entity *e, int num) { for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++) { Shot *shot = *i; if (shot->isActive() && isEntityCollideWithShot(e, shot)) { bool b = collideHairVsCircle(e, num, shot->position, 8); if (b) { lastCollidePosition = shot->position; shot->hitEntity(e, 0); } } } } #ifdef AQUARIA_BUILD_SCENEEDITOR void Game::toggleSceneEditor() { if (!core->getAltState()) { sceneEditor.toggle(); setElementLayerFlags(); } } #endif void Game::toggleMiniMapRender() { if (miniMapRender) { if (miniMapRender->alpha == 0) miniMapRender->alpha.interpolateTo(1, 0.1f); else if (!miniMapRender->alpha.isInterpolating()) miniMapRender->alpha.interpolateTo(0, 0.1f); } } void Game::toggleMiniMapRender(int v) { if (miniMapRender) { if (v == 0) miniMapRender->alpha.interpolateTo(0, 0.1f); else miniMapRender->alpha.interpolateTo(1, 0.1f); } } void Game::toggleGridRender() { float t = 0; if (gridRender->alpha == 0) { gridRender->alpha.interpolateTo(0.5, t); gridRender2->alpha.interpolateTo(0.5, t); gridRender3->alpha.interpolateTo(0.5, t); edgeRender->alpha.interpolateTo(0.5, t); gridRenderEnt->alpha.interpolateTo(0.5, t); } else if (gridRender->alpha == 0.5) { gridRender->alpha.interpolateTo(0, t); gridRender2->alpha.interpolateTo(0, t); gridRender3->alpha.interpolateTo(0, t); edgeRender->alpha.interpolateTo(0, t); gridRenderEnt->alpha.interpolateTo(0, t); } } Vector Game::getCameraPositionFor(const Vector &pos) { Vector dest = pos; Vector v; dest += v + Vector(-400/core->globalScale.x,-300/core->globalScale.y); dest.z = 0; return dest; } void Game::setParallaxTextureCoordinates(Quad *q, float speed) { //int backgroundImageRepeat = 1.2; q->followCamera = 1; q->texture->repeat = true; float camx = (core->cameraPos.x/800.0f)*speed; float camy = -(core->cameraPos.y/600.0f)*speed; float camx1 = camx - float(backgroundImageRepeat)/2.0f; float camx2 = camx + float(backgroundImageRepeat)/2.0f; float camy1 = camy - float(backgroundImageRepeat)/2.0f; float camy2 = camy + float(backgroundImageRepeat)/2.0f; q->upperLeftTextureCoordinates = Vector(camx1*backgroundImageRepeat, camy1*backgroundImageRepeat); q->lowerRightTextureCoordinates = Vector(camx2*backgroundImageRepeat, camy2*backgroundImageRepeat); } void Game::setCameraFollow(Vector *position) { cameraFollow = position; cameraFollowObject = 0; cameraFollowEntity = 0; } void Game::setCameraFollow(RenderObject *r) { cameraFollow = &r->position; cameraFollowObject = r; cameraFollowEntity = 0; } void Game::setCameraFollowEntity(Entity *e) { cameraFollow = &e->position; cameraFollowObject = 0; cameraFollowEntity = e; } void Game::updateCurrentVisuals(float dt) { /* static float delay = 0; delay += dt; if (delay > 0.2f) { for (Path *p = dsq->game->getFirstPathOfType(PATH_CURRENT); p; p = p->nextOfType) { if (p->active) { for (int n = 1; n < p->nodes.size(); n++) { PathNode *node2 = &p->nodes[n]; PathNode *node1 = &p->nodes[n-1]; Vector dir = node2->position - node1->position; dir.setLength2D(p->currentMod); dsq->spawnBubble(node1->position, dir); } } } delay = 0; } */ /* if (dsq->game->getPath(i)->name == "CURRENT" && dsq->game->getPath(i)->nodes.size() >= 2) { Vector dir = dsq->game->getPath(i)->nodes[1].position - dsq->game->getPath(i)->nodes[0].position; dir.setLength2D(800); dsq->spawnBubble(dsq->game->getPath(i)->nodes[0].position, dir); } */ } void Game::onOptionsMenu() { dsq->screenTransition->capture(); toggleOptionsMenu(true); dsq->screenTransition->transition(MENUPAGETRANSTIME); } void Game::onOptionsSave() { dsq->user.apply(); if (dsq->user.video.resx != dsq->user_backup.video.resx || dsq->user.video.resy != dsq->user_backup.video.resy || dsq->user.video.bits != dsq->user_backup.video.bits || dsq->user.video.full != dsq->user_backup.video.full || dsq->user.video.vsync != dsq->user_backup.video.vsync) { dsq->resetGraphics(dsq->user.video.resx, dsq->user.video.resy, dsq->user.video.full); if (dsq->confirm("", "graphics", false, 10)) { } else { dsq->user.video.resx = dsq->user_backup.video.resx; dsq->user.video.resy = dsq->user_backup.video.resy; dsq->user.video.bits = dsq->user_backup.video.bits; dsq->user.video.full = dsq->user_backup.video.full; dsq->user.video.vsync = dsq->user_backup.video.vsync; dsq->user.apply(); dsq->resetGraphics(dsq->user.video.resx, dsq->user.video.resy, dsq->user.video.full); } } /* if (dsq->user.video.ripples != dsq->user_backup.video.ripples) { if (dsq->user.video.ripples) { if (core->frameBuffer.isInited()) { if (!core->afterEffectManager) { core->afterEffectManager = new AfterEffectManager(vars->afterEffectsXDivs, vars->afterEffectsYDivs); core->afterEffectManager->update(0.0); core->afterEffectManager->capture(); } dsq->useFrameBuffer = 1; } else { dsq->useFrameBuffer = 0; } } else { if (core->afterEffectManager) { delete core->afterEffectManager; core->afterEffectManager = 0; } } } */ if (!keyConfigMenu) dsq->user.save(); if (keyConfigMenu) { AquariaKeyConfig::waitingForInput = 0; dsq->screenTransition->capture(); toggleKeyConfigMenu(false); toggleOptionsMenu(true, false, true); dsq->screenTransition->transition(MENUPAGETRANSTIME); } else { if (optionsOnly) { hideInGameMenu(); } else { dsq->screenTransition->capture(); toggleOptionsMenu(false); dsq->screenTransition->transition(MENUPAGETRANSTIME); } } } void Game::onOptionsCancel() { if (!keyConfigMenu) { dsq->user = dsq->user_backup; } else { dsq->user.control.actionSet = dsq->user_bcontrol.control.actionSet; } dsq->user.apply(); if (keyConfigMenu) { AquariaKeyConfig::waitingForInput = 0; dsq->screenTransition->capture(); toggleKeyConfigMenu(false); toggleOptionsMenu(true, true, true); dsq->screenTransition->transition(MENUPAGETRANSTIME); } else { if (optionsOnly) { hideInGameMenu(); } else { dsq->screenTransition->capture(); toggleOptionsMenu(false); dsq->screenTransition->transition(MENUPAGETRANSTIME); } } } void Game::refreshFoodSlots(bool effects) { for (int i = 0; i < foodSlots.size(); i++) { foodSlots[i]->refresh(effects); } adjustFoodSlotCursor(); } void Game::refreshTreasureSlots() { for (int i = 0; i < treasureSlots.size(); i++) { treasureSlots[i]->refresh(); } } void Game::togglePetMenu(bool f) { if (optionsMenu) { toggleOptionsMenu(false); } if (foodMenu) toggleFoodMenu(false); if (treasureMenu) toggleTreasureMenu(false); if (f && !petMenu) { currentMenuPage = MENUPAGE_PETS; toggleMainMenu(false); bool hasPet = false; for (int i = 0; i < petSlots.size(); i++) { petSlots[i]->alpha = 1; bool has = dsq->continuity.getFlag(petSlots[i]->petFlag); if (has) { hasPet = true; /* for (int j = 0; j < petSlots.size(); j++) { if (j != i) { bool has = dsq->continuity.getFlag(petSlots[j]->petFlag); if (has) { if (i == 0 && j == 1) { } } } } */ } } // act as if they're all active for now... if (petSlots.size() == 4) { petSlots[0]->setDirMove(DIR_RIGHT, petSlots[1]); petSlots[0]->setDirMove(DIR_UP, petSlots[2]); petSlots[0]->setDirMove(DIR_LEFT, petSlots[3]); petSlots[0]->setDirMove(DIR_DOWN, menu[0]); menu[0]->setDirMove(DIR_UP, petSlots[0]); petSlots[1]->setDirMove(DIR_LEFT, petSlots[3]); petSlots[1]->setDirMove(DIR_UP, petSlots[2]); petSlots[1]->setDirMove(DIR_DOWN, petSlots[0]); petSlots[1]->setDirMove(DIR_RIGHT, menu[5]); menu[5]->setDirMove(DIR_LEFT, petSlots[1]); menu[5]->setDirMove(DIR_UP, petSlots[1]); petSlots[2]->setDirMove(DIR_RIGHT, petSlots[1]); petSlots[2]->setDirMove(DIR_DOWN, petSlots[0]); petSlots[2]->setDirMove(DIR_LEFT, petSlots[3]); petSlots[3]->setDirMove(DIR_UP, petSlots[2]); petSlots[3]->setDirMove(DIR_RIGHT, petSlots[1]); petSlots[3]->setDirMove(DIR_DOWN, petSlots[0]); } for (int i = 0; i < petTips.size(); i++) { /* if (hasPet && i == 0) { petTips[i]->alpha = 0; } else if (!hasPet && i == 1) petTips[i]->alpha = 0; else petTips[i]->alpha = 1; */ petTips[i]->alpha = 1; } liCrystal->alpha = 1; menu[7]->setFocus(true); doMenuSectionHighlight(2); } else if (!f && petMenu) { for (int i = 0; i < petSlots.size(); i++) { petSlots[i]->alpha = 0; } for (int i = 0; i < petTips.size(); i++) { petTips[i]->alpha = 0; } liCrystal->alpha = 0; menu[5]->setDirMove(DIR_LEFT, 0); menu[5]->setDirMove(DIR_UP, 0); menu[0]->setDirMove(DIR_UP, 0); } petMenu = f; } void Game::toggleTreasureMenu(bool f) { //debugLog("toggle treasure menu!"); if (optionsMenu) toggleOptionsMenu(false); if (foodMenu) toggleFoodMenu(false); if (petMenu) togglePetMenu(false); if (f && !treasureMenu) { currentMenuPage = MENUPAGE_TREASURES; treasureMenu = true; toggleMainMenu(false); refreshTreasureSlots(); for (int i = 0; i < treasureTips.size(); i++) treasureTips[i]->alpha = 1; if (treasureSlots.size() > 8) { treasureSlots[0]->setDirMove(DIR_DOWN, menu[0]); menu[0]->setDirMove(DIR_UP, treasureSlots[0]); treasureSlots[2]->setDirMove(DIR_RIGHT, menu[5]); menu[5]->setDirMove(DIR_LEFT, treasureSlots[2]); treasureSlots[3]->setDirMove(DIR_RIGHT, menu[5]); } menu[8]->setFocus(true); doMenuSectionHighlight(3); liCrystal->alpha = 1; circlePageNum->alpha = 1; } else if (!f && treasureMenu) { treasureMenu = false; for (int i = 0; i < treasureTips.size(); i++) treasureTips[i]->alpha = 0; menu[0]->setDirMove(DIR_UP, 0); menu[5]->setDirMove(DIR_LEFT, 0); liCrystal->alpha = 0; circlePageNum->alpha = 0; } for (int i = 0; i < treasureSlots.size(); i++) { if (f) treasureSlots[i]->alpha = 1; else treasureSlots[i]->alpha = 0; } if (f) { nextTreasure->alpha = 1; prevTreasure->alpha = 1; use->alpha = 0; treasureLabel->alpha = 0; treasureDescription->alpha = 0; treasureCloseUp->alpha = 0; } else { nextTreasure->alpha = 0; prevTreasure->alpha = 0; use->alpha = 0; treasureLabel->alpha = 0; treasureDescription->alpha = 0; treasureCloseUp->alpha = 0; } } void Game::toggleRecipeList(bool on) { recipeMenu.toggle(on, true); } void Game::toggleFoodMenu(bool f) { if (optionsMenu) toggleOptionsMenu(false); if (petMenu) togglePetMenu(false); if (treasureMenu) toggleTreasureMenu(false); for (int i = 0; i < foodHolders.size(); i++) { if (f) foodHolders[i]->alpha = 1; else foodHolders[i]->alpha = 0; } if (f) { if (dsq->game->avatar) { Path *p=0; if (dsq->continuity.getFlag(FLAG_UPGRADE_WOK) > 0 || ((p=dsq->game->getNearestPath(dsq->game->avatar->position, PATH_COOK)) && p->isCoordinateInside(dsq->game->avatar->position))) { //cook->alpha = 1; foodHolders[0]->alpha = 1; } else { foodHolders[0]->alpha = 0; } } } if (f && !foodMenu) { currentMenuPage = MENUPAGE_FOOD; foodMenu = true; toggleMainMenu(false); refreshFoodSlots(false); cook->alpha = 1; recipes->alpha = 1; prevFood->alpha = 1; nextFood->alpha = 1; foodLabel->alphaMod = 1; foodDescription->alphaMod = 1; foodSort->alpha = 1; for (int i = 0; i < foodTips.size(); i++) foodTips[i]->alpha = 1; if (foodSlots.size() >= 16) { foodSlots[2]->setDirMove(DIR_RIGHT, menu[5]); foodSlots[3]->setDirMove(DIR_RIGHT, menu[5]); menu[5]->setDirMove(DIR_LEFT, foodSlots[2]); treasureSlots[3]->setDirMove(DIR_RIGHT, menu[5]); recipes->setDirMove(DIR_UP, foodSlots[15]); foodSlots[15]->setDirMove(DIR_DOWN, recipes); foodSlots[14]->setDirMove(DIR_DOWN, recipes); foodSlots[0]->setDirMove(DIR_DOWN, recipes); foodSlots[0]->setDirMove(DIR_LEFT, foodSlots[15]); foodSlots[15]->setDirMove(DIR_RIGHT, foodSlots[0]); foodSlots[15]->setDirMove(DIR_LEFT, foodSlots[14]); recipes->setDirMove(DIR_RIGHT, menu[5]); } menu[6]->setFocus(true); doMenuSectionHighlight(1); liCrystal->alpha = 1; circlePageNum->alpha = 1; previewRecipe->alpha = 0; updatePreviewRecipe(); } else if (!f && foodMenu) { recipeMenu.toggle(false); foodMenu = false; cook->alpha = 0; recipes->alpha = 0; prevFood->alpha = 0; nextFood->alpha = 0; foodLabel->alphaMod = 0; foodLabel->alpha = 0; foodDescription->alpha = 0; foodSort->alpha = 0; showRecipe->alpha = 0; liCrystal->alpha = 0; for (int i = 0; i < foodTips.size(); i++) foodTips[i]->alpha = 0; menu[5]->setDirMove(DIR_LEFT, 0); circlePageNum->alpha = 0; previewRecipe->alpha = 0; } for (int i = 0; i < foodSlots.size(); i++) { foodSlots[i]->toggle(f); } } void Game::doMenuSectionHighlight(int section) { for (int i = 0; i < 4; i++) ((AquariaMenuItem*)menu[(5+i)])->quad->alphaMod = 0.8; //menu[(5+i)]->offset = Vector(0,-2); ((AquariaMenuItem*)menu[(5+section)])->quad->alphaMod = 1.0; menuIconGlow->position = menu[5+section]->position; /* for (int i = 0; i < 4; i++) menu[5+i]->color = Vector(0.5, 0.5, 0.5); menu[5+section]->color = Vector(1,1,1); */ } void Game::toggleMainMenu(bool f) { const float t = 0; if (f) { currentMenuPage = MENUPAGE_SONGS; for (int i = 0; i < songSlots.size(); i++) { //songSlots[i]->alpha.interpolateTo(1, t); songSlots[i]->alphaMod = 1; } songBubbles->alpha.interpolateTo(1,t); energyIdol->alpha.interpolateTo(1,t); liCrystal->alpha.interpolateTo(1, t); for (int i = 0; i < songTips.size(); i++) songTips[i]->alpha = 1; menuBg2->alpha.interpolateTo(1, t); int sm=-900; SongSlot *ss=0; for (int i = 0; i < songSlots.size(); i++) { if (dsq->continuity.hasSong(dsq->continuity.getSongTypeBySlot(i))) { //if (songSlots[i]->alpha == 1 && songSlots[i]->renderQuad && songSlots[i]->alphaMod == 1) { Vector p = songSlots[i]->getWorldPosition(); if (p.x > sm) { sm = p.x; ss = songSlots[i]; } } } } if (ss) { ss->setDirMove(DIR_RIGHT, (AquariaMenuItem*)menu[5]); } ((AquariaMenuItem*)menu[5])->setDirMove(DIR_LEFT, ss); doMenuSectionHighlight(0); } else { ((AquariaMenuItem*)menu[5])->setDirMove(DIR_LEFT, 0); for (int i = 0; i < songSlots.size(); i++) { songSlots[i]->alphaMod = 0; } for (int i = 0; i < songTips.size(); i++) songTips[i]->alpha = 0; songBubbles->alpha.interpolateTo(0, t); energyIdol->alpha.interpolateTo(0,t); liCrystal->alpha.interpolateTo(0, t); } } void Game::toggleKeyConfigMenu(bool f) { const float t = 0; playingSongInMenu = -1; if (f && !keyConfigMenu) { //dsq->screenTransition->capture(); toggleOptionsMenu(false, false, true); // Prevent int i from "leaking out" due to Microsoft extension to for-scope { for (int i = 0; i <= 1; i++) menu[i]->alpha.interpolateTo(0, t); for (int i = 4; i <= 8; i++) menu[i]->alpha.interpolateTo(0, t); } toggleMainMenu(false); menuBg2->alpha.interpolateTo(0, t); keyConfigMenu = true; group_keyConfig->setHidden(false); group_keyConfig->alpha = 1; dsq->user_bcontrol = dsq->user; //group_keyConfig->children[group_keyConfig->children.size()-3] RenderObjectList::reverse_iterator i = group_keyConfig->children.rbegin(); AquariaKeyConfig *upright0 = (AquariaKeyConfig*)(*i); i++; AquariaKeyConfig *upright = (AquariaKeyConfig*)(*i); i++; //i++; AquariaKeyConfig *upleft = (AquariaKeyConfig*)(*i); opt_cancel->setDirMove(DIR_UP, upright); upright->setDirMove(DIR_DOWN, opt_cancel); upright0->setDirMove(DIR_DOWN, opt_cancel); opt_save->setDirMove(DIR_UP, upleft); upleft->setDirMove(DIR_DOWN, opt_save); opt_cancel->alpha = 1; opt_save->alpha = 1; opt_save->position = opt_save_original + Vector(0, 120); opt_cancel->position = opt_cancel_original + Vector(0, 120); opt_cancel->setFocus(true); menuIconGlow->alpha = 0; //dsq->screenTransition->transition(MENUPAGETRANSTIME); } else if (!f) { keyConfigMenu = false; group_keyConfig->alpha = 0; group_keyConfig->setHidden(true); opt_cancel->alpha = 0; opt_save->alpha = 0; opt_save->position = opt_save_original; opt_cancel->position = opt_cancel_original; menuIconGlow->alpha = 1; } } void Game::toggleOptionsMenu(bool f, bool skipBackup, bool isKeyConfig) { const float t = 0; playingSongInMenu = -1; if (f && !optionsMenu) { //menuBg->setTexture("gui/options-menu"); //menuBg->setWidthHeight(1024, 1024); if (!isKeyConfig && !optionsOnly) { dsq->continuity.lastOptionsMenuPage = currentMenuPage; } toggleFoodMenu(false); optionsMenu = true; voxslider->setValue(dsq->user.audio.voxvol); musslider->setValue(dsq->user.audio.musvol); sfxslider->setValue(dsq->user.audio.sfxvol); if (blurEffectsCheck) blurEffectsCheck->setValue(dsq->user.video.blur); flipInputButtonsCheck->setValue(dsq->user.control.flipInputButtons); toolTipsCheck->setValue(dsq->user.control.toolTipsOn); autoAimCheck->setValue(dsq->user.control.autoAim); targetingCheck->setValue(dsq->user.control.targeting); subtitlesCheck->setValue(dsq->user.audio.subtitles); fullscreenCheck->setValue(dsq->isFullscreen()); if (ripplesCheck) ripplesCheck->setValue(core->afterEffectManager!=0); if (micInputCheck) micInputCheck->setValue(dsq->user.audio.micOn); if (resBox) { std::ostringstream os; os << core->width << "x" << core->height; if (!resBox->setSelectedItem(os.str())) { resBox->addItem(os.str()); resBox->setSelectedItem(os.str()); } } opt_cancel->setDirMove(DIR_UP, targetingCheck); targetingCheck->setDirMove(DIR_DOWN, opt_cancel); opt_save->setDirMove(DIR_UP, voxslider); voxslider->setDirMove(DIR_DOWN, opt_save); keyConfigButton->setDirMove(DIR_UP, targetingCheck); if (!skipBackup) dsq->user_backup = dsq->user; options->alpha.interpolateTo(1, t); for (int i = 0; i <= 1; i++) menu[i]->alpha.interpolateTo(0, t); for (int i = 4; i <= 9; i++) menu[i]->alpha.interpolateTo(0, t); toggleMainMenu(false); keyConfigButton->alpha = 1; menuBg2->alpha.interpolateTo(0, t); opt_cancel->alpha = 1; opt_save->alpha = 1; opt_cancel->setFocus(true); lips->alpha = 0; liCrystal->alpha = 1; optionsMenu = true; menuIconGlow->alpha = 0; /* for (int i = 0; i < menu.size(); i++) menu[i]->alpha.interpolateTo(0, 0.2); */ } else if (!f && optionsMenu) { lips->alpha = 0; keyConfigButton->alpha = 0; options->alpha.interpolateTo(0, t); opt_cancel->alpha = 0; opt_save->alpha = 0; liCrystal->alpha = 0; /* // what does this do? if (optionsMenu) ((AquariaMenuItem*)menu[4])->setFocus(true); */ //((AquariaMenuItem*)menu[5])->setFocus(true); optionsMenu = false; if (!optionsOnly) { for (int i = 0; i <= 1; i++) menu[i]->alpha.interpolateTo(1, t); for (int i = 4; i <= 9; i++) { menu[i]->alpha.interpolateTo(1, t); } //menu[9]->alpha = 1; if (!isKeyConfig) { switch(dsq->continuity.lastOptionsMenuPage) { case MENUPAGE_FOOD: toggleFoodMenu(true); ((AquariaMenuItem*)menu[6])->setFocus(true); break; case MENUPAGE_TREASURES: toggleTreasureMenu(true); ((AquariaMenuItem*)menu[8])->setFocus(true); break; case MENUPAGE_PETS: togglePetMenu(true); ((AquariaMenuItem*)menu[7])->setFocus(true); break; case MENUPAGE_SONGS: default: toggleMainMenu(true); ((AquariaMenuItem*)menu[5])->setFocus(true); break; } } //((AquariaMenuItem*)menu[4])->setFocus(true); menuBg2->alpha.interpolateTo(1, t); } menuIconGlow->alpha = 1; } } float optsfxdly = 0; void Game::updateOptionsMenu(float dt) { if (optionsMenu) { dsq->user.audio.voxvol = voxslider->getValue(); dsq->user.audio.sfxvol = sfxslider->getValue(); dsq->user.audio.musvol = musslider->getValue(); if (micInputCheck) dsq->user.audio.micOn = micInputCheck->getValue(); dsq->user.control.flipInputButtons = flipInputButtonsCheck->getValue(); dsq->user.control.toolTipsOn = toolTipsCheck->getValue(); dsq->user.control.autoAim = autoAimCheck->getValue(); dsq->user.control.targeting = targetingCheck->getValue(); dsq->user.audio.subtitles = subtitlesCheck->getValue(); dsq->user.video.full = fullscreenCheck->getValue(); if (ripplesCheck) dsq->user.video.fbuffer = ripplesCheck->getValue(); if (blurEffectsCheck) dsq->user.video.blur = blurEffectsCheck->getValue(); if (resBox) { std::string s = resBox->getSelectedItemString(); if (!s.empty()) { int pos = s.find('x'); std::istringstream is1(s.substr(0, pos)); is1 >> dsq->user.video.resx; std::istringstream is2(s.substr(pos+1, s.size()-(pos+1))); is2 >> dsq->user.video.resy; } } /* dsq->user.audio.sfxvol = sfxslider->getValue(); dsq->user.audio.musvol = musslider->getValue(); */ optsfxdly += dt; if (sfxslider->hadInput()) { dsq->sound->playSfx("denied"); } else if (voxslider->hadInput()) { if (!dsq->sound->isPlayingVoice()) dsq->voice("naija_somethingfamiliar"); } else if (optsfxdly > 0.6f) { optsfxdly = 0; if (sfxslider->isGrabbed()) { dsq->sound->playSfx("denied"); dsq->loops.updateVolume(); if (dsq->game->avatar) dsq->game->avatar->updateHeartbeatSfx(); } if (voxslider->isGrabbed()) { if (!dsq->sound->isPlayingVoice()) { dsq->voice("naija_somethingfamiliar"); } } } /* std::ostringstream os; os << "musvol: " << dsq->user.audio.musvol; debugLog(os.str()); */ dsq->user.apply(); } } void Game::updateInGameMenu(float dt) { if (isInGameMenu()) { menuOpenTimer += dt; if (dt > 10) dt = 10; if (foodMenu) { if (dsq->inputMode == INPUT_JOYSTICK) { //debugLog("food menu, joystick"); /* */ } if (dsq->continuity.hasIngredients()) { int pageNum = (currentFoodPage+1); int numPages = ((dsq->continuity.ingredientCount()-1)/foodPageSize)+1; std::ostringstream os; os << pageNum << "/" << numPages; circlePageNum->setText(os.str()); if (pageNum > numPages && pageNum > 1) { onPrevFoodPage(); } } else { circlePageNum->setText("1/1"); } } if (treasureMenu) { std::ostringstream os; os << (currentTreasurePage+1) << "/" << (numTreasures/treasurePageSize); circlePageNum->setText(os.str()); } // HACK: move this later updateOptionsMenu(dt); if (playingSongInMenu != -1) { songMenuPlayDelay += dt; Song s = dsq->continuity.songBank[playingSongInMenu]; if (currentSongMenuNote < s.notes.size()) { if (songMenuPlayDelay >= 0.5f) { songMenuPlayDelay = 0; if (currentSongMenuNote >= 0 && currentSongMenuNote < s.notes.size()) { /* std::ostringstream os; os << "MenuNote" << s[currentSongMenuNote]; */ sound->playSfx(dsq->game->getNoteName(s.notes[currentSongMenuNote], "Menu")); float a = (s.notes[currentSongMenuNote]*2*PI)/8.0f; int sz = 110*menuBg->scale.x; Vector notePos(sinf(a)*sz,cosf(a)*sz); float t = 0.5; Quad *q = new Quad("particles/glow", Vector(400+237*menuBg->scale.x,300-52*menuBg->scale.x)+notePos); q->setBlendType(RenderObject::BLEND_ADD); q->scale = Vector(5,5); q->alpha.ensureData(); q->alpha.data->path.addPathNode(0, 0); q->alpha.data->path.addPathNode(0.75, 0.5); q->alpha.data->path.addPathNode(0.75, 0.5); q->alpha.data->path.addPathNode(0, 1); q->alpha.startPath(t); q->followCamera = 1; q->setLife(t); q->setDecayRate(1); game->addRenderObject(q, LR_HUD); currentSongMenuNote++; } else { /* if (playedDudNote) playingSongInMenu = -1; else playedDudNote = true; */ } } } else { if (songMenuPlayDelay >= 1.0f) { playingSongInMenu = -1; } } } } } void Game::updateCursor(float dt) { bool rotate = false; if (dsq->inputMode == INPUT_MOUSE) { dsq->cursor->offset.stop(); dsq->cursor->offset = Vector(0,0); //debugLog("offset lerp stop in mouse!"); } else if (dsq->inputMode == INPUT_JOYSTICK) { if (!dsq->game->isPaused() || dsq->game->isInGameMenu() || !dsq->game->avatar->isInputEnabled()) { int offy = -60; if (dsq->game->isInGameMenu() || !dsq->game->avatar->isInputEnabled()) { //cursor->setTexture(""); offy = 0; } if (!dsq->cursor->offset.isInterpolating()) { //debugLog("offset lerp!"); dsq->cursor->offset = Vector(0, offy); dsq->cursor->offset.interpolateTo(Vector(0, offy-20), 0.4, -1, 1, 1); } } else { //debugLog("offset lerp stop in joystick!"); dsq->cursor->offset.stop(); dsq->cursor->offset = Vector(0,0); } } if (isSceneEditorActive() || dsq->game->isPaused() || (!avatar || !avatar->isInputEnabled()) || (dsq->game->miniMapRender && dsq->game->miniMapRender->isCursorIn()) ) { dsq->setCursor(CURSOR_NORMAL); // Don't show the cursor in keyboard/joystick mode if it's not // already visible (this keeps the cursor from appearing for an // instant during map fadeout). if (dsq->inputMode == INPUT_MOUSE || isSceneEditorActive() || dsq->game->isPaused()) dsq->cursor->alphaMod = 0.5; /* dsq->cursor->offset.stop(); dsq->cursor->offset = Vector(0,0); */ } else if (avatar) { //Vector v = avatar->getVectorToCursorFromScreenCentre(); if (dsq->inputMode == INPUT_JOYSTICK)// && !avatar->isSinging() && !dsq->game->isInGameMenu() && !dsq->game->isPaused()) { dsq->cursor->alphaMod = 0; if (!avatar->isSinging()) core->setMousePosition(core->center); if (!dsq->game->isPaused()) { /* */ } } else { dsq->cursor->offset.stop(); dsq->cursor->offset = Vector(0,0); dsq->cursor->alphaMod = 0.5; } Vector v = avatar->getVectorToCursor(); if (avatar->looking) { dsq->setCursor(CURSOR_LOOK); } else if (avatar->isSinging()) { dsq->setCursor(CURSOR_SING); } else if (dsq->game->isInGameMenu() || v.isLength2DIn(avatar->getStopDistance()) || (avatar->entityToActivate || avatar->pathToActivate)) { dsq->setCursor(CURSOR_NORMAL); } else if (!v.isLength2DIn(avatar->getBurstDistance()) /*|| avatar->state.lockedToWall*/ /*|| avatar->bursting*/) { dsq->setCursor(CURSOR_BURST); rotate = true; } else { dsq->setCursor(CURSOR_SWIM); rotate = true; } } if (rotate) { if (avatar) { Vector vec = dsq->getGameCursorPosition() - avatar->position; float angle=0; MathFunctions::calculateAngleBetweenVectorsInDegrees(Vector(0,0,0), vec, angle); angle = 180-(360-angle); angle += 90; dsq->cursor->rotation.z = angle; } } else { dsq->cursor->rotation.z = 0; } } void Game::constrainCamera() { cameraOffBounds = 0; if (cameraConstrained) { float vw2 = core->getVirtualOffX()*core->invGlobalScale; float vh2 = core->getVirtualOffY()*core->invGlobalScale; if (dsq->cameraPos.x - vw2 < (cameraMin.x+1)) { dsq->cameraPos.x = (cameraMin.x+1) + vw2; cameraOffBounds = 1; } if (dsq->cameraPos.y <= (cameraMin.y+1)) { dsq->cameraPos.y = (cameraMin.y+1) + vh2; cameraOffBounds = 1; } // The camera is positioned at (0, 0) screen coordinates, which, on widescreen resolutions, // is *not* the upper left corner. Subtract the offset to get the real position. // HACK: One column shows through after blackness ends, adding TILE_SIZE fixes this. -- fg float scrw = (core->getVirtualWidth()-core->getVirtualOffX()+TILE_SIZE)*core->invGlobalScale; float scrh = 600*core->invGlobalScale; if (cameraMax.x != -1 && dsq->cameraPos.x + scrw >= cameraMax.x) { dsq->cameraPos.x = cameraMax.x - scrw; cameraOffBounds = 1; } if (cameraMax.y != -1 && dsq->cameraPos.y + scrh >= cameraMax.y) { dsq->cameraPos.y = cameraMax.y - scrh; cameraOffBounds = 1; } } } bool areEntitiesUnique() { bool unique = true; int c = 0; FOR_ENTITIES(i) { Entity *e = *i; FOR_ENTITIES(j) { Entity *e2 = *j; if (e != e2) { if (e->getID() == e2->getID()) { std::ostringstream os; os << "found non-unique entity: " << e->getID() << " names, " << e->name << " and " << e2->name; debugLog(os.str()); unique = false; c++; } } } } if (unique) { debugLog("Entity IDs are unique"); } else { std::ostringstream os; os << c << " Entity IDs are NOT unique"; debugLog(os.str()); } return unique; } bool Game::isControlHint() { return controlHint_bg->alpha.x != 0; } bool Game::trace(Vector start, Vector target) { /* TileVector tstart(start); TileVector ttarget(target); */ int i = 0; Vector mov(target-start); Vector pos = start; //mov.normalize2D(); //mov |= g; //mov |= 0.5; mov.setLength2D(TILE_SIZE*1); int c = 0; // 1024 while (c < 2048*10) { pos += mov; if (dsq->game->isObstructed(TileVector(pos))) return false; //Vector diff(tstart.x - ttarget.x, tstart.y - ttarget.y); Vector diff = target - pos; if (diff.getSquaredLength2D() <= sqr(TILE_SIZE*2)) //close enough! return true; Vector pl = mov.getPerpendicularLeft(); Vector pr = mov.getPerpendicularRight(); i = 1; for (i = 1; i <= 6; i++) { TileVector tl(pos + pl*i);//(start.x + pl.x*i, start.y + pl.y*i); TileVector tr(pos + pr*i);//(start.x + pr.x*i, start.y + pr.y*i); if (dsq->game->isObstructed(tl) || dsq->game->isObstructed(tr)) return false; } c++; } return false; } const float bgLoopFadeTime = 1; void Game::updateBgSfxLoop() { if (!avatar) return; Path *p = getNearestPath(dsq->game->avatar->position, PATH_BGSFXLOOP); if (p && p->isCoordinateInside(dsq->game->avatar->position) && !p->content.empty()) { if (bgSfxLoopPlaying2 != p->content) { if (dsq->loops.bg2 != BBGE_AUDIO_NOCHANNEL) { core->sound->fadeSfx(dsq->loops.bg2, SFT_OUT, bgLoopFadeTime); dsq->loops.bg2 = BBGE_AUDIO_NOCHANNEL; bgSfxLoopPlaying2 = ""; } PlaySfx play; play.name = p->content; play.time = bgLoopFadeTime; play.fade = SFT_IN; play.vol = 1; play.loops = -1; play.priority = 0.7; dsq->loops.bg2 = core->sound->playSfx(play); bgSfxLoopPlaying2 = p->content; } } else { if (dsq->loops.bg2 != BBGE_AUDIO_NOCHANNEL) { core->sound->fadeSfx(dsq->loops.bg2, SFT_OUT, bgLoopFadeTime); dsq->loops.bg2 = BBGE_AUDIO_NOCHANNEL; bgSfxLoopPlaying2 = ""; } } if (avatar->isUnderWater(avatar->getHeadPosition())) { dsq->game->switchBgLoop(0); } else dsq->game->switchBgLoop(1); } const float helpTextScrollSpeed = 800.0f; const float helpTextScrollClickAmount = 340.0f; const float helpTextScrollClickTime = -helpTextScrollSpeed; void Game::onHelpDown() { float to = helpText->offset.y - helpTextScrollClickAmount; if (to < -helpText->getFullHeight() + core->getVirtualHeight()) { to = -helpText->getFullHeight() + core->getVirtualHeight(); } helpText->offset.interpolateTo(Vector(0, to), helpTextScrollClickTime); } void Game::onHelpUp() { float to = helpText->offset.y + helpTextScrollClickAmount; if (to > 0) { to = 0; } helpText->offset.interpolateTo(Vector(0, to), helpTextScrollClickTime); } void Game::update(float dt) { particleManager->clearInfluences(); if (inHelpScreen) { const float helpTextScrollSpeed = 400.0f; if (isActing(ACTION_SWIMDOWN)) { helpText->offset.stop(); helpText->offset.y -= helpTextScrollSpeed * dt; if (helpText->offset.y < -helpText->getFullHeight() + core->getVirtualHeight()) { helpText->offset.y = -helpText->getFullHeight() + core->getVirtualHeight(); } } if (isActing(ACTION_SWIMUP)) { helpText->offset.stop(); helpText->offset.y += helpTextScrollSpeed * dt; if (helpText->offset.y > 0) { helpText->offset.y = 0; } } } if (enqueuedPreviewRecipe) { updatePreviewRecipe(); enqueuedPreviewRecipe = 0; } if (moveFoodSlotToFront) { moveFoodSlotToFront->moveToFront(); moveFoodSlotToFront = 0; } if (ingOffYTimer > 0) { ingOffYTimer -= dt; if (ingOffYTimer < 0) { ingOffYTimer = 0; ingOffY = 0; } } if (cookDelay > 0) { cookDelay -= dt; if (cookDelay < 0) cookDelay = 0; } if (avatar) { tintColor.update(dt); if (core->afterEffectManager) { if (tintColor.isInterpolating()) core->afterEffectManager->setActiveShader(AS_GLOW); else core->afterEffectManager->setActiveShader(AS_NONE); core->afterEffectManager->glowShader.setValue(tintColor.x, tintColor.y, tintColor.z, 1); } if (avatar->isRolling()) particleManager->addInfluence(ParticleInfluence(avatar->position, 300, 800, true)); else if (avatar->isCharging()) particleManager->addInfluence(ParticleInfluence(avatar->position, 100, 600, true)); else if (avatar->bursting) particleManager->addInfluence(ParticleInfluence(avatar->position, 400, 200, true)); else particleManager->addInfluence(ParticleInfluence(avatar->position, avatar->vel.getLength2D(), 24, false)); particleManager->setSuckPosition(0, avatar->position); particleManager->setSuckPosition(1, avatar->position + avatar->vel + avatar->vel2); //avatar->vel.getLength2D() /* for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++) { Emitter::addInfluence(ParticleInfluence((*i)->position, 400, 128, true)); } */ /* FOR_ENTITIES (i) { Entity *e = *i; if (e->getEntityType() != ET_AVATAR && e->collideRadius > 0) { Emitter::addInfluence(ParticleInfluence(e->position, 200, e->collideRadius, false)); } } */ } updateParticlePause(); //areEntitiesUnique(); if (controlHintTimer > 0) { controlHintTimer -= dt; if (controlHintTimer < 0) { controlHint_ignoreClear = false; clearControlHint(); } } dsq->continuity.update(dt); StateObject::update(dt); for (ElementUpdateList::iterator e = elementUpdateList.begin(); e != elementUpdateList.end(); e++) { (*e)->update(dt); } int i = 0; for (i = 0; i < dsq->game->getNumPaths(); i++) { dsq->game->getPath(i)->update(dt); } FOR_ENTITIES(j) { (*j)->postUpdate(dt); } FlockEntity::updateFlockData(); updateCurrentVisuals(dt); updateCursor(dt); updateBgSfxLoop(); /* for (int i = 0; i < 2; i++) dsq->spawnBubble(Vector(rand()%800 + core->cameraPos.x, rand()%600 + core->cameraPos.y, -0.05f), Vector(0, 0,0)); */ // spawn bubbles /* const float spawnTime = 0.008; static float bubbleTimer = 0; bubbleTimer += dt; int sx1, sx2, sy1, sy2; int extra = 300; sx1 = core->screenCullX1 - extra; sx2 = core->screenCullX2 + extra; sy1 = core->screenCullY1 - extra; sy2 = core->screenCullY2 + extra; while (bubbleTimer >= spawnTime) { Vector p(sx1 + rand()%(sx2-sx1),sy1 + rand()%(sy2-sy1)); Quad *q = new Quad; q->scale = Vector(0.25,0.25); q->position = p; q->setTexture("bubble"); q->setLife(2); q->setDecayRate(1); q->alpha = 0; q->alpha.interpolateTo(0.4, 1, 1, 1, 1); addRenderObject(q, LR_ELEMENTS3); q->velocity = Vector(((rand()%200)-100)/100.0f, ((rand()%200)-100)/100.0f); q->velocity *= 32; bubbleTimer -= spawnTime; } */ sceneColor.update(dt); sceneColor2.update(dt); sceneColor3.update(dt); dsq->sceneColorOverlay->color = sceneColor * sceneColor2 * sceneColor3; if (bg) { setParallaxTextureCoordinates(bg, 0.3); } if (bg2) { setParallaxTextureCoordinates(bg2, 0.1); } updateInGameMenu(dt); if (avatar && grad && bg && bg2) { //float d = avatar->position.y / float(40000.0); /* Vector top1(0.6, 0.8, 0.65); Vector top2(0.1, 0.2, 0.4); Vector btm1(0.1, 0.2, 0.4); Vector btm2(0, 0, 0.1); */ /* Vector top1(0.5, 0.65, 7); Vector top2(0.2, 0.25, 0.3); Vector btm1(0.2, 0.25, 0.3); Vector btm2(0, 0, 0.1); */ /* // dynamic gradient Vector top1(99/256.0f, 166/256.0f, 170/256.0f); Vector top2(86/256.0f, 150/256.0f, 154/256.0f); Vector btm1(86/256.0f, 150/256.0f, 154/256.0f); Vector btm2(66/256.0f, 109/256.0f, 122/256.0f); btm2 *= 0.75; Vector newtop1(105/256.0f, 190/256.0f, 200/256.0f); grad->makeVertical(newtop1, btm2); */ //grad->makeVertical(top1*(1.0-d) + top2*(d), btm1*(1.0-d) + btm2*(d)); /* float range = 0.5f; float left = 1.0f - range; float v = ((range-(d*range)) + left); bg->color = Vector(v,v,v); bg2->color = Vector(v,v,v); */ } #ifdef AQUARIA_BUILD_SCENEEDITOR { sceneEditor.update(dt); } #endif dsq->emote.update(dt); if (!isPaused()) { timer += dt; while (timer > 1.0f) timer -= 1.0f; halfTimer += dt*0.5f; while (halfTimer > 1.0f) halfTimer -= 1.0f; } if (avatar && (avatar->isEntityDead() || avatar->health <= 0) && core->getNestedMains()==1 && !isPaused()) { dsq->stopVoice(); /* if (runGameOverScript && dsq->runScript("scripts/maps/" + sceneName + ".lua", "gameOver")) { // no game over for you! } else */ if (deathTimer > 0) { deathTimer -= dt; if (deathTimer <= 0) { // run game over script //errorLog("here"); core->enqueueJumpState("GameOver"); } } } if (avatar && avatar->isSinging() && avatar->songInterfaceTimer > 0.5f) { avatar->entityToActivate = 0; avatar->pathToActivate = 0; } if (avatar && core->getNestedMains() == 1 && !isPaused() && !avatar->isSinging() && activation) // && dsq->continuity.form == FORM_NORMAL { dsq->continuity.refreshAvatarData(avatar); Vector bigGlow(3,3); float bigGlowTime = 0.4; bool hadThingToActivate = (avatar->entityToActivate!=0 || avatar->pathToActivate!=0); avatar->entityToActivate = 0; if (avatar->canActivateStuff()) { FOR_ENTITIES(i) { Entity *e = *i; int sqrLen = (dsq->getGameCursorPosition() - e->position).getSquaredLength2D(); if (sqrLen < sqr(e->activationRadius) && (avatar->position-e->position).getSquaredLength2D() < sqr(e->activationRange) && e->activationType == Entity::ACT_CLICK && !e->position.isInterpolating() ) { //if (trace(avatar->position, e->position)) { avatar->entityToActivate = e; dsq->cursorGlow->alpha.interpolateTo(1, 0.2); dsq->cursorBlinker->alpha.interpolateTo(1.0,0.1); if (!hadThingToActivate) { dsq->cursorGlow->scale = Vector(1,1); dsq->cursorGlow->scale.interpolateTo(bigGlow,bigGlowTime,1, -1, 1); } } break; } } } avatar->pathToActivate = 0; //if (!avatar->entityToActivate && !avatar->state.lockedToWall) // make sure you also disable entityToActivate if (dsq->game && dsq->game->avatar->canActivateStuff()) { Path* p = dsq->game->getScriptedPathAtCursor(true); if (p && p->cursorActivation) { Vector diff = p->nodes[0].position - dsq->game->avatar->position; if (p->isCoordinateInside(dsq->game->avatar->position) || diff.getSquaredLength2D() < sqr(PATH_ACTIVATION_RANGE)) { //if (trace(avatar->position, p->nodes[0].position)) { avatar->pathToActivate = p; dsq->cursorGlow->alpha.interpolateTo(1,0.2); dsq->cursorBlinker->alpha.interpolateTo(1,0.2); if (!hadThingToActivate) { dsq->cursorGlow->scale = Vector(1,1); dsq->cursorGlow->scale.interpolateTo(bigGlow,bigGlowTime,1, -1, 1); } } } } } /* if (!hadThingToActivate && (avatar->entityToActivate || avatar->pathToActivate)) { debugLog("Spawning cursor particles"); dsq->spawnParticleEffect("CursorBurst", dsq->getGameCursorPosition()); } */ } if (!activation) { avatar->entityToActivate = 0; avatar->pathToActivate = 0; } if (!avatar->entityToActivate && !avatar->pathToActivate) { dsq->cursorGlow->alpha.interpolateTo(0, 0.2); dsq->cursorBlinker->alpha.interpolateTo(0, 0.1); } if (!isSceneEditorActive()) { if (!isPaused()) waterLevel.update(dt); cameraInterp.update(dt); if (cameraFollow) { Vector dest = getCameraPositionFor(*cameraFollow); if (avatar) { if (avatar->looking && !dsq->game->isPaused()) { Vector diff = avatar->getAim();//dsq->getGameCursorPosition() - avatar->position; diff.capLength2D(600); dest += diff; } else { avatar->looking = 0; } } /* if (avatar) { if (!dsq->game->isPaused() && core->mouse.buttons.middle && !dsq->game->avatar->isSinging() && dsq->game->avatar->isInputEnabled()) { Vector diff = avatar->getAim();//dsq->getGameCursorPosition() - avatar->position; diff.capLength2D(600); avatar->looking = 1; dest += diff; } else { avatar->looking = 0; } } */ if (cameraLerpDelay==0) { //cameraLerpDelay = 0.15; cameraLerpDelay = vars->defaultCameraLerpDelay; } cameraInterp.interpolateTo(dest, cameraLerpDelay); dsq->cameraPos.x = cameraInterp.x; dsq->cameraPos.y = cameraInterp.y; // constrainCamera constrainCamera(); /* if (cam_region) ConstrainToRegion(&ek->cameraPos, cam_region, core->getVirtualWidth()*(core->globalScale.x), core->getVirtualHeight()*(core->globalScale.y)); */ } } } void Game::setElementLayerVisible(int bgLayer, bool v) { core->getRenderObjectLayer(LR_ELEMENTS1+bgLayer)->visible = v; } bool Game::isElementLayerVisible(int bgLayer) { return core->getRenderObjectLayer(LR_ELEMENTS1+bgLayer)->visible; } /* void Game::cameraPanToNode(Path *p, int speed) { cameraFollow = &p->nodes[0].position; } void Game::cameraRestore() { setCameraFollow(avatar); } */ Shot *Game::fireShot(const std::string &bankShot, Entity *firer, Entity *target, const Vector &pos, const Vector &aim, bool playSfx) { Shot *s = 0; if (firer) { s = new Shot; s->firer = firer; if (pos.isZero()) s->position = firer->position; else s->position = pos; if (target) s->setTarget(target); Shot::loadBankShot(bankShot, s); if (!aim.isZero()) s->setAimVector(aim); else { if (target && firer) s->setAimVector(target->position - firer->position); else if (firer) s->setAimVector(firer->getNormal()); else s->setAimVector(Vector(0,1)); } s->updatePosition(); s->fire(playSfx); core->getTopStateData()->addRenderObject(s, LR_PROJECTILES); } return s; } Shot* Game::fireShot(Entity *firer, const std::string &particleEffect, Vector position, bool big, Vector dir, Entity *target, int homing, int velLenOverride, int targetPt) { //sound->playSfx("BasicShot", 255, 0, rand()%100 + 1000); /* DamageType dt; if (firer->getEntityType() == ET_ENEMY) dt = DT_ENEMY_ENERGYBLAST; else if (firer->getEntityType() == ET_AVATAR) dt = DT_AVATAR_ENERGYBLAST; else debugLog("UNDEFINED DAMAGE TYPE!"); int velLen = 900; if (big) velLen += 200; if (velLenOverride != 0) velLen = velLenOverride; Shot *shot; if (big && target) shot = new Shot(dt, firer, position, target, "energyBlast", homing, velLen, 8, 0.1, 4, 2); else { if (homing > 0) shot = new Shot(dt, firer, position, target, "energyBlast", homing, velLen, 5, 0.1, 4, 1); else shot = new Shot(dt, firer, position, 0, "energyBlast", 0, velLen, 5, 0.1, 4, 1); } shot->setParticleEffect(particleEffect); if (big) shot->scale = Vector(1.5, 1.5); //shot->velocity = dsq->getGameCursorPosition() - position; if (dir.x == 0 && dir.y == 0 && target) { shot->velocity = target->position - firer->position; } else { shot->velocity = dir; } if (velLen != 0 && !shot->velocity.isZero()) shot->velocity.setLength2D(velLen); if (firer->getEntityType() == ET_AVATAR && homing && target) { //std::ostringstream os; //os << "targetvel(" << target->vel.x << ", " << target->vel.y << ")"; //debugLog(os.str()); if (!target->vel.isZero() && !target->vel.isNan()) shot->velocity += target->vel; } shot->targetPt = targetPt; //shot->velocity += firer->vel; core->getTopStateData()->addRenderObject(shot, LR_PROJECTILES); return shot; */ debugLog("Old version of Game::fireShot is obsolete"); return 0; } void Game::warpCameraTo(RenderObject *r) { warpCameraTo(r->position); } void Game::warpCameraTo(Vector position) { cameraInterp.stop(); cameraInterp = getCameraPositionFor(position); dsq->cameraPos.x = cameraInterp.x; dsq->cameraPos.y = cameraInterp.y; } void Game::snapCam() { if (cameraFollow) { Vector p = getCameraPositionFor(*cameraFollow); cameraInterp.interpolateTo(p,0); cameraInterp = p; core->cameraPos = p; } } ElementTemplate Game::getElementTemplateForLetter(int i) { float cell = 64.0f/512.0f; //for (int i = 0; i < 27; i++) ElementTemplate t; t.idx = 1024+i; t.gfx = "Aquarian"; int x = i,y=0; while (x >= 6) { x -= 6; y++; } t.tu1 = x*cell; t.tv1 = y*cell; t.tu2 = t.tu1 + cell; t.tv2 = t.tv1 + cell; t.tv2 = 1 - t.tv2; t.tv1 = 1 - t.tv1; std::swap(t.tv1,t.tv2); t.w = 512*cell; t.h = 512*cell; //elementTemplates.push_back(t); return t; } void Game::loadElementTemplates(std::string pack) { stringToLower(pack); /* std::string fn = ("data/"+pack+".xml"); if (!exists(fn)) { loadElementTemplatesDAT(pack); return; } loadElementTemplatesXML(pack); */ elementTemplates.clear(); // HACK: need to uncache things! causes memory leak currently bool doPrecache=false; std::string fn; if (dsq->mod.isActive()) fn = dsq->mod.getPath() + "tilesets/" + pack + ".txt"; else fn = "data/tilesets/" + pack + ".txt"; if (lastTileset == fn) { doPrecache=false; } lastTileset = fn; if (!exists(fn)) { errorLog ("Could not open element template pack [" + fn + "]"); return; } if (doPrecache) { tileCache.clean(); } InStream in(fn.c_str()); std::string line; while (std::getline(in, line)) { int idx=-1, w=-1, h=-1; std::string gfx; std::istringstream is(line); is >> idx >> gfx >> w >> h; ElementTemplate t; t.idx = idx; t.gfx = gfx; if (w==0) w=-1; if (h==0) h=-1; t.w = w; t.h = h; elementTemplates.push_back(t); if (doPrecache) tileCache.precacheTex(gfx); } in.close(); for (int i = 0; i < elementTemplates.size(); i++) { for (int j = i; j < elementTemplates.size(); j++) { if (elementTemplates[i].idx > elementTemplates[j].idx) { std::swap(elementTemplates[i], elementTemplates[j]); } } } for (int i = 0; i < 27; i++) { elementTemplates.push_back(getElementTemplateForLetter(i)); } } void Game::clearGrid(int v) { // ensure that grid is really a byte-array compile_assert(sizeof(grid) == MAX_GRID * MAX_GRID); memset(grid, v, sizeof(grid)); } void Game::resetFromTitle() { overrideMusic = ""; } void Game::setGrid(ElementTemplate *et, Vector position, float rot360) { for (int i = 0; i < et->grid.size(); i++) { TileVector t(position); /* std::ostringstream os; os << "opos(" << position.x << ", " << position.y << ") centre(" << t.x << ", " << t.y << ")"; debugLog(os.str()); */ int x = et->grid[i].x; int y = et->grid[i].y; if (rot360 >= 0 && rot360 < 90) { } else if (rot360 >= 90 && rot360 < 180) { int swap = y; y = x; x = swap; x = -x; } else if (rot360 >= 180 && rot360 < 270) { x = -x; y = -y; } else if (rot360 >= 270 && rot360 < 360) { int swap = y; y = x; x = swap; y = -y; } TileVector s(t.x+x, t.y+y); //Vector v = Vector(position.x+et->grid[i].x*TILE_SIZE, position.y+et->grid[i].y*TILE_SIZE); setGrid(s, 1); } } void Game::removeState() { const float fadeTime = 0.25; dsq->toggleVersionLabel(false); dsq->subtitlePlayer.hide(fadeTime); dropIngrNames.clear(); debugLog("Entering Game::removeState"); shuttingDownGameState = true; debugLog("avatar->endOfGameState()"); if (avatar) { avatar->endOfGameState(); } #ifdef AQUARIA_BUILD_SCENEEDITOR debugLog("toggle sceneEditor"); if (sceneEditor.isOn()) sceneEditor.toggle(false); #endif debugLog("gameSpeed"); dsq->gameSpeed.interpolateTo(1, 0); debugLog("bgSfxLoop"); dsq->loops.stopAll(); debugLog("toggleCursor"); dsq->toggleCursor(0, fadeTime); if (!isInGameMenu()) avatar->disableInput(); debugLog("control hint"); controlHint_ignoreClear = false; clearControlHint(); dsq->overlay->color = 0; //dsq->overlay->alpha = 0; dsq->overlay->alpha.interpolateTo(1, fadeTime); dsq->main(fadeTime); /* // to block on voice overs while (dsq->isStreamingVoice()) { dsq->main(FRAME_TIME); } */ // AFTER TRANSITION: dsq->rumble(0,0,0); dsq->sound->clearFadingSfx(); ingredients.clear(); core->particlesPaused = false; elementUpdateList.clear(); if (core->afterEffectManager) { //core->afterEffectManager->blurShader.setMode(0); core->afterEffectManager->setActiveShader(AS_NONE); } dsq->setCursor(CURSOR_NORMAL); dsq->darkLayer.toggle(0); dsq->shakeCamera(0,0); if (core->afterEffectManager) core->afterEffectManager->clear(); dsq->getRenderObjectLayer(LR_BLACKGROUND)->update = true; //core->sound->fadeOut(1); if (saveFile) { delete saveFile; saveFile = 0; } /* if (core->getEnqueuedJumpState() != "Game") { this->overrideMusic = ""; } */ dsq->continuity.zoom = core->globalScale; dsq->game->toggleOverrideZoom(false); dsq->game->avatar->myZoom.stop(); dsq->globalScale.stop(); dsq->game->avatar->myZoom = Vector(1,1); dsq->globalScale = Vector(1,1); for (int i = 0; i < getNumPaths(); i++) { Path *p = getPath(i); p->destroy(); delete p; } clearPaths(); StateObject::removeState(); dsq->clearElements(); dsq->clearEntities(); avatar = 0; //items.clear(); #ifdef AQUARIA_BUILD_SCENEEDITOR sceneEditor.shutdown(); #endif cameraFollow = 0; core->cameraPos = Vector(0,0); sceneColor.stop(); controlHint_mouseLeft = controlHint_mouseRight = controlHint_mouseMiddle = controlHint_mouseBody = controlHint_bg = controlHint_image = 0; controlHint_text = 0; miniMapRender = 0; gridRender = 0; worldMapRender = 0; //core->sound->stopStreamingOgg(); // optimize:: clear layers /* int c = 0; for (DSQ::RenderObjectLayers::iterator i = core->renderObjectLayers.begin(); i != core->renderObjectLayers.end(); i++) { DSQ::RenderObjects *r = &(*i); //if (c <= LR_HUD) if (c<=LR_PARTICLES) r->clear(); c++; } */ clearObsRows(); debugLog("killAllShots"); Shot::killAllShots(); Shot::clearShotGarbage(); // make sure there are no pointers left (would lead to a crash on shutdown otherwise) debugLog("killAllBeams"); Beam::killAllBeams(); debugLog("killAllWebs"); Web::killAllWebs(); debugLog("killAllSpores"); Spore::killAllSpores(); debugLog("clear Local Sounds"); core->sound->clearLocalSounds(); active = false; dsq->routeShoulder = true; debugLog("Game::removeState Done"); //core->sound->stopAllSounds(); } bool Game::isActive() { return active; } bool isBoxIn(Vector pos1, Vector sz1, Vector pos2, Vector sz2) { if ((pos1.x - sz1.x > pos2.x-sz2.x) && (pos1.x - sz1.x < pos2.x+sz2.x)) { if ((pos1.y - sz1.y > pos2.y-sz2.y) && (pos1.y - sz1.y < pos2.y+sz2.y)) return true; else if ((pos1.y + sz1.y > pos2.y-sz2.y) && (pos1.y + sz1.y < pos2.y+sz2.y)) return true; } else if ((pos1.x + sz1.x > pos2.x-sz2.x) && (pos1.x + sz1.x < pos2.x+sz2.x)) { if ((pos1.y - sz1.y > pos2.y-sz2.y) && (pos1.y - sz1.y < pos2.y+sz2.y)) return true; else if ((pos1.y + sz1.y > pos2.y-sz2.y) && (pos1.y + sz1.y < pos2.y+sz2.y)) return true; } return false; } Vector Game::getClosestPointOnTriangle(Vector a, Vector b, Vector c, Vector p) { Vector Rab = getClosestPointOnLine(a, b, p); Vector Rbc = getClosestPointOnLine(b, c, p); Vector Rca = getClosestPointOnLine(c, a, p); int RabDist = Rab.getSquaredLength2D(); int RbcDist = Rab.getSquaredLength2D(); int RcaDist = Rca.getSquaredLength2D(); if (RabDist < RbcDist && RabDist < RcaDist) { return Rab; } if (RbcDist < RabDist && RbcDist < RcaDist) return Rbc; return Rca; } Vector Game::getClosestPointOnLine(Vector a, Vector b, Vector p) { // Determine t (the length of the vector from ‘a’ to ‘p’) Vector c = p - a; Vector V = b-a; V.normalize2D(); float d = (a-b).getLength2D(); float t = V.dot(c); // Check to see if ‘t’ is beyond the extents of the line segment if (t < 0) return a; if (t > d) return b; // Return the point between ‘a’ and ‘b’ //set length of V to t; V.setLength2D(t); return a + V; } bool Game::collideCircleWithGrid(const Vector& position, int r) { Vector tile = position; TileVector t(tile); tile.x = t.x; tile.y = t.y; float hsz = TILE_SIZE/2; int xrange=1,yrange=1; xrange = (r/TILE_SIZE)+1; yrange = (r/TILE_SIZE)+1; for (int x = tile.x-xrange; x <= tile.x+xrange; x++) { for (int y = tile.y-yrange; y <= tile.y+yrange; y++) { int v = this->getGrid(TileVector(x, y)); if (v != 0) { //if (tile.x == x && tile.y == y) return true; TileVector t(x, y); lastCollidePosition = t.worldVector(); //if (tile.x == x && tile.y == y) return true; float rx = (x*TILE_SIZE)+TILE_SIZE/2; float ry = (y*TILE_SIZE)+TILE_SIZE/2; float rSqr; lastCollideTileType = (ObsType)v; rSqr = sqr(position.x - (rx+hsz)) + sqr(position.y - (ry+hsz)); if (rSqr < sqr(r)) return true; rSqr = sqr(position.x - (rx-hsz)) + sqr(position.y - (ry+hsz)); if (rSqr < sqr(r)) return true; rSqr = sqr(position.x - (rx-hsz)) + sqr(position.y - (ry-hsz)); if (rSqr < sqr(r)) return true; rSqr = sqr(position.x - (rx+hsz)) + sqr(position.y - (ry-hsz)); if (rSqr < sqr(r)) return true; if (position.x > rx-hsz && position.x < rx+hsz) { if (fabsf(ry - position.y) < r+hsz) { return true; } } if (position.y > ry-hsz && position.y < ry+hsz) { if (fabsf(rx - position.x) < r+hsz) { return true; } } } } } lastCollideTileType = OT_EMPTY; return false; } bool Game::collideBoxWithGrid(const Vector& position, int hw, int hh) { Vector tile = position; TileVector t(tile); tile.x = t.x; tile.y = t.y; float hsz = TILE_SIZE/2; int xrange=1,yrange=1; xrange = (hw/TILE_SIZE)+1; yrange = (hh/TILE_SIZE)+1; for (int x = tile.x-xrange; x <= tile.x+xrange; x++) { for (int y = tile.y-yrange; y <= tile.y+yrange; y++) { int v = this->getGrid(TileVector(x, y)); if (v == 1) { if (tile.x == x && tile.y == y) return true; float rx = (x*TILE_SIZE)+TILE_SIZE/2; float ry = (y*TILE_SIZE)+TILE_SIZE/2; if (isBoxIn(position, Vector(hw, hh), Vector(rx, ry), Vector(hsz, hsz))) { return true; } if (isBoxIn(Vector(rx, ry), Vector(hsz, hsz), position, Vector(hw, hh))) { return true; } } } } return false; } void Game::learnedRecipe(Recipe *r, bool effects) { if (nocasecmp(dsq->getTopStateData()->name,"Game")==0 && !applyingState) { std::ostringstream os; os << dsq->continuity.stringBank.get(23) << " " << r->resultDisplayName << " " << dsq->continuity.stringBank.get(24); IngredientData *data = dsq->continuity.getIngredientDataByName(r->result); if (data) { if (effects) { dsq->game->setControlHint(os.str(), 0, 0, 0, 3, std::string("gfx/ingredients/") + data->gfx); } } /* errorLog(os.str()); */ } }