From 82eed1ab1f2e08633c5f7a7fc09824b6e8037b37 Mon Sep 17 00:00:00 2001 From: cybermind <iddqd_mail@mail.ru> Date: Sun, 10 Feb 2013 13:47:03 +0600 Subject: [PATCH] [+] Added autocast by variable priority (heal the wounded ones, bloodlust for strong ones...) --- src/include/spells.h | 8 ++++++- src/spell/script_spell.cpp | 24 +++++++++++++++++++ src/spell/spells.cpp | 48 +++++++++++++++++++++++++++----------- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/include/spells.h b/src/include/spells.h index c934c6e59..6a792ccdc 100644 --- a/src/include/spells.h +++ b/src/include/spells.h @@ -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.) diff --git a/src/spell/script_spell.cpp b/src/spell/script_spell.cpp index 01a848629..60b04f351 100644 --- a/src/spell/script_spell.cpp +++ b/src/spell/script_spell.cpp @@ -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; diff --git a/src/spell/spells.cpp b/src/spell/spells.cpp index 69693fc7b..9c4173fbd 100644 --- a/src/spell/spells.cpp +++ b/src/spell/spells.cpp @@ -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: