25.04.2025, 15:39
(25.04.2025 15:23)Barin Wrote: [ -> ]В данном конкретном случае, я на ERA 3.9.26 and HD 5.5 R53
Сделал отдельный деф, но с 6-ю символами получил ошибку. Сделал 5 символов - всё заработало.
У меня ERA 3.9.21 и HD 5.4 R84. Правда сами дефы добавлены в качестве новых, без замен. Лошадки привязаны к типу и полу героев в коде самой игре, но можно привязать их и к номеру героя (тогда придётся сделать 255 def-ов). Надо точнее узавать у Берсеркера как он меняет данные структуры загруженного def-а на лету во время выпаления RedirectFile.
Например хотовцы проделывают такую чёрную магию у себя в hota.dll для подмены def-а, к примеру, чтобы работала абилка Коатля, где он из стека превращается в препятствие и наоборот:
Code:
// Загрузка и установка нового def`а по имени, а так же установление безопасных текущих группы, кадра и границ изображения для него.
// Старый def удаляется автоматически.
inline void SetNewDef(char* DefName)
{
// Удаляем старый def.
this->DeleteDef();
// Загружаем новый def.
this->Def = _Def_::Load(DefName);
// Обнуляем параметры def`а, если они стали некорректны.
if (this->Def->groups_count > this->CurrDefGroup && ((DWORD*)(this->Def->active_groups))[this->CurrDefGroup])
{
if (this->Def->groups[this->CurrDefGroup]->frames_count <= this->CurrFrame)
{
this->CurrFrame = 0;
}
}
else
{
this->CurrDefGroup = 0;
this->CurrFrame = 0;
}
if (this->Img_Width != SIZE_FULL && (this->Img_Def_X < 0 || this->Img_Def_X >= this->Def->width
|| this->Img_Def_X + this->Img_Width < 0 || this->Img_Def_X + this->Img_Width >= this->Def->width))
{
this->Img_Def_X = 0;
this->Img_Width = SIZE_FULL;
}
if (this->Img_Height != SIZE_FULL && (this->Img_Def_Y < 0 || this->Img_Def_Y >= this->Def->height
|| this->Img_Def_Y + this->Img_Height < 0 || this->Img_Def_Y + this->Img_Height >= this->Def->height))
{
this->Img_Def_Y = 0;
this->Img_Height = SIZE_FULL;
}
}
Ну и вот аналог из era.dll:
Code:
procedure RedirectFile (const OldFileName, NewFileName: string);
var
Redirection: TString;
begin
{!} Windows.EnterCriticalSection(RedirCritSection);
if NewFileName = '' then begin
if OldFileName = '' then begin
LodRedirs.Clear;
end else begin
LodRedirs.DeleteItem(OldFileName);
end;
end else begin
Redirection := LodRedirs[OldFileName];
if Redirection = nil then begin
LodRedirs[OldFileName] := TString.Create(NewFileName);
end else begin
Redirection.Value := NewFileName;
end;
end; // .else
{!} Windows.LeaveCriticalSection(RedirCritSection);
end; // .procedure RedirectFile
(25.04.2025 15:10)Berserker Wrote: [ -> ]Это такой хитрый способ экономить ресурсы или держать в памяти отдельные изображения, отгрузив всё остальное. Не знаю, насколько он практичен и используется ли где игрой доступ именно к конкретному кадру по имени.
Да, разработчики так экономили память. Спрайт проверяется на присутствие в памяти по имени и если он там уже есть - его повторная загрузка пропускается, сам спрайт берётся из числа ранее загруженных, к нему при этом ещё и прикручивается палитра от загружаемого def-а. В ERA+ я сталкивался с кучей графических косяков из-за этого - приходилось всё переименовывать.
(25.04.2025 15:10)Berserker Wrote: [ -> ]Если нет, можно было бы сделать реализацию с генерацией случайного имени в процессе выполнения и решить эту проблему навсегда. Херомант, что думаешь?
Вряд ли стоит лезть так глубоко в движок. Проще сгенерировать уникальный абырвалг в самом def-е раз и навсегда, нежели париться с памятью самой игры. Те же хотовцы пошли ещё дальше - у них сейчас в тренде длинные имена в def-ах, из-за чего прога ГрейФейса не может их нормально распаковать, т.к. ГрейФейс похоже не догадывался о таком трюке в def-е и сам лимитировал имя прайта в def, хотя в самой игре на имя - обычный лимит на строку в 512.