- option for Distance building rule to not count diagonally. - add surrounded-by distance rule

This commit is contained in:
Tim Felgentreff 2015-09-06 17:14:32 +02:00
parent 6a1f22268f
commit 926e64502c
3 changed files with 165 additions and 5 deletions

View file

@ -413,7 +413,7 @@ public:
class CBuildRestrictionDistance : public CBuildRestriction
{
public:
CBuildRestrictionDistance() : Distance(0), CheckBuilder(false), RestrictType(NULL) {};
CBuildRestrictionDistance() : Distance(0), CheckBuilder(false), RestrictType(NULL), Diagonal(true) {};
virtual ~CBuildRestrictionDistance() {};
virtual void Init() {this->RestrictType = UnitTypeByIdent(this->RestrictTypeName);};
virtual bool Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&ontoptarget) const;
@ -424,6 +424,7 @@ public:
std::string RestrictTypeOwner;
CUnitType *RestrictType;
bool CheckBuilder;
bool Diagonal;
};
class CBuildRestrictionHasUnit : public CBuildRestriction
@ -440,6 +441,24 @@ public:
CUnitType *RestrictType;
};
class CBuildRestrictionSurroundedBy : public CBuildRestriction
{
public:
CBuildRestrictionSurroundedBy() : Count(0), Distance(0), DistanceType(Equal), CountType(Equal), RestrictType(NULL), CheckBuilder(false) {};
virtual ~CBuildRestrictionSurroundedBy() {};
virtual void Init() { this->RestrictType = UnitTypeByIdent(this->RestrictTypeName); };
virtual bool Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&ontoptarget) const;
int Distance;
DistanceTypeType DistanceType;
int Count;
DistanceTypeType CountType;
std::string RestrictTypeName;
std::string RestrictTypeOwner;
CUnitType *RestrictType;
bool CheckBuilder;
};
/// Base structure of unit-type
/// @todo n0body: AutoBuildRate not implemented.
class CUnitType

View file

@ -148,23 +148,23 @@ bool CBuildRestrictionDistance::Check(const CUnit *builder, const CUnitType &typ
case GreaterThan :
case GreaterThanEqual :
if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) <= distance) {
return false;
return Diagonal ? false : !(pos.x != table[i]->tilePos.x || pos.y != table[i]->tilePos.y);
}
break;
case LessThan :
case LessThanEqual :
if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) <= distance) {
return true;
return Diagonal || pos.x == table[i]->tilePos.x || pos.y == table[i]->tilePos.y;
}
break;
case Equal :
if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) == distance) {
return true;
return Diagonal || pos.x == table[i]->tilePos.x || pos.y == table[i]->tilePos.y;
}
break;
case NotEqual :
if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) == distance) {
return false;
return Diagonal ? false : !(pos.x != table[i]->tilePos.x || pos.y != table[i]->tilePos.y);
}
break;
}
@ -195,6 +195,82 @@ bool CBuildRestrictionHasUnit::Check(const CUnit *builder, const CUnitType &type
}
}
/**
** Check Surrounded By Restriction
*/
bool CBuildRestrictionSurroundedBy::Check(const CUnit *builder, const CUnitType &type, const Vec2i &pos, CUnit *&) const
{
Vec2i pos1(0, 0);
Vec2i pos2(0, 0);
int distance = 0;
int count = 0;
if (this->DistanceType == LessThanEqual
|| this->DistanceType == GreaterThan
|| this->DistanceType == Equal
|| this->DistanceType == NotEqual) {
pos1.x = std::max<int>(pos.x - this->Distance, 0);
pos1.y = std::max<int>(pos.y - this->Distance, 0);
pos2.x = std::min<int>(pos.x + type.TileWidth + this->Distance, Map.Info.MapWidth);
pos2.y = std::min<int>(pos.y + type.TileHeight + this->Distance, Map.Info.MapHeight);
distance = this->Distance;
}
else if (this->DistanceType == LessThan || this->DistanceType == GreaterThanEqual) {
pos1.x = std::max<int>(pos.x - this->Distance - 1, 0);
pos1.y = std::max<int>(pos.y - this->Distance - 1, 0);
pos2.x = std::min<int>(pos.x + type.TileWidth + this->Distance + 1, Map.Info.MapWidth);
pos2.y = std::min<int>(pos.y + type.TileHeight + this->Distance + 1, Map.Info.MapHeight);
distance = this->Distance - 1;
}
std::vector<CUnit *> table;
Select(pos1, pos2, table);
for (size_t i = 0; i != table.size(); ++i) {
if ((builder != table[i] || this->CheckBuilder) &&
// unit has RestrictType or no RestrictType was set, but a RestrictTypeOwner
(this->RestrictType == table[i]->Type || (!this->RestrictType && this->RestrictTypeOwner.size() > 0)) &&
// RestrictTypeOwner is not set or unit belongs to a suitable player
(this->RestrictTypeOwner.size() == 0 ||
(!this->RestrictTypeOwner.compare("self") && builder->Player == table[i]->Player) ||
(!this->RestrictTypeOwner.compare("allied") && (builder->Player == table[i]->Player || builder->Player->IsAllied(*table[i]->Player))) ||
(!this->RestrictTypeOwner.compare("enemy") && builder->Player->IsEnemy(*table[i]->Player)))) {
switch (this->DistanceType) {
case GreaterThan:
case GreaterThanEqual:
break;
case LessThan:
case LessThanEqual:
if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) <= distance) {
count++;
}
break;
case Equal:
if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) == distance) {
count++;
}
break;
case NotEqual:
if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) == distance) {
count++;
}
break;
}
}
}
switch (this->CountType)
{
case LessThan: return count < this->Count;
case LessThanEqual: return count <= this->Count;
case Equal: return count == this->Count;
case NotEqual: return count != this->Count;
case GreaterThanEqual: return count >= this->Count;
case GreaterThan: return count > this->Count;
default: return false;
}
}
inline bool CBuildRestrictionAddOn::functor::operator()(const CUnit *const unit) const
{
return (unit->Type == Parent && unit->tilePos == this->pos);

View file

@ -268,6 +268,8 @@ static void ParseBuildingRules(lua_State *l, std::vector<CBuildRestriction *> &b
b->RestrictTypeOwner = LuaToString(l, -1);
} else if (!strcmp(value, "CheckBuilder")) {
b->CheckBuilder = LuaToBoolean(l, -1);
} else if (!strcmp(value, "Diagonal")) {
b->Diagonal = LuaToBoolean(l, -1);
} else {
LuaError(l, "Unsupported BuildingRules distance tag: %s" _C_ value);
}
@ -340,6 +342,69 @@ static void ParseBuildingRules(lua_State *l, std::vector<CBuildRestriction *> &b
}
}
andlist->push_back(b);
}
else if (!strcmp(value, "surrounded-by")) {
CBuildRestrictionSurroundedBy *b = new CBuildRestrictionSurroundedBy;
for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
value = LuaToString(l, -2);
if (!strcmp(value, "Type")) {
b->RestrictTypeName = LuaToString(l, -1);
} else if (!strcmp(value, "Count")) {
b->Count = LuaToNumber(l, -1);
} else if (!strcmp(value, "CountType")) {
value = LuaToString(l, -1);
if (value[0] == '=') {
if ((value[1] == '=' && value[2] == '\0') || (value[1] == '\0')) {
b->CountType = Equal;
}
} else if (value[0] == '>') {
if (value[1] == '=' && value[2] == '\0') {
b->CountType = GreaterThanEqual;
} else if (value[1] == '\0') {
b->CountType = GreaterThan;
}
} else if (value[0] == '<') {
if (value[1] == '=' && value[2] == '\0') {
b->CountType = LessThanEqual;
} else if (value[1] == '\0') {
b->CountType = LessThan;
}
} else if (value[0] == '!' && value[1] == '=' && value[2] == '\0') {
b->CountType = NotEqual;
}
} else if (!strcmp(value, "Distance")) {
b->Distance = LuaToNumber(l, -1);
} else if (!strcmp(value, "DistanceType")) {
value = LuaToString(l, -1);
if (value[0] == '=') {
if ((value[1] == '=' && value[2] == '\0') || (value[1] == '\0')) {
b->DistanceType = Equal;
}
} else if (value[0] == '>') {
if (value[1] == '=' && value[2] == '\0') {
b->DistanceType = GreaterThanEqual;
} else if (value[1] == '\0') {
b->DistanceType = GreaterThan;
}
} else if (value[0] == '<') {
if (value[1] == '=' && value[2] == '\0') {
b->DistanceType = LessThanEqual;
} else if (value[1] == '\0') {
b->DistanceType = LessThan;
}
} else if (value[0] == '!' && value[1] == '=' && value[2] == '\0') {
b->DistanceType = NotEqual;
}
} else if (!strcmp(value, "Owner")) {
b->RestrictTypeOwner = LuaToString(l, -1);
} else if (!strcmp(value, "CheckBuilder")) {
b->CheckBuilder = LuaToBoolean(l, -1);
} else {
LuaError(l, "Unsupported BuildingRules surrounded-by tag: %s" _C_ value);
}
}
andlist->push_back(b);
} else {
LuaError(l, "Unsupported BuildingRules tag: %s" _C_ value);
}