diff --git a/activeGameState.cpp b/activeGameState.cpp index 937cfa4..db68e41 100755 --- a/activeGameState.cpp +++ b/activeGameState.cpp @@ -148,17 +148,17 @@ namespace battleship{ } vector offers = (gameObjHoveredOn && alliedGameObj ? mainPlayer->getTradeOffers(gameObjHoveredOn->getPlayer()) : vector{}); - bool tradeResource[NUM_RESOURCES][2], trade = false; + bool tradeResource[NUM_RESOURCES], trade = false; + int unloadFlag = (int)shiftPressed; - for(TradeOffer *offer : offers) - for(int i = 0; i < NUM_RESOURCES; i++) - for(int j = 0; j < 2; j++){ - if(!tradeResource[i][j] && offer->tradeResources[i][j] > 0){ - tradeResource[i][j] = true; - trade = true; - } - else tradeResource[i][j] = false; - } + for(int i = 0; i < NUM_RESOURCES && !offers.empty(); i++){ + if(offers[0]->tradeResources[i][unloadFlag] > 0){ + tradeResource[i] = true; + trade = true; + } + else + tradeResource[i] = false; + } int objClass = (gameObjUnit ? int(((Unit*)gameObjHoveredOn)->getUnitClass()) : -1); bool tradeCenter = ((UnitClass)objClass == UnitClass::TRADE_CENTER); @@ -179,34 +179,30 @@ namespace battleship{ cursorState = CursorState::SUPPLY; } else if(roverSelected && (tradeCenter || refinery || lab) && (ownGameObj || (alliedGameObj && trade))){ - bool canLoad = (rover && rover->calcTotalLoad() < rover->getCapacity()); - bool tradeRes; + bool tradeRes = false; int resId; - + switch((UnitClass)objClass){ case UnitClass::TRADE_CENTER: - tradeRes = (tradeResource[(int)ResourceType::WEALTH][0] || tradeResource[(int)ResourceType::WEALTH][1]); + tradeRes = tradeResource[(int)ResourceType::WEALTH]; resId = (int)ResourceType::WEALTH; break; case UnitClass::REFINERY: - tradeRes = (tradeResource[(int)ResourceType::REFINEDS][0] || tradeResource[(int)ResourceType::REFINEDS][1]); + tradeRes = tradeResource[(int)ResourceType::REFINEDS]; resId = (int)ResourceType::REFINEDS; break; case UnitClass::LAB: - tradeRes = (tradeResource[(int)ResourceType::RESEARCH][0] || tradeResource[(int)ResourceType::RESEARCH][1]); + tradeRes = tradeResource[(int)ResourceType::RESEARCH]; resId = (int)ResourceType::RESEARCH; break; } + + bool canLoad = (rover && rover->calcTotalLoad() < rover->getCapacity()); + orderPossible = (unloadFlag ? rover->getLoad(resId) > 0 : canLoad); - orderPossible = ( - (ownGameObj && canLoad) || - ( - alliedGameObj && - tradeRes && - (rover->calcTotalLoad() < rover->getCapacity() || rover->getLoad(resId) > 0) - ) - ); - cursorState = CursorState::SUPPLY; + if(alliedGameObj) orderPossible = tradeRes && orderPossible; + + cursorState = (unloadFlag ? CursorState::UNLOAD : CursorState::LOAD); } else if(gameObjUnit && !(ownGameObj || alliedGameObj)) cursorState = CursorState::ATTACK; @@ -216,18 +212,20 @@ namespace battleship{ else{ if(cursorState == CursorState::GARRISON) orderPossible = (ownGameObj && gameObjTransport && canGarrison); - else if(cursorState == CursorState::SUPPLY){ - bool tradeRefs = (tradeResource[(int)ResourceType::REFINEDS][0] || tradeResource[(int)ResourceType::REFINEDS][1]); - bool tradeWealth = (tradeResource[(int)ResourceType::WEALTH][0] || tradeResource[(int)ResourceType::WEALTH][1]); - bool tradeTech = (tradeResource[(int)ResourceType::RESEARCH][0] || tradeResource[(int)ResourceType::RESEARCH][1]); - + else if(cursorState == CursorState::SUPPLY) + orderPossible = (roverSelected && ownExtractor); + else if(cursorState == CursorState::LOAD || cursorState == CursorState::UNLOAD){ + bool tradeRefs = tradeResource[(int)ResourceType::REFINEDS]; + bool tradeWealth = tradeResource[(int)ResourceType::WEALTH]; + bool tradeTech = tradeResource[(int)ResourceType::RESEARCH]; + bool canLoad = (rover->calcTotalLoad() < rover->getCapacity()); - bool transfer = ( + bool loadResource = ( (refinery && ((ownGameObj && canLoad) || (alliedGameObj && tradeRefs && rover->getLoad((int)ResourceType::REFINEDS) > 0))) || (tradeCenter && ((ownGameObj && canLoad) || (alliedGameObj && tradeWealth && rover->getLoad((int)ResourceType::WEALTH) > 0))) || (lab && ((ownGameObj && canLoad) || (alliedGameObj && tradeTech && rover->getLoad((int)ResourceType::RESEARCH) > 0))) ); - orderPossible = (roverSelected && (ownExtractor || transfer)); + orderPossible = (roverSelected && loadResource); } else if(cursorState == CursorState::HACK) orderPossible = (!ownGameObj && gameObjUnit && mainPlayer->getSelectedUnit(0)->getUnitClass() == UnitClass::ENGINEER); @@ -249,6 +247,8 @@ namespace battleship{ tex = (orderPossible ? garrisonTex : noGarrisonTex); break; case CursorState::SUPPLY: + case CursorState::LOAD: + case CursorState::UNLOAD: tex = (orderPossible ? supplyTex : noSupplyTex); break; case CursorState::HACK: @@ -551,6 +551,7 @@ namespace battleship{ } //TODO fix ejectable unit selection with multiple transports selected + //TODO replace shiftPressed with a dedicated buy flag void ActiveGameState::issueOrder(Order::TYPE type, vector targets, bool addOrder) { depth = 1; Vector3 destDir = Vector3::VEC_ZERO; @@ -675,6 +676,12 @@ namespace battleship{ else if(cursorState == CursorState::SUPPLY){ if(orderPossible) issueOrder(Order::TYPE::SUPPLY, vector{Order::Target((Unit*)gameObjHoveredOn)}, shiftPressed); } + else if(cursorState == CursorState::LOAD){ + if(orderPossible) issueOrder(Order::TYPE::LOAD, vector{Order::Target((Unit*)gameObjHoveredOn)}, shiftPressed); + } + else if(cursorState == CursorState::UNLOAD){ + if(orderPossible) issueOrder(Order::TYPE::UNLOAD, vector{Order::Target((Unit*)gameObjHoveredOn)}, shiftPressed); + } else if(cursorState == CursorState::ATTACK){ if(controlPressed && !gameObjHoveredOn){ castRayToTerrain(); diff --git a/activeGameState.h b/activeGameState.h index 7d81569..63740c7 100755 --- a/activeGameState.h +++ b/activeGameState.h @@ -29,6 +29,8 @@ namespace battleship{ ATTACK, GARRISON, SUPPLY, + LOAD, + UNLOAD, HACK }; diff --git a/orderButton.cpp b/orderButton.cpp index fe92653..0251c06 100644 --- a/orderButton.cpp +++ b/orderButton.cpp @@ -45,6 +45,12 @@ namespace battleship{ case Order::TYPE::SUPPLY: cs = ActiveGameState::CursorState::SUPPLY; break; + case Order::TYPE::LOAD: + cs = ActiveGameState::CursorState::LOAD; + break; + case Order::TYPE::UNLOAD: + cs = ActiveGameState::CursorState::UNLOAD; + break; case Order::TYPE::HACK: cs = ActiveGameState::CursorState::HACK; break; diff --git a/player.cpp b/player.cpp index fa13b79..c63adb8 100755 --- a/player.cpp +++ b/player.cpp @@ -41,30 +41,35 @@ namespace battleship{ vector units = this->units; for(Unit *u : units){ - if(!u->isRemove()) - u->update(); - else - removeUnit(u); + if(!u->isRemove()) u->update(); + else removeUnit(u); } vector projectiles = this->projectiles; for(Projectile *proj : projectiles){ - if(!proj->isRemove()) - proj->update(); - else - removeProjectile(proj); + if(!proj->isRemove()) proj->update(); + else removeProjectile(proj); } - for(ResourceDeposit *rd : resourceDeposits) - rd->update(); + for(ResourceDeposit *rd : resourceDeposits) rd->update(); - updateTradeOffers(); + for(pair> &pair : tradeOffers){ + if(pair.second.empty()) continue; + + bool fulfiled = true; + + for(int i = 0; i < NUM_RESOURCES && fulfiled; i++){ + bool b = (pair.second[0]->tradeResources[i][0] == pair.second[0]->deliveredResources[i][0]); + bool s = (pair.second[0]->tradeResources[i][1] == pair.second[0]->deliveredResources[i][1]); + + if(!(b && s)) fulfiled = false; + } + + if(fulfiled) + pair.second.erase(pair.second.begin()); + } } - void Player::updateTradeOffers(){ - - } - int Player::getOrderLineId(Order::TYPE type, Vector3 startPos, Vector3 endPos){ Vector3 color; @@ -82,6 +87,8 @@ namespace battleship{ break; case Order::TYPE::BUILD: case Order::TYPE::SUPPLY: + case Order::TYPE::LOAD: + case Order::TYPE::UNLOAD: color = Vector3(1, 1, 0); break; case Order::TYPE::HACK: diff --git a/player.h b/player.h index 1a97c78..7aafdb3 100755 --- a/player.h +++ b/player.h @@ -104,7 +104,6 @@ namespace battleship{ int getOrderLineId(Order::TYPE, vb01::Vector3, vb01::Vector3); void initTradingVecs(); - void updateTradeOffers(); }; } diff --git a/resourceRover.cpp b/resourceRover.cpp index dbc2ac1..7ea60d5 100644 --- a/resourceRover.cpp +++ b/resourceRover.cpp @@ -37,6 +37,76 @@ namespace battleship{ loadRate = unitTable["loadRate"]; loadRate += game->calcAbilFromTech(Ability::Type::LOAD_RATE, currTechs, (int)GameObject::type, id); } + void ResourceRover::handleTransfer(Structure *targStruct, float minDist, bool loadResource){ + bool closeEnough = (pos.getDistanceFrom(targStruct->getPos()) <= minDist); + if(!closeEnough) return; + + ResourceType resType; + + switch(targStruct->getUnitClass()){ + case UnitClass::TRADE_CENTER: + resType = ResourceType::WEALTH; + break; + case UnitClass::REFINERY: + resType = ResourceType::REFINEDS; + break; + case UnitClass::LAB: + resType = ResourceType::RESEARCH; + break; + } + + if(player == targStruct->getPlayer()){ + if(!loadResource && canUnload((int)resType)){ + player->updateResource(resType, loadSpeed, true); + cargo[(int)resType] -= loadSpeed; + lastLoadTime = getTime(); + } + else if(loadResource && canLoad() && player->getResource(resType) > 0){ + player->updateResource(resType, -loadSpeed, true); + cargo[(int)resType] += loadSpeed; + lastLoadTime = getTime(); + } + } + else{ + vector offers = player->getTradeOffers(targStruct->getPlayer()); + if(offers.empty()) return; + + TradeOffer *offer = offers[0]; + + if(!loadResource && offer->tradeResources[(int)resType][1] > offer->deliveredResources[(int)resType][1] && canUnload((int)resType)){ + targStruct->getPlayer()->updateResource(resType, loadSpeed, true); + offer->deliveredResources[(int)resType][1]++; + cargo[(int)resType] -= loadSpeed; + lastLoadTime = getTime(); + } + else if( + loadResource && + offer->tradeResources[(int)resType][0] > offer->deliveredResources[(int)resType][0] && + targStruct->getPlayer()->getResource(resType) > 0 && + canLoad() + ) + { + targStruct->getPlayer()->updateResource(resType, -loadSpeed, true); + offer->deliveredResources[(int)resType][0]++; + cargo[(int)resType] += loadSpeed; + lastLoadTime = getTime(); + } + } + } + + void ResourceRover::transfer(Order order, bool loadResource){ + float minDist = .5 * Map::getSingleton()->getCellSize().x; + + if(!pathPoints.empty()) + navigate(minDist); + else + handleTransfer((Structure*)order.targets[0].unit, minDist, loadResource); + } + + void ResourceRover::load(Order order){transfer(order, true);} + + void ResourceRover::unload(Order order){transfer(order, false);} + //TODO equate rover load and extractor draw rates void ResourceRover::collectRefineds(Order order, float minDist){ vector units = player->getUnits(); @@ -58,7 +128,7 @@ namespace battleship{ if(canLoad() && deposit->getAmmount() > 0){ if(nearestExtractor->canDraw()){ nearestExtractor->draw(); - load[(int)ResourceType::REFINEDS] += loadSpeed; + cargo[(int)ResourceType::REFINEDS] += loadSpeed; lastLoadTime = getTime(); } } @@ -66,7 +136,7 @@ namespace battleship{ preparePathpoints(order, nearestRefinery->getPos(), true); } else if(!nearestExtractor){ - if(nearestRefinery && load[(int)ResourceType::REFINEDS] > 0) + if(nearestRefinery && cargo[(int)ResourceType::REFINEDS] > 0) preparePathpoints(order, nearestRefinery->getPos(), true); else removeOrder(0); @@ -74,57 +144,22 @@ namespace battleship{ if(nearestRefinery && nearestRefinery->getPos().getDistanceFrom(pos) <= minDist){ if(canUnload((int)ResourceType::REFINEDS)){ - load[(int)ResourceType::REFINEDS] -= loadSpeed; + cargo[(int)ResourceType::REFINEDS] -= loadSpeed; player->updateResource(ResourceType::REFINEDS, loadSpeed, true); lastLoadTime = getTime(); } - else if(load[(int)ResourceType::REFINEDS] == 0 && nearestExtractor) + else if(cargo[(int)ResourceType::REFINEDS] == 0 && nearestExtractor) preparePathpoints(order, nearestExtractor->getPos()); } } - void ResourceRover::transferResource(Structure *targStruct, float minDist){ - bool closeEnough = (pos.getDistanceFrom(targStruct->getPos()) <= minDist); - ResourceType resType; - - switch(targStruct->getUnitClass()){ - case UnitClass::TRADE_CENTER: - resType = ResourceType::WEALTH; - break; - case UnitClass::REFINERY: - resType = ResourceType::REFINEDS; - break; - case UnitClass::LAB: - resType = ResourceType::RESEARCH; - break; - } - - if(closeEnough){ - if(player == targStruct->getPlayer() && canLoad() && player->getResource(resType) > 0){ - player->updateResource(resType, -loadSpeed, true); - load[(int)resType] += loadSpeed; - lastLoadTime = getTime(); - } - else if(player != targStruct->getPlayer() && canUnload((int)resType)){ - targStruct->getPlayer()->updateResource(resType, loadSpeed, true); - load[(int)resType] -= loadSpeed; - lastLoadTime = getTime(); - } - } - } - void ResourceRover::supply(Order order){ float minDist = .5 * Map::getSingleton()->getCellSize().x; if(!pathPoints.empty()) navigate(minDist); - else{ - Unit *targUnit = order.targets[0].unit; - - if(targUnit->getUnitClass() == UnitClass::EXTRACTOR) - collectRefineds(order, minDist); - else transferResource((Structure*)targUnit, minDist); - } + else + collectRefineds(order, minDist); } void ResourceRover::update(){ diff --git a/resourceRover.h b/resourceRover.h index 22eaaa6..cfa6197 100644 --- a/resourceRover.h +++ b/resourceRover.h @@ -14,20 +14,23 @@ namespace battleship{ ResourceRover(Player*, int, vb01::Vector3, vb01::Quaternion, Unit::State = Unit::State::STAND_GROUND); ~ResourceRover(); void update(); - inline int getLoad(int id){return load[id];} - inline int calcTotalLoad(){return load[0] + load[1] + load[2];} + inline int getLoad(int id){return cargo[id];} + inline int calcTotalLoad(){return cargo[0] + cargo[1] + cargo[2];} inline int getCapacity(){return capacity;} + inline bool canLoad(){return vb01::getTime() - lastLoadTime > loadRate && calcTotalLoad() < capacity;} + inline bool canUnload(int id){return vb01::getTime() - lastLoadTime > loadRate && cargo[id] > 0;} private: void initProperties(); - void supply(Order); void collectRefineds(Order, float); - void transferResource(Structure*, float); + void supply(Order); + void handleTransfer(Structure*, float, bool); + void transfer(Order, bool); + void load(Order); + void unload(Order); Unit* getClosestUnit(std::vector); - inline bool canLoad(){return vb01::getTime() - lastLoadTime > loadRate && calcTotalLoad() < capacity;} - inline bool canUnload(int id){return vb01::getTime() - lastLoadTime > loadRate && load[id] > 0;} vb01::s64 lastLoadTime = 0; - int load[3]{0, 0, 0}, capacity, loadRate, loadSpeed; + int cargo[3]{0, 0, 0}, capacity, loadRate, loadSpeed; Extractor *nearestExtractor = nullptr; Unit *nearestRefinery = nullptr; vb01::Node *loadBackground = nullptr, *loadForeground = nullptr; diff --git a/unit.cpp b/unit.cpp index 4affd74..c6fdd59 100755 --- a/unit.cpp +++ b/unit.cpp @@ -629,6 +629,12 @@ namespace battleship{ case Order::TYPE::SUPPLY: supply(order); break; + case Order::TYPE::LOAD: + load(order); + break; + case Order::TYPE::UNLOAD: + unload(order); + break; case Order::TYPE::HACK: hack(order); break; @@ -702,6 +708,8 @@ namespace battleship{ return false; } case Order::TYPE::SUPPLY: + case Order::TYPE::LOAD: + case Order::TYPE::UNLOAD: return unitClass == UnitClass::RESOURCE_ROVER; case Order::TYPE::HACK: { diff --git a/unit.h b/unit.h index ecd2ea5..0b0ba46 100755 --- a/unit.h +++ b/unit.h @@ -37,7 +37,7 @@ namespace battleship{ class Projectile; struct Order { - enum class TYPE {ATTACK, BUILD, MOVE, GARRISON, EJECT, PATROL, LAUNCH, SUPPLY, HACK}; + enum class TYPE {ATTACK, BUILD, MOVE, GARRISON, EJECT, PATROL, LAUNCH, SUPPLY, LOAD, UNLOAD, HACK}; struct Target{ Unit *unit = nullptr; vb01::Vector3 pos; @@ -53,9 +53,14 @@ namespace battleship{ std::vector targets; Order(){} - Order(TYPE t, std::vector targ, vb01::Vector3 dir = vb01::Vector3::VEC_ZERO, int lid = -1, bool pa = true) : type(t), playerAssigned(pa), lineId(lid), targets(targ), direction(dir){} + Order(TYPE t, std::vector targ, vb01::Vector3 dir = vb01::Vector3::VEC_ZERO, int lid = -1, bool pa = true) : + type(t), + playerAssigned(pa), + lineId(lid), + targets(targ), + direction(dir){} }; - + enum class MoveDir {LEFT, UP, FORW}; enum class Corner {FRONT_LEFT, FRONT_RIGHT, REAR_LEFT, REAR_RIGHT}; enum class UnitType {UNDERWATER, SEA_LEVEL, HOVER, LAND, AIR, NONE = -1}; @@ -205,6 +210,8 @@ namespace battleship{ virtual void patrol(Order){} virtual void launch(Order); virtual void supply(Order){} + virtual void load(Order){} + virtual void unload(Order){} virtual void hack(Order){} float calculateRotation(vb01::Vector3, float, float); void removeBar(vb01::Node*);