Skip to content

Commit

Permalink
Bulidings can now prevent building other buildings
Browse files Browse the repository at this point in the history
  • Loading branch information
Yankes committed Jul 1, 2016
1 parent b4d2288 commit ad27f8d
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 21 deletions.
4 changes: 4 additions & 0 deletions Extended.txt
Expand Up @@ -107,6 +107,9 @@ New recolr and replace script graphic option for items.[br/]
Option for global events shared by scripts.[br/]
Custom tags that have user defined values.[br/]
[br/]
3.1:[br/]
Base building can now prevent building other buildings.[br/]
[br/]

[examples]
[br/][br/]
Expand Down Expand Up @@ -500,6 +503,7 @@ facilities:
refund: 6 #how many items are returned when facility is dismantled.
provideBaseFunc: [ A ] #List of custom IDs that this bulding provide for base.
requiresBaseFunc: [ ] #List of custom IDs that are require to build this building in base.
forbidenBaseFunc: [ B ] #List of custom IDs that are forbiden by this building.
trainingRooms: 0 #Number of solder that can be train in that building, require langue strings.
refundValue: 0 #how much mony is returned when facility is dismantled.
[/code]
Expand Down
55 changes: 53 additions & 2 deletions src/Basescape/BuildFacilitiesState.cpp
Expand Up @@ -80,7 +80,6 @@ BuildFacilitiesState::BuildFacilitiesState(Base *base, State *state) : _base(bas
_lstFacilities->setScrolling(true, 0);
_lstFacilities->onMouseClick((ActionHandler)&BuildFacilitiesState::lstFacilitiesClick);

PopulateBuildList();
}

/**
Expand All @@ -91,22 +90,72 @@ BuildFacilitiesState::~BuildFacilitiesState()

}

namespace
{
/**
* Find if two vector ranges intersects.
* @param a First Vector.
* @param b Second Vector.
* @return True if have common value.
*/
bool intersection(const std::vector<std::string> &a, const std::vector<std::string> &b)
{
auto a_begin = std::begin(a);
auto a_end = std::end(a);
auto b_begin = std::begin(b);
auto b_end = std::end(b);
while (true)
{
if (b_begin == b_end)
{
return false;
}
a_begin = std::lower_bound(a_begin, a_end, *b_begin);
if (a_begin == a_end)
{
return false;
}
if (*a_begin == *b_begin)
{
return true;
}
b_begin = std::lower_bound(b_begin, b_end, *a_begin);
}
}

}

/**
* Populates the build list from the current "available" facilities.
*/
void BuildFacilitiesState::PopulateBuildList()
{
const std::set<std::string> &providedBaseFunc = _base->getProvidedBaseFunc();
_facilities.clear();
_lstFacilities->clearList();

const std::vector<std::string> &providedBaseFunc = _base->getProvidedBaseFunc();
const std::vector<std::string> &forbiddenBaseFunc = _base->getForbiddenBaseFunc();
const std::vector<std::string> &futureBaseFunc = _base->getFutureBaseFunc();

const std::vector<std::string> &facilities = _game->getMod()->getBaseFacilitiesList();
for (std::vector<std::string>::const_iterator i = facilities.begin(); i != facilities.end(); ++i)
{
RuleBaseFacility *rule = _game->getMod()->getBaseFacility(*i);
const std::vector<std::string> &req = rule->getRequireBaseFunc();
const std::vector<std::string> &forb = rule->getForbiddenBaseFunc();
const std::vector<std::string> &prov = rule->getProvidedBaseFunc();
if (!std::includes(providedBaseFunc.begin(), providedBaseFunc.end(), req.begin(), req.end()))
{
continue;
}
if (intersection(forbiddenBaseFunc, prov))
{
continue;
}
if (intersection(futureBaseFunc, forb))
{
continue;
}
if (_game->getSavedGame()->isResearched(rule->getRequirements()) && !rule->isLift())
_facilities.push_back(rule);
}
Expand All @@ -125,6 +174,8 @@ void BuildFacilitiesState::init()
{
_state->init();
State::init();

PopulateBuildList();
}

/**
Expand Down
11 changes: 11 additions & 0 deletions src/Mod/RuleBaseFacility.cpp
Expand Up @@ -55,9 +55,11 @@ void RuleBaseFacility::load(const YAML::Node &node, Mod *mod, int listOrder)
_requires = node["requires"].as< std::vector<std::string> >(_requires);
_requiresBaseFunc = node["requiresBaseFunc"].as< std::vector<std::string> >(_requiresBaseFunc);
_provideBaseFunc = node["provideBaseFunc"].as< std::vector<std::string> >(_provideBaseFunc);
_forbiddenBaseFunc = node["forbiddenBaseFunc"].as< std::vector<std::string> >(_forbiddenBaseFunc);

std::sort(_requiresBaseFunc.begin(), _requiresBaseFunc.end());
std::sort(_provideBaseFunc.begin(), _provideBaseFunc.end());
std::sort(_forbiddenBaseFunc.begin(), _forbiddenBaseFunc.end());

if (node["spriteShape"])
{
Expand Down Expand Up @@ -162,6 +164,15 @@ const std::vector<std::string> &RuleBaseFacility::getProvidedBaseFunc() const
{
return _provideBaseFunc;
}

/**
* Gets the list of forbiden functions by this building.
* @return List of function IDs.
*/
const std::vector<std::string> &RuleBaseFacility::getForbiddenBaseFunc() const
{
return _forbiddenBaseFunc;
}
/**
* Gets the ID of the sprite used to draw the
* base structure of the facility that defines its shape.
Expand Down
4 changes: 3 additions & 1 deletion src/Mod/RuleBaseFacility.h
Expand Up @@ -39,7 +39,7 @@ class RuleBaseFacility
{
private:
std::string _type;
std::vector<std::string> _requires, _requiresBaseFunc, _provideBaseFunc;
std::vector<std::string> _requires, _requiresBaseFunc, _provideBaseFunc, _forbiddenBaseFunc;
int _spriteShape, _spriteFacility;
bool _lift, _hyper, _mind, _grav;
int _size, _buildCost, _refundValue, _buildTime, _monthlyCost;
Expand All @@ -63,6 +63,8 @@ class RuleBaseFacility
const std::vector<std::string> &getRequireBaseFunc() const;
/// Gets the functions that facility provide in base.
const std::vector<std::string> &getProvidedBaseFunc() const;
/// Gets the functions that facility prevent in base.
const std::vector<std::string> &getForbiddenBaseFunc() const;
/// Gets the facility's shape sprite.
int getSpriteShape() const;
/// Gets the facility's content sprite.
Expand Down
74 changes: 61 additions & 13 deletions src/Savegame/Base.cpp
Expand Up @@ -1785,14 +1785,34 @@ void Base::cleanupDefenses(bool reclaimItems)
}
}

namespace
{

/**
* Store unique values from diffrent vectors.
* @param result Vector where final data will be send.
* @param temp Temporaly data container storing working buffer.
* @param data Data to add.
*/
void aggregateUnique(std::vector<std::string> &result, std::vector<std::string> &temp, const std::vector<std::string> &data)
{
temp.clear();

std::set_union(std::make_move_iterator(std::begin(result)), std::make_move_iterator(std::end(result)), std::begin(data), std::end(data), std::back_inserter(temp));

std::swap(result, temp);
}

}

/**
* Return list of all provided functionality in base.
* @param skip Skip functions provide by this facility .
* @param skip Skip functions provide by this facility.
* @return List of custom IDs.
*/
std::set<std::string> Base::getProvidedBaseFunc(const BaseFacility *skip) const
std::vector<std::string> Base::getProvidedBaseFunc(const BaseFacility *skip) const
{
std::set<std::string> ret;
std::vector<std::string> ret, temp;

for (std::vector<BaseFacility*>::const_iterator bf = _facilities.begin(); bf != _facilities.end(); ++bf)
{
Expand All @@ -1804,8 +1824,7 @@ std::set<std::string> Base::getProvidedBaseFunc(const BaseFacility *skip) const
{
continue;
}
const std::vector<std::string> &prov = (*bf)->getRules()->getProvidedBaseFunc();
ret.insert(prov.begin(), prov.end());
aggregateUnique(ret, temp, (*bf)->getRules()->getProvidedBaseFunc());
}

return ret;
Expand All @@ -1816,30 +1835,59 @@ std::set<std::string> Base::getProvidedBaseFunc(const BaseFacility *skip) const
* @param skip Skip functions require by this facility.
* @return List of custom IDs.
*/
std::set<std::string> Base::getRequireBaseFunc(const BaseFacility *skip) const
std::vector<std::string> Base::getRequireBaseFunc(const BaseFacility *skip) const
{
std::set<std::string> ret;
std::vector<std::string> ret, temp;

for (std::vector<BaseFacility*>::const_iterator bf = _facilities.begin(); bf != _facilities.end(); ++bf)
{
if (*bf == skip)
{
continue;
}
const std::vector<std::string> &prov = (*bf)->getRules()->getRequireBaseFunc();
ret.insert(prov.begin(), prov.end());
aggregateUnique(ret, temp, (*bf)->getRules()->getRequireBaseFunc());
}

for (std::vector<ResearchProject*>::const_iterator res = _research.begin(); res != _research.end(); ++res)
{
const std::vector<std::string> &req = (*res)->getRules()->getRequireBaseFunc();
ret.insert(req.begin(), req.end());
aggregateUnique(ret, temp, (*res)->getRules()->getRequireBaseFunc());
}

for (std::vector<Production*>::const_iterator prod = _productions.begin(); prod != _productions.end(); ++prod)
{
const std::vector<std::string> &req = (*prod)->getRules()->getRequireBaseFunc();
ret.insert(req.begin(), req.end());
aggregateUnique(ret, temp, (*prod)->getRules()->getRequireBaseFunc());
}

return ret;
}

/**
* Return list of all forbiden functionality in base.
* @return List of custom IDs.
*/
std::vector<std::string> Base::getForbiddenBaseFunc() const
{
std::vector<std::string> ret, temp;

for (std::vector<BaseFacility*>::const_iterator bf = _facilities.begin(); bf != _facilities.end(); ++bf)
{
aggregateUnique(ret, temp, (*bf)->getRules()->getForbiddenBaseFunc());
}

return ret;
}

/**
* Return list of all future provided functionality in base.
* @return List of custom IDs.
*/
std::vector<std::string> Base::getFutureBaseFunc() const
{
std::vector<std::string> ret, temp;

for (std::vector<BaseFacility*>::const_iterator bf = _facilities.begin(); bf != _facilities.end(); ++bf)
{
aggregateUnique(ret, temp, (*bf)->getRules()->getProvidedBaseFunc());
}

return ret;
Expand Down
8 changes: 6 additions & 2 deletions src/Savegame/Base.h
Expand Up @@ -222,9 +222,13 @@ class Base : public Target
/// Cleans up the defenses vector and optionally reclaims the tanks and their ammo.
void cleanupDefenses(bool reclaimItems);
/// Gets available base functionality.
std::set<std::string> getProvidedBaseFunc(const BaseFacility *skip = 0) const;
std::vector<std::string> getProvidedBaseFunc(const BaseFacility *skip = 0) const;
/// Gets used base functionality.
std::set<std::string> getRequireBaseFunc(const BaseFacility *skip = 0) const;
std::vector<std::string> getRequireBaseFunc(const BaseFacility *skip = 0) const;
/// Gets forbiden base functionality.
std::vector<std::string> getForbiddenBaseFunc() const;
/// Gets future base functionality.
std::vector<std::string> getFutureBaseFunc() const;
};

}
Expand Down
7 changes: 4 additions & 3 deletions src/Savegame/BaseFacility.cpp
Expand Up @@ -19,6 +19,7 @@
#include "BaseFacility.h"
#include "../Mod/RuleBaseFacility.h"
#include "Base.h"
#include <algorithm>

namespace OpenXcom
{
Expand Down Expand Up @@ -154,13 +155,13 @@ bool BaseFacility::inUse() const
return false;
}

const std::set<std::string> &otherBaseFunc = _base->getProvidedBaseFunc(this);
const std::set<std::string> &usedBaseFunc = _base->getRequireBaseFunc(this);
const std::vector<std::string> &otherBaseFunc = _base->getProvidedBaseFunc(this);
const std::vector<std::string> &usedBaseFunc = _base->getRequireBaseFunc(this);

const std::vector<std::string> &thisProve = getRules()->getProvidedBaseFunc();
for (std::vector<std::string>::const_iterator i = thisProve.begin(); i != thisProve.end(); ++i)
{
if (!otherBaseFunc.count(*i) && usedBaseFunc.count(*i)) //we provide something unique and someone else using it.
if (!std::binary_search(std::begin(otherBaseFunc),std::end(otherBaseFunc), *i) && std::binary_search(std::begin(usedBaseFunc),std::end(usedBaseFunc), *i)) //we provide something unique and someone else using it.
return true;
}

Expand Down

0 comments on commit ad27f8d

Please sign in to comment.