diff --git a/Assets/Scripts/GameObjects/Units/unitData.lua b/Assets/Scripts/GameObjects/Units/unitData.lua index 50977c5..73426ff 100644 --- a/Assets/Scripts/GameObjects/Units/unitData.lua +++ b/Assets/Scripts/GameObjects/Units/unitData.lua @@ -145,6 +145,7 @@ units = { unitClass = UnitClass.WAR_MECH, unitType = UnitType.LAND, armor = {ArmorType.MECHANIC}, + maxUnevenness = .5, isVehicle = true, health = 500, buildTime = 1000, @@ -200,6 +201,7 @@ units = { unitClass = UnitClass.TANK, unitType = UnitType.LAND, armor = {ArmorType.STEEL}, + maxUnevenness = .5, isVehicle = true, alignToSurface = true, health = 500, @@ -257,6 +259,7 @@ units = { unitClass = UnitClass.ARTILLERY, unitType = UnitType.LAND, armor = {ArmorType.MECHANIC}, + maxUnevenness = .5, alignToSurface = true, isVehicle = true, health = 500, @@ -301,6 +304,7 @@ units = { unitClass = UnitClass.ENGINEER, unitType = UnitType.HOVER, armor = {ArmorType.MECHANIC}, + maxUnevenness = .5, isVehicle = true, health = 500, hackRange = 200, @@ -326,6 +330,7 @@ units = { { unitClass = UnitClass.TRANSPORT, unitType = UnitType.HOVER, + maxUnevenness = .5, alignToSurface = true, isVehicle = true, health = 500, @@ -353,6 +358,7 @@ units = { unitClass = UnitClass.TRANSPORT, unitType = UnitType.HOVER, armor = {ArmorType.MECHANIC}, + maxUnevenness = .5, alignToSurface = true, isVehicle = true, health = 500, @@ -385,6 +391,7 @@ units = { unitClass = UnitClass.RESOURCE_ROVER, unitType = UnitType.HOVER, armor = {ArmorType.CAST}, + maxUnevenness = .5, alignToSurface = true, capacity = 3000, loadRate = 1, @@ -931,6 +938,7 @@ units = { }, unitClass = UnitClass.LAND_FACTORY, unitType = UnitType.LAND, + maxUnevenness = .5, isVehicle = false, health = 500, buildTime = 1000, @@ -972,6 +980,7 @@ units = { {buttonType = ButtonType.BUY_RESEARCH, name = 'Buy rsch', trigger = 75}, {buttonType = ButtonType.SELL_RESEARCH, name = 'Sell rsch', trigger = 76} }, + maxUnevenness = .5, isVehicle = false, health = 500, buildTime = 1000, @@ -990,6 +999,7 @@ units = { { unitClass = UnitClass.LAB, unitType = UnitType.LAND, + maxUnevenness = .5, abilityButtons = {{buttonType = ButtonType.ACTIVE_GAME_STATE, name = 'Tech tree', guiScreen = 'techTree.lua'}}, isVehicle = false, health = 500, @@ -1056,6 +1066,7 @@ units = { }, unitClass = UnitClass.POINT_DEFENSE, unitType = UnitType.LAND, + maxUnevenness = .5, isVehicle = false, health = 500, buildTime = 1000, @@ -1075,6 +1086,7 @@ units = { { unitClass = UnitClass.EXTRACTOR, unitType = UnitType.LAND, + maxUnevenness = .5, isVehicle = false, health = 500, buildTime = 1000, @@ -1095,6 +1107,7 @@ units = { { unitClass = UnitClass.REFINERY, unitType = UnitType.LAND, + maxUnevenness = .5, isVehicle = false, health = 500, buildTime = 1000, @@ -1114,6 +1127,7 @@ units = { buildableUnits = {{id = UnitId.ENGINEER, buildable = true, trigger = 69}}, unitClass = UnitClass.FORT, unitType = UnitType.LAND, + maxUnevenness = .5, isVehicle = false, health = 1000, buildTime = 1000, diff --git a/activeGameState.cpp b/activeGameState.cpp index 66ac08c..ecede1c 100755 --- a/activeGameState.cpp +++ b/activeGameState.cpp @@ -311,10 +311,8 @@ namespace battleship{ if(targets.empty()) castRayToTerrain(); if(!buildableStructSelected) - for(int i = 0; i < selectedUnits.size(); i++){ - fc->addGameObjectFrame(GameObjectFrame(selectedUnits[i]->getId(), GameObject::Type::UNIT)); - fc->placeGameObjectFrame(fc->getNumGameObjectFrames() - 1, targets[0].pos, selectedUnits[i]->getWidth(), selectedUnits[i]->getLength()); - } + for(int i = 0; i < selectedUnits.size(); i++) + fc->addGameObjectFrame(GameObjectFrame(selectedUnits[i]->getId(), GameObject::Type::UNIT, selectedUnits[i], targets[0].pos)); selectingDestOrient = true; fc->setRotating(true); diff --git a/external/vb01 b/external/vb01 index 8acc008..d4d188e 160000 --- a/external/vb01 +++ b/external/vb01 @@ -1 +1 @@ -Subproject commit 8acc008fa42cd6f585d71785246c6be410520a27 +Subproject commit d4d188eef722eed15a3b4c7db07c3fc9aab92937 diff --git a/gameObject.cpp b/gameObject.cpp index 23fb3ce..5904786 100644 --- a/gameObject.cpp +++ b/gameObject.cpp @@ -104,7 +104,12 @@ namespace battleship{ } void GameObject::initProperties(){ - sol::table sizeTable = generateView()[GameObject::getGameObjTableName()][id + 1]["size"]; + sol::table objTable = generateView()[GameObject::getGameObjTableName()][id + 1]; + sol::optional maxUnevOpt = objTable["maxUnevenness"]; + + if(maxUnevOpt != sol::nullopt) maxUnevenness = objTable["maxUnevenness"]; + + sol::table sizeTable = objTable["size"]; width = sizeTable["x"]; height = sizeTable["y"]; length = sizeTable["z"]; diff --git a/gameObject.h b/gameObject.h index e88e899..aeb501c 100644 --- a/gameObject.h +++ b/gameObject.h @@ -30,6 +30,7 @@ namespace battleship{ static sf::Sound* prepareSfx(sf::SoundBuffer*, std::string); bool pointWithinObj(vb01::Vector3, float = 0, float = 0, bool = false, float = 0); void changePlayer(Player *newPlayer); + inline float getMaxUnevenness(){return maxUnevenness;} inline vb01::Vector2 getScreenPos(){return screenPos;} inline vb01::Vector3 getCorner(int i){return corners[i];} inline bool isSelectable(){return selectable;} @@ -69,7 +70,7 @@ namespace battleship{ vb01::Vector2 screenPos; vb01::Quaternion rot; bool selectable = false, debugging = false, remove = false; - float width, height, length; + float width, height, length, maxUnevenness; }; } diff --git a/gameObjectFrame.h b/gameObjectFrame.h index f9b5924..5a249d2 100644 --- a/gameObjectFrame.h +++ b/gameObjectFrame.h @@ -10,13 +10,21 @@ namespace battleship{ struct GameObjectFrame : public GameObject{ enum Status{PLACEABLE, NOT_PLACEABLE, PLACED}; - GameObjectFrame(int i, GameObject::Type t, vb01::Vector3 pos = vb01::Vector3::VEC_ZERO, vb01::Quaternion rot = vb01::Quaternion::QUAT_W) : GameObject(t, i, nullptr, pos, rot) { + GameObjectFrame(int i, GameObject::Type t, Unit *ou = nullptr, vb01::Vector3 pos = vb01::Vector3::VEC_ZERO, vb01::Quaternion rot = vb01::Quaternion::QUAT_W) : + originalUnit(ou), + GameObject(t, i, nullptr, pos, rot) + { initModel(false); + initProperties(); + placeAt(pos); + orientAt(rot); } ~GameObjectFrame(){} void destroy(){destroyModel();} + inline Unit* getOriginalUnit(){return originalUnit;} Status status; + Unit *originalUnit = nullptr; }; } diff --git a/gameObjectFrameController.cpp b/gameObjectFrameController.cpp index 51e6020..0311bfa 100644 --- a/gameObjectFrameController.cpp +++ b/gameObjectFrameController.cpp @@ -34,9 +34,11 @@ namespace battleship{ return gameObjectFrameController; } - void GameObjectFrameController::paintSelect(Vector3 rowEnd, float width, float length){ + void GameObjectFrameController::paintSelect(Vector3 rowEnd){ Vector3 rowDir = rowEnd - paintSelectRowStart; float lenRow = rowDir.getLength(); + float width = gameObjectFrames[0].getWidth(); + float length = gameObjectFrames[0].getLength(); float hypothenuse = sqrt(width * width + length * length); int numStructsInRow = int(lenRow / hypothenuse); @@ -51,79 +53,130 @@ namespace battleship{ buildDir = gameObjectFrames[1].getModel()->getPosition() - gameObjectFrames[0].getModel()->getPosition(); Vector3 pos = paintSelectRowStart + buildDir.norm() * hypothenuse * gameObjectFrames.size(); - addGameObjectFrame(GameObjectFrame(structureId, GameObject::Type::UNIT, pos)); + addGameObjectFrame(GameObjectFrame(structureId, GameObject::Type::UNIT, nullptr, pos)); } } - //TODO specify what to snap the frame to - void GameObjectFrameController::snapToObj(GameObjectFrame &s, GameObject::Type type, int unitId, float maxDist){ - if(s.getType() == GameObject::Type::UNIT && s.getId() == unitId){ - s.status = GameObjectFrame::NOT_PLACEABLE; - Player *civPl = Game::getSingleton()->getCivilianPlayer(); + void GameObjectFrameController::snapToObj(GameObjectFrame &s, vector snapTargets, float maxDist){ + s.status = GameObjectFrame::NOT_PLACEABLE; - for(ResourceDeposit *dep : civPl->getResourceDeposits()){ - Vector3 depPos = dep->getPos(); + for(GameObject *st : snapTargets){ + Vector3 stPos = st->getPos(); - if(!dep->getExtractor() && s.getPos().getDistanceFrom(depPos) < maxDist){ - s.status = GameObjectFrame::PLACEABLE; - s.placeAt(depPos); - break; - } + if(s.getPos().getDistanceFrom(stPos) < maxDist){ + s.status = GameObjectFrame::PLACEABLE; + s.placeAt(stPos); + checkPlacement(s); + break; } } } - //TODO implement terrain evenness check - //TODO factor out literal values //TODO fix which unit frames light green or red - void GameObjectFrameController::placeGameObjectFrame(int id, Vector3 newPos, float width, float length){ + void GameObjectFrameController::checkPlacement(GameObjectFrame &s){ Map *map = Map::getSingleton(); MeshData meshData = map->getNodeParent()->getChild(0)->getMesh(0)->getMeshBase(); MeshData::Vertex *verts = meshData.vertices; int numVerts = 3 * meshData.numTris; - float maxUnevenness = .5, unevenness = 0; - bool placeable = true; + s.status = GameObjectFrame::PLACEABLE; - for(int i = 0; i < numVerts; i++){ - float diffX = fabs(newPos.x - verts[i].pos->x); - float diffY = fabs(newPos.y - verts[i].pos->y); - float diffZ = fabs(newPos.z - verts[i].pos->z); + if(s.getMaxUnevenness() > 0) + for(int i = 0; i < numVerts; i++){ + float diffX = fabs(s.getPos().x - verts[i].pos->x); + float diffY = fabs(s.getPos().y - verts[i].pos->y); + float diffZ = fabs(s.getPos().z - verts[i].pos->z); - if(diffX < 0.5 * width && diffZ < 0.5 * length && diffY > unevenness){ - unevenness = diffY; - - if(unevenness > maxUnevenness){ - placeable = false; + if(diffX < 0.5 * s.getWidth() && diffZ < 0.5 * s.getLength() && diffY > s.getMaxUnevenness()){ + s.status = GameObjectFrame::NOT_PLACEABLE; break; } } + + vector units; + + for(Player *player : Game::getSingleton()->getPlayers(true)){ + vector u = player->getUnits(); + units.insert(units.end(), u.begin(), u.end()); } - GameObjectFrame &s = gameObjectFrames[id]; - s.placeAt(newPos); + for(Unit *unit : units){ + if(unit == s.getOriginalUnit()) continue; - snapToObj(s, GameObject::Type::UNIT, 20, 3); + Vector3 gm1Pos = s.getPos(); + Vector3 gm1Dir = s.getDirVec(); + gm1Dir = Vector3(gm1Dir.x, 0, gm1Dir.z).norm(); - Vector4 color; + Vector3 gm1Left = s.getLeftVec(); + gm1Left = Vector3(gm1Left.x, 0, gm1Left.z).norm(); - if(placeable){ - s.status = GameObjectFrame::PLACEABLE; - color = Vector4(0, 1, 0, 1); + Vector3 gm2Pos = unit->getPos(); + + Vector3 gm2Dir = unit->getDirVec(); + gm2Dir = Vector3(gm2Dir.x, 0, gm2Dir.z).norm(); + + Vector3 gm2Left = unit->getLeftVec(); + gm2Left = Vector3(gm2Left.x, 0, gm2Left.z).norm(); + + bool intersects = rectanglesIntersect( + Vector2(gm1Pos.x, gm1Pos.z), + Vector2(gm1Dir.x, gm1Dir.z), + Vector2(gm1Left.x, gm1Left.z), + Vector2(s.getWidth(), s.getLength()), + Vector2(gm2Pos.x, gm2Pos.z), + Vector2(gm2Dir.x, gm2Dir.z), + Vector2(gm2Left.x, gm2Left.z), + Vector2(unit->getWidth(), unit->getLength()) + ); + + if(intersects){ + s.status = GameObjectFrame::NOT_PLACEABLE; + break; + } } - else{ - s.status = GameObjectFrame::NOT_PLACEABLE; - color = Vector4(1, 0, 0, 1); - } - - Material *mat = s.getModel()->getMaterial(); - mat->setVec4Uniform("diffuseColor", color); } - void GameObjectFrameController::updatePlacement(){ - for(GameObjectFrame &frame : gameObjectFrames) - frame.update(); + void GameObjectFrameController::shiftVerticalPlacement(){ + if(!minDepthCalculated){ + Map *map = Map::getSingleton(); + Node *nodeParent = map->getNodeParent(); + Vector3 cellSize = map->getCellSize(), waterBodyPos; + bool inWater = false; + + for(int i = 1; i < nodeParent->getNumChildren(); i++){ + Vector3 wPos = nodeParent->getChild(i)->getPosition(); + Vector3 wSize = ((Quad*)nodeParent->getChild(i)->getMesh(0))->getSize(); + + if(fabs(wPos.x - placementPos.x) < .5 * wSize.x && fabs(wPos.z - placementPos.z) < .5 * wSize.y){ + waterBodyPos = wPos; + inWater = true; + break; + } + } + if(!inWater) return; + + vector res = map->raycastTerrain( + Vector3(placementPos.x, 100, placementPos.z), + -Vector3::VEC_J, + false + ); + + vector &cells = map->getCells(); + int cid = map->getCellId(placementPos, false); + int numSubmarineCells = cells[cid].underWaterCellIds.size(); + maxDepth = cells[cid].pos.y; + minDepth = (numSubmarineCells > 0 ? cells[cells[cid].underWaterCellIds[numSubmarineCells - 1]].pos.y : maxDepth) - .5 * cellSize.y; + minDepthCalculated = true; + } + else{ + ActiveGameState *activeState = (ActiveGameState*)(GameManager::getSingleton()->getStateManager()->getAppStateByType((int)AppStateType::ACTIVE_STATE)); + float newDepth = minDepth + activeState->getDepth() * (maxDepth - minDepth); + placementPos.y = newDepth; + } + } + + void GameObjectFrameController::update(){ Map *map = Map::getSingleton(); Vector3 startPos = Root::getSingleton()->getCamera()->getPosition(); Vector3 endPos = screenToSpace(getCursorPos()); @@ -131,71 +184,38 @@ namespace battleship{ if(results.empty()) return; - float width, length; + if(paintSelecting) paintSelect(results[0].pos); - if(paintSelecting){ - sol::table sizeTable = generateView()[gameObjectFrames[0].getGameObjTableName()][gameObjectFrames[0].getId() + 1]["size"]; - width = sizeTable["x"], length = sizeTable["z"]; - paintSelect(results[0].pos, width, length); - } + if(placingVertically) shiftVerticalPlacement(); + else if(placingOnSurface) placementPos = results[0].pos; - if(placingVertically){ - if(!minDepthCalculated){ - placementPos = results[0].pos; - - Node *nodeParent = map->getNodeParent(); - Vector3 cellSize = map->getCellSize(), waterBodyPos; - bool inWater = false; - - for(int i = 1; i < nodeParent->getNumChildren(); i++){ - Vector3 wPos = nodeParent->getChild(i)->getPosition(); - Vector3 wSize = ((Quad*)nodeParent->getChild(i)->getMesh(0))->getSize(); - - if(fabs(wPos.x - placementPos.x) < .5 * wSize.x && fabs(wPos.z - placementPos.z) < .5 * wSize.y){ - waterBodyPos = wPos; - inWater = true; - break; - } - } - - if(!inWater) return; - - vector res = map->raycastTerrain( - Vector3(placementPos.x, 100, placementPos.z), - -Vector3::VEC_J, - false - ); - - vector &cells = map->getCells(); - int cid = map->getCellId(placementPos, false); - int numSubmarineCells = cells[cid].underWaterCellIds.size(); - maxDepth = cells[cid].pos.y; - minDepth = (numSubmarineCells > 0 ? cells[cells[cid].underWaterCellIds[numSubmarineCells - 1]].pos.y : maxDepth) - .5 * cellSize.y; - minDepthCalculated = true; - } - else{ - ActiveGameState *activeState = (ActiveGameState*)(GameManager::getSingleton()->getStateManager()->getAppStateByType((int)AppStateType::ACTIVE_STATE)); - float newDepth = minDepth + activeState->getDepth() * (maxDepth - minDepth); - placementPos.y = newDepth; - } - } - else if(placingOnSurface) - placementPos = results[0].pos; + vector deposits; + for(ResourceDeposit *rd : Game::getSingleton()->getCivilianPlayer()->getResourceDeposits()) + deposits.push_back((GameObject*)rd); for(int i = 0; i < gameObjectFrames.size(); i++){ + gameObjectFrames[i].update(); + if(paintSelecting){ + float width = gameObjectFrames[0].getWidth(); + float length = gameObjectFrames[0].getLength(); float hypothenuse = sqrt(width * width + length * length); Vector3 dir = (results[0].pos - paintSelectRowStart).norm(); placementPos = paintSelectRowStart + dir * hypothenuse * i; } if(!rotating && (placingOnSurface || placingVertically)) - placeGameObjectFrame(i, placementPos, width, length); - } - } + gameObjectFrames[i].placeAt(placementPos); - void GameObjectFrameController::update(){ - updatePlacement(); + if(gameObjectFrames[i].getId() == 23) + snapToObj(gameObjectFrames[i], deposits, 20); + else + checkPlacement(gameObjectFrames[i]); + + bool placeable = (gameObjectFrames[i].status == GameObjectFrame::PLACEABLE); + Vector4 color = (placeable ? Vector4(0, 1, 0, 1) : Vector4(1, 0, 0, 1)); + gameObjectFrames[i].getModel()->getMaterial()->setVec4Uniform("diffuseColor", color); + } if(!placingVertically) minDepthCalculated = false; } diff --git a/gameObjectFrameController.h b/gameObjectFrameController.h index 488c7df..2726e9e 100644 --- a/gameObjectFrameController.h +++ b/gameObjectFrameController.h @@ -21,7 +21,7 @@ namespace battleship{ void removeGameObjectFrame(int); void removeGameObjectFrames(); void rotateGameObjectFrames(float); - void placeGameObjectFrame(int, vb01::Vector3, float, float); + void checkPlacement(GameObjectFrame&); inline int getNumGameObjectFrames(){return gameObjectFrames.size();} inline void addGameObjectFrame(GameObjectFrame u){gameObjectFrames.push_back(u);} inline GameObjectFrame& getGameObjectFrame(int i){return gameObjectFrames[i];} @@ -41,9 +41,9 @@ namespace battleship{ } private: GameObjectFrameController(){} - void paintSelect(vb01::Vector3, float, float); - void snapToObj(GameObjectFrame&, GameObject::Type, int, float); - void updatePlacement(); + void paintSelect(vb01::Vector3); + void snapToObj(GameObjectFrame&, std::vector, float); + void shiftVerticalPlacement(); std::vector gameObjectFrames; vb01::Vector3 paintSelectRowStart, placementPos;