- option for Distance building rule to not count diagonally. - add surrounded-by distance rule
This commit is contained in:
parent
6a1f22268f
commit
926e64502c
3 changed files with 165 additions and 5 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue