Значить все таки значение. Ну ок, буду знать.
Все таки я добил это отражение на один отряд. Не думал, что у меня получится это сделать. Причем сделал так, как описывал. То есть у нас есть массив (вектор) значений с силой каждого стека, отсортированный по убыванию с сохраненим индексов. В x[i].first хранится боевая мощь отряда, а в x[i].second - порядковый номер отряда. После сортировки в x[0].second - хранится порядковый номер самого сильного отряда, x[1].second - второго по силе и тд. При выборе отряда мы также проверяем наш отряд на то, являестя ли он Черным драконом или Элементалем магии или наложена ли на него Антимагия, и если да, то переходим к следующему по силе отряду.
- Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "HotA\homm3.h"
#include <utility>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;
struct SpellDesc
{
char* DefaultDesc;
char* BasicDesc;
char* AdvancedDesc;
char* ExpertDesc;
};
SpellDesc NewMagicMirror =
{
"{Магическое зеркало}\n\nЦелевой отряд способен отразить вражеское заклинание на самый сильный отряд противника (вместо случайного) с вероятностью в 50%.",
"{Базовое Магическое зеркало}\n\nЦелевой отряд способен отразить вражеское заклинание на самый сильный отряд противника (вместо случайного) с вероятностью в 50%.",
"{Продвинутое Магическое зеркало}\n\nЦелевой отряд способен отразить вражеское заклинание на самый сильный отряд противника (вместо случайного).",
"{Экспертное Магическое зеркало}\n\nВсе дружественные отряды способны отразить вражеское заклинание на все или самые сильные отряды противника (вместо случайного)."
};
int __stdcall afterInit(LoHook* h, HookContext* c)
{
o_Spell[SPL_MAGIC_MIRROR].effect[0] = 40;
o_Spell[SPL_MAGIC_MIRROR].effect[1] = 40;
o_Spell[SPL_MAGIC_MIRROR].effect[2] = 50;
o_Spell[SPL_MAGIC_MIRROR].effect[3] = 50;
*(SpellDesc*)(o_Spell + SPL_MAGIC_MIRROR)->description = NewMagicMirror;
return EXEC_DEFAULT;
}
bool my_cmp(const pair<int, int>& a, const pair<int, int>& b)
{
return a.first > b.first;
}
int __stdcall NewTarget(LoHook* h, HookContext* c)
{
int pos = 0;
vector <pair<int, int> > combatPowerOfStacks;
combatPowerOfStacks.resize(o_BattleMgr->stacks_count[o_BattleMgr->current_side]);
for (int i = 0; i < combatPowerOfStacks.size(); ++i)
{
_BattleStack_* stack = &o_BattleMgr->stack[o_BattleMgr->current_side][i];
combatPowerOfStacks[i].first = o_pCreatureInfo[stack->creature_id].fight_value * stack->count_current;
combatPowerOfStacks[i].second = i;
}
sort(combatPowerOfStacks.begin(), combatPowerOfStacks.end(), my_cmp);
for (int i = 0; i < combatPowerOfStacks.size(); ++i)
{
_BattleStack_* stack = &o_BattleMgr->stack[o_BattleMgr->current_side][combatPowerOfStacks[i].second];
if (stack->creature_id == CID_BLACK_DRAGON || stack->creature_id == CID_MAGIC_ELEMENTAL || stack->active_spell_duration[SPL_ANTI_MAGIC]) continue; else
{
pos = combatPowerOfStacks[i].second;
break;
}
}
c->eax = (int)&o_BattleMgr->stack[o_BattleMgr->current_side][pos];
return EXEC_DEFAULT;
}
char __stdcall IsSpellSingleTarget(HiHook *h, int spell, int ssLevel)
{
if (spell == SPL_MAGIC_MIRROR && ssLevel == 3) return FALSE; else
return CALL_2(char, __fastcall, h->GetDefaultFunc(), spell, ssLevel);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (DLL_PROCESS_ATTACH == ul_reason_for_call)
{
if (!plugin_On)
{
plugin_On = 1;
_P = GetPatcher();
_PI = _P->CreateInstance("HD.Plugin.NewMagicMirror");
_PI->WriteHiHook(0x59E360, SPLICE_, EXTENDED_, FASTCALL_, IsSpellSingleTarget);
_PI->WriteLoHook(0x4EE1C1, afterInit);
_PI->WriteLoHook(0x5A05CC, NewTarget);
}
}
return TRUE;
}
Проверить заклинания, которые висят на отряде, можно через тот же _BattleStack_. ID заклинания в *(int*)(c->ebp + 8).
Не пригодилось.
* OK. Кое-что, требующееся для решения задачи, Вам неизвестно, но я предлагаю хотя бы понять, что именно Вам неизвестно.
А что вы здесь имели ввиду? Вроде бы все было известно, ничего больше не понадобилось.
Попробуйте для начала самостоятельно реализовать перенаправление для одного стека. А потом, может быть, разберёмся и с массовым.
Ну что ж свою часть работы я с горем пополам, но выполнил, теперь ваша очередь. AI пока не трогаем.
Задача усложняется для Экспертного уровня, ведь здесь уже все отряды под Зеркалом.
Плюс в оригинале есть такой баг, хотя не уверен баг ли это. В общем когда мы кастуем закл, например, Замедление на одно вражеское существо под Зеркалом, то оно срабытывает, а вот если мы кастуем массовый спелл (например, Замедление) на все вражеские отряды, среди которых есть отряд под Зеркалом, то на него тоже этот спелл всегда накладывается, хотя по идее должен отражатся. Это, конечно, было бы неплохо исправить.
На Эксперте у нас 3 случая:
1) Когда кол-во отрядов героя РАВНО кол-ву отрядов противника. Тут все просто и вычислять ничего ненужно, только реализовать отражение все на все.
2) Когда кол-во отрядов героя СТРОГО БОЛЬШЕ кол-ва отрядов противника. Тут как бы хотелось бы сделать так, чтобы часть отрядов просто отражала накладываемый спелл, получается в никуда, а вот та часть, которая соответствует кол-ву отрядов противника, отражала как раз на вражеские отряды.
3) Когда кол-во отрядов героя СТРОГО МЕНЬШЕ кол-ва отрядов противника. И самое сложное: вот здесь нам нужно уже будет при отражении из имеющегося кол-ва отрядов противника выбрать такое кол-во самых сильных вражеских отрядов, которое будет соответствует кол-ву отрядов героя. Получается нам нужно изначально вычислить массив (длинной в кол-во отрядов противника) с силой отрядов противника, после отсортировать его по убыванию коэф и взять первые N-значений, где N - кол-во отрядов в войске нашего героя.