[+] Added autocast by variable priority (heal the wounded ones, bloodlust for strong ones...)

This commit is contained in:
cybermind 2013-02-10 13:47:03 +06:00
parent 102a369dcf
commit 82eed1ab1f
3 changed files with 66 additions and 14 deletions

View file

@ -164,11 +164,17 @@ public:
class AutoCastInfo
{
public:
AutoCastInfo() : Range(0), Condition(0), Combat(0) {};
// Special flags for priority sorting
#define ACP_NOVALUE -1
#define ACP_DISTANCE -2
AutoCastInfo() : Range(0), Condition(0), Combat(0), PriorytyVar(ACP_NOVALUE), ReverseSort(false) {};
~AutoCastInfo() { delete Condition; };
/// @todo this below is SQUARE!!!
int Range; /// Max range of the target.
int PriorytyVar; /// Variable to sort autocast targets by priority.
bool ReverseSort; /// If true, small values have the highest priority.
ConditionInfo *Condition; /// Conditions to cast the spell.
/// Detalied generic conditions (not per-target, where Condition is evaluated.)

View file

@ -242,6 +242,30 @@ static void CclSpellAutocast(lua_State *l, AutoCastInfo *autocast)
lua_rawgeti(l, -1, j + 1);
autocast->Combat = Ccl2Condition(l, LuaToString(l, -1));
lua_pop(l, 1);
} else if (!strcmp(value, "priority")) {
lua_rawgeti(l, -1, j + 1);
if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 2) {
LuaError(l, "incorrect argument");
}
lua_rawgeti(l, -1, 1);
std::string var = LuaToString(l, -1);
int index = UnitTypeVar.VariableNameLookup[var.c_str()];// User variables
if (index == -1) {
if (!strcmp(var.c_str(), "Distance")) {
index = ACP_DISTANCE;
} else {
fprintf(stderr, "Bad variable name '%s'\n", var.c_str());
Exit(1);
}
}
autocast->PriorytyVar = index;
lua_pop(l, 1);
lua_rawgeti(l, -1, 2);
autocast->ReverseSort = LuaToBoolean(l, -1);
lua_pop(l, 1);
lua_pop(l, 1);
} else if (!strcmp(value, "condition")) {
if (!autocast->Condition) {
autocast->Condition = new ConditionInfo;

View file

@ -187,6 +187,32 @@ static bool PassCondition(const CUnit &caster, const SpellType &spell, const CUn
return true;
}
class AutoCastPrioritySort
{
public:
explicit AutoCastPrioritySort(const CUnit &caster, const int var, const bool reverse) :
caster(caster), variable(var), reverse(reverse) {}
bool operator()(const CUnit *lhs, const CUnit *rhs) const {
if (variable == ACP_DISTANCE) {
if (reverse) {
return lhs->MapDistanceTo(caster) > rhs->MapDistanceTo(caster);
} else {
return lhs->MapDistanceTo(caster) < rhs->MapDistanceTo(caster);
}
} else {
if (reverse) {
return lhs->Variable[variable].Value > rhs->Variable[variable].Value;
} else {
return lhs->Variable[variable].Value < rhs->Variable[variable].Value;
}
}
}
private:
const CUnit &caster;
const int variable;
const bool reverse;
};
/**
** Select the target for the autocast.
**
@ -263,21 +289,17 @@ static Target *SelectTargetUnitsOfAutoCast(CUnit &caster, const SpellType &spell
}
}
// Now select the best unit to target.
// FIXME: Some really smart way to do this.
// FIXME: Heal the unit with the lowest hit-points
// FIXME: Bloodlust the unit with the highest hit-point
// FIMXE: it will survive more
if (n != 0) {
#if 0
// For the best target???
sort(table, n, spell.autocast->f_order);
return NewTargetUnit(*table[0]);
#else
// Best unit, random unit, oh well, same stuff.
int index = SyncRand() % n;
return NewTargetUnit(*table[index]);
#endif
}
if (autocast->PriorytyVar != ACP_NOVALUE) {
std::sort(table.begin(), table.begin() + n,
AutoCastPrioritySort(caster, autocast->PriorytyVar, autocast->ReverseSort));
return NewTargetUnit(*table[0]);
} else { // Use the old behavior
return NewTargetUnit(*table[SyncRand() % n]);
}
}
break;
}
default: