#include "game.h" #include "player.h" #include "projectile.h" #include "gameManager.h" #include "activeGameState.h" #include "inGameAppState.h" #include "concreteGuiManager.h" #include "defConfigs.h" #include #include #include #include #include #include namespace battleship{ using namespace std; using namespace vb01; using namespace gameBase; static Game *game = nullptr; Game* Game::getSingleton(){ if(!game) game = new Game(); return game; } void Game::resetLuaGameObjects(){ sol::state_view SOL_LUA_VIEW = generateView(); SOL_LUA_VIEW.script("game.players = {}"); for(int i = 0; i < players.size(); i++) SOL_LUA_VIEW["game"]["players"][i + 1] = players[i]; for(int i = 0; i < players.size(); i++) if(players[i]->isCpuPlayer()){ string plStr = "game.players[" + to_string(i + 1) + "]"; SOL_LUA_VIEW.script("executeBtNode(" + plStr + ", " + plStr + ".behaviour)"); } } void Game::endGame(bool victory){ ended = true; StateManager *sm = GameManager::getSingleton()->getStateManager(); sm->dettachAppState(sm->getAppStateByType(AppStateType::ACTIVE_STATE)); togglePause(); string endGameScreen = (victory ? "victory.lua" : "defeat.lua"); ConcreteGuiManager::getSingleton()->readLuaScreenScript(endGameScreen); } void Game::update(){ resetLuaGameObjects(); int numPlayersWithUnits = 0; for(int i = 0; i < players.size(); i++){ players[i]->update(); if(players[i]->getNumUnits() > 0) numPlayersWithUnits++; } ActiveGameState *activeState = (ActiveGameState*)GameManager::getSingleton()->getStateManager()->getAppStateByType(AppStateType::ACTIVE_STATE); Player *mainPlayer = (activeState ? activeState->getPlayer() : nullptr); if(mainPlayer && !ended){ int numMainPlayerUnits = mainPlayer->getNumUnits(); if(numMainPlayerUnits > 0 && numPlayersWithUnits == 1) endGame(true); else if(numMainPlayerUnits == 0) endGame(false); } for(int i = 0; i < fx.size(); i++){ if(getTime() - fx[i].initTime > fx[i].vfxTime) removeFx(i, true); if(getTime() - fx[i].initTime > fx[i].sfxTime) removeFx(i, false); } } //TODO remove the bool flag void Game::removeFx(int id, bool vfx){ const sf::SoundBuffer *buffer = fx[id].sfx->getBuffer(); if(!vfx){ fx[id].sfx->stop(); delete fx[id].sfx; delete buffer; fx.erase(fx.begin() + id); } if(fx[id].peNode && vfx){ Root::getSingleton()->getRootNode()->dettachChild(fx[id].peNode); delete fx[id].peNode; fx[id].peNode = nullptr; } } void Game::removeAllElements(){ resetLuaGameObjects(); while(!players.empty()){ delete players[0]; players.erase(players.begin()); } ended = false; paused = false; } void Game::togglePause(){ GameManager *gm = GameManager::getSingleton(); ConcreteGuiManager *guiManager = ConcreteGuiManager::getSingleton(); ActiveGameState *activeState = ((InGameAppState*)gm->getStateManager()->getAppStateByType(AppStateType::IN_GAME_STATE))->getActiveState(); if (!paused) { gm->getStateManager()->dettachAppState(activeState); guiManager->readLuaScreenScript("gamePaused.lua", activeState->getButtons()); } else { for(string f : configData::scripts) generateView().script_file(gm->getPath() + f); guiManager->readLuaScreenScript("inGame.lua", activeState->getButtons()); string mp = generateView()["modelPrefix"]; AssetManager::getSingleton()->load(gm->getPath() + mp, true); vector gameObjs; for(Player *pl : Game::getSingleton()->getPlayers()){ for(Unit *u : pl->getUnits()) gameObjs.push_back((GameObject*)u); for(Projectile *proj : pl->getProjectiles()) gameObjs.push_back((GameObject*)proj); for(ResourceDeposit *dep : pl->getResourceDeposits()) gameObjs.push_back((GameObject*)dep); } for(GameObject *obj : gameObjs) obj->reinit(); gm->getStateManager()->attachAppState(activeState); } paused = !paused; } void Game::explode(Vector3 pos, int damage, float radius, sf::Sound *explosionSfx){ if(!(damage == 0 || radius == 0)) for(Player *pl : players){ for(Unit *un : pl->getUnits()){ float distance = un->getPos().getDistanceFrom(pos); if(distance < radius) un->takeDamage(int(damage * (1.f - distance / radius))); } } Root *root = Root::getSingleton(); const int numFrames = 1; string p[numFrames]; for(int i = 0; i < numFrames; i++) p[i] = GameManager::getSingleton()->getPath() + "Textures/Explosion/explosion07.png"; Texture *tex = new Texture(p, numFrames, false); Material *mat = new Material(root->getLibPath() + "particle"); mat->addTexUniform("tex", tex, true); ParticleEmitter *pe = new ParticleEmitter(1); pe->setMaterial(mat); pe->setLowLife(3); pe->setHighLife(3); pe->setSize(10 * Vector2::VEC_IJ); pe->setSpeed(0); Node *node = new Node(pos + Vector3(0, 2, 0)); node->attachParticleEmitter(pe); node->lookAt(Vector3::VEC_J, Vector3::VEC_K); root->getRootNode()->attachChild(node); Fx fx(50, 2500, explosionSfx, node); fx.activate(); addFx(fx); } void Game::changeUnitPlayer(Unit *unit, Player *newPlayer){ Player *oldPlayer = unit->getPlayer(); vector &oldPlayerUnits = oldPlayer->getUnits(); int oldId = -1; for(int i = 0; i < oldPlayerUnits.size(); i++) if(oldPlayerUnits[i] == unit){ oldId = i; break; } oldPlayerUnits.erase(oldPlayerUnits.begin() + oldId); newPlayer->addUnit(unit); unit->setPlayer(newPlayer); unit->halt(); } vector Game::parseTechTable(int tid, string key, string numVarKey, string varKey){ sol::state_view SOL_LUA_VIEW = generateView(); SOL_LUA_VIEW.script(numVarKey + " = #" + key + "[" + to_string(tid + 1) + "]." + varKey); int numVar = SOL_LUA_VIEW[numVarKey]; sol::table techTable = SOL_LUA_VIEW[key][tid + 1]; vector varVec; for(int i = 0; i < numVar; i++) varVec.push_back(techTable[varKey][i + 1]); return varVec; } //TODO clean this method up void Game::initTechnologies(){ technologies.clear(); sol::state_view SOL_LUA_VIEW = generateView(); string techKey = "technologies"; SOL_LUA_VIEW.script("numTechs = #" + techKey); int numTechs = SOL_LUA_VIEW["numTechs"]; for(int i = 0; i < numTechs; i++){ sol::table techTable = SOL_LUA_VIEW[techKey][i + 1]; Technology t; t.cost = techTable["cost"]; t.name = techTable["name"]; t.icon = techTable["icon"]; t.description = techTable["description"]; t.parents = parseTechTable(i, techKey, "numParents", "parents"); t.abilities = parseTechTable(i, techKey, "numAbilities", "abilities"); technologies.push_back(t); } techKey = "abilities"; SOL_LUA_VIEW.script("numAbilities = #" + techKey); int numAbilities = SOL_LUA_VIEW["numAbilities"]; for(int i = 0; i < numAbilities; i++){ sol::table techTable = SOL_LUA_VIEW[techKey][i + 1]; Ability ability; ability.type = techTable["type"]; ability.ammount = techTable["ammount"].get_or(0.0); ability.gameObjType = techTable["gameObjType"]; ability.gameObjIds = parseTechTable(i, techKey, "numGameObjIds", "gameObjIds"); abilities.push_back(ability); } } float Game::calcAbilFromTech(Ability::Type type, vector techResearch, int gameObjType, int unitId){ float ammount = 0; for(int techId : techResearch) for(int abilId : technologies[techId].abilities) if( abilities[abilId].type == type && abilities[abilId].gameObjType == gameObjType && find(abilities[abilId].gameObjIds.begin(), abilities[abilId].gameObjIds.end(), unitId) != abilities[abilId].gameObjIds.end() ){ ammount += abilities[abilId].ammount; } return ammount; } bool Game::isUnitUnlocked(vector techResearch, int unitId){ for(int techId : techResearch){ for(int abilId : technologies[techId].abilities){ vector ids = abilities[abilId].gameObjIds; if(find(ids.begin(), ids.end(), unitId) != ids.end()) return true; } } return false; } vector Game::findTradeOffers(Player *pl1, Player *pl2){ vector offers; for(TradeOffer *to : tradeOffers) if((to->initPlayer == pl1 || to->recPlayer == pl1) && (to->initPlayer == pl2 || to->recPlayer == pl2)) offers.push_back(to); return offers; } }