Список форумов Форум Лиги Героев — HeroesLeague Forum Форум Лиги Героев — HeroesLeague Forum
Турниры и обсуждение игр серии Heroes of Might and Magic
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 

Работа со скриптами

 
Начать новую тему   Ответить на тему    Список форумов Форум Лиги Героев — HeroesLeague Forum -> Общие вопросы по Heroes V — General Discussion
Предыдущая тема :: Следующая тема  
Автор Сообщение
Nargott
Ведущий WGE - HoMM5 WGE Master
Ведущий WGE - HoMM5 WGE Master



Зарегистрирован: 11.12.2010
Сообщения: 2688
Откуда: Хабаровск

СообщениеДобавлено: 17 Апр 2013, 01:32    Заголовок сообщения: Работа со скриптами      Ответить с цитатой

В данной теме предлагаю опытным скриптовикам делиться своими наработками, выкладывая те или иные реализованные ими сложные скрипты, выполняющие какие-либо полезные/интересные вещи. Чтобы менее опытные могли что-то перенять и чему-то у них научиться.

Также здесь собираются нетривиальные вопросы на тему, как реализовать ту или иную идею в скриптах, и приветствуется обсуждение возможных путей решения, минимизации побочных эффектов и т.д.
_________________
Автор HoMM 5.5 WGE / WGT 1.23 и Асимметричных шахмат
Стрим GG
YouTube
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Nargott
Ведущий WGE - HoMM5 WGE Master
Ведущий WGE - HoMM5 WGE Master



Зарегистрирован: 11.12.2010
Сообщения: 2688
Откуда: Хабаровск

СообщениеДобавлено: 17 Апр 2013, 01:33    Заголовок сообщения:      Ответить с цитатой

Как реализовать через скрипты следующие вещи?

1) Перестройка городов на старте игры.
Для чего: ИРМГ генерирует некрасивые карты, а стандартный ГСК генерирует все города только 2 уровня с построенной таверной.
Нужно:
- первому игроку стартовый город 4 уровня (скажем, форт, таверна и жилище-1);
- всем последующим игрокам стартовый город 4 уровня плюс, вероятно, дополнительная постройка (жилище-2) - до 5 уровня, шанс зависит от номера игрока и равен 100% для последнего игрока
- все нейтральные города получают 6 уровень (скажем, форт-цитадель, жилище-1,2,3)
Проблема:
- Как перебрать города, существующие на карте, если их имена заранее неизвестны?
Придётся ли перебирать все существующие имена городов, прописанные в ресурсах игры на предмет их наличия на карте?

2) Забор хода у героев при встрече или после боя.
Для чего: запрет цепочек, лимит боёв.
Нужно:
- Забирать у героя 50% полного хода после сыгранной битвы (как в Disciples 2), если остаток хода героя меньше - забирать весь остаток хода. В идеале забирать только в том случае, если нейтралы не были отпущены без боя.
- При встрече дружественных героев выравнивать их остаток хода по минимуму (т.е. устанавливать остаток хода обоих героев равным наименьшему остатку хода среди них). При посещении героем гарнизонов шахт обнулять его ход (в идеале - только гарнизонов, чтобы ход не терялся при захвате шахты) - запрет шахтерских цепочек.
Проблемы:
- Как отследить факт проведения битвы (что-то типа триггера)?
- Как отследить факт встречи героев или посещения гарнизона?

Ап: первая проблема решилась, оказалось что "нерабочая" функция GetObjectNamesByType() оказалась рабочей, ошибка была в мануале и лишней букве s в имени переменной.
_________________
Автор HoMM 5.5 WGE / WGT 1.23 и Асимметричных шахмат
Стрим GG
YouTube
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Nargott
Ведущий WGE - HoMM5 WGE Master
Ведущий WGE - HoMM5 WGE Master



Зарегистрирован: 11.12.2010
Сообщения: 2688
Откуда: Хабаровск

СообщениеДобавлено: 18 Апр 2013, 21:44    Заголовок сообщения:      Ответить с цитатой

Буду публиковать здесь свои скриптовые разработки для WGE в качестве "библиотек" кода. Функции или классы, представленные здесь, могут быть полезными при разработке и других модов с использованием скриптов (в частности, ТЕ-мода). В свою очередь, рассчитываю на то, что скриптовики ТЕ в данной теме также будут делиться своими наработками в доступной форме.

init-exe.lua
Класс, через который запускаются все остальные новые скрипты.
Код:
-- Аналоги true/false
YES = 1
NO = 0

doFile("/scripts/wge/list-dll.lua")
doFile("/scripts/wge/dwelling-growth-dll.lua")
doFile("/scripts/wge/towntype-building-list-dll.lua")
doFile("/scripts/wge/start-game-rebuilding-exe.lua")
doFile("/scripts/wge/building-code-dll.lua")
doFile("/scripts/wge/dwelling-boost-exe.lua")


list-dll.lua
Класс работы со списками
Код:
-- Печать массива в консоль (для отладки)
function printList(array)
   print("List:")
   for i, element in array do
      print("[", i, "] = ", element)
   end
end

-- Поиск элемента в массиве
function indexOf(array, targetElement)
   local index = -1
   for i, currentElement in array do
      if (currentElement == targetElement) then
         index = i
         break
      end
   end
   return index
end

-- Добавление элемента в массив
function push(array, element)
   local lastIndex = length(array)
   array[lastIndex] = element
end

-- Получение копии массива
function copyList(array)
   local arrayCopy = {}
   for i, element in array do
      arrayCopy[i] = array[i]
   end
   return arrayCopy
end

-- Извлечение элемента из массива, возвращает новый массив
function getSlice(array, sliceIndex)
   local lastIndex = length(array) - 1
   local resultArray = { }
   for i = 0, sliceIndex - 1 do
      push(resultArray, array[i])
   end
   for i = sliceIndex, lastIndex - 1 do
      push(resultArray, array[i + 1])
   end
   return resultArray
end

-- Обрезка массива
function getCut(array, leftIndex, rightIndex)
   local resultArray = {}
   for i = leftIndex, rightIndex do
      push(resultArray, array[i])
   end
   return resultArray
end


dwelling-growth-dll.lua
Класс, в котором задаётся информация о приростах существ (приросты расставлены в соответствии с WGE)
Код:
-- Уровни жилищ существ
DWELLING_LEVEL_1 = 1
DWELLING_LEVEL_2 = 2
DWELLING_LEVEL_3 = 3
DWELLING_LEVEL_4 = 4
DWELLING_LEVEL_5 = 5
DWELLING_LEVEL_6 = 6
DWELLING_LEVEL_7 = 7

-- Приросты от жилищ существ Замка
GROWTH_CASTLE_DWELLING_1 = 24
GROWTH_CASTLE_DWELLING_2 = 16
GROWTH_CASTLE_DWELLING_3 = 12
GROWTH_CASTLE_DWELLING_4 = 6
GROWTH_CASTLE_DWELLING_5 = 6
GROWTH_CASTLE_DWELLING_6 = 4
GROWTH_CASTLE_DWELLING_7 = 2

-- Приросты от жилищ существ Оплота
GROWTH_RAMPART_DWELLING_1 = 16
GROWTH_RAMPART_DWELLING_2 = 8
GROWTH_RAMPART_DWELLING_3 = 6
GROWTH_RAMPART_DWELLING_4 = 4
GROWTH_RAMPART_DWELLING_5 = 4
GROWTH_RAMPART_DWELLING_6 = 2
GROWTH_RAMPART_DWELLING_7 = 1

-- Приросты от жилищ существ Академии
GROWTH_ACADEMY_DWELLING_1 = 18
GROWTH_ACADEMY_DWELLING_2 = 10
GROWTH_ACADEMY_DWELLING_3 = 8
GROWTH_ACADEMY_DWELLING_4 = 6
GROWTH_ACADEMY_DWELLING_5 = 2
GROWTH_ACADEMY_DWELLING_6 = 1
GROWTH_ACADEMY_DWELLING_7 = 1

-- Приросты от жилищ существ Темницы
GROWTH_DUNGEON_DWELLING_1 = 12
GROWTH_DUNGEON_DWELLING_2 = 8
GROWTH_DUNGEON_DWELLING_3 = 6
GROWTH_DUNGEON_DWELLING_4 = 6
GROWTH_DUNGEON_DWELLING_5 = 1
GROWTH_DUNGEON_DWELLING_6 = 4
GROWTH_DUNGEON_DWELLING_7 = 1

-- Приросты от жилищ существ Некрополиса
GROWTH_NECROPOLIS_DWELLING_1 = 20
GROWTH_NECROPOLIS_DWELLING_2 = 20
GROWTH_NECROPOLIS_DWELLING_3 = 8
GROWTH_NECROPOLIS_DWELLING_4 = 4
GROWTH_NECROPOLIS_DWELLING_5 = 2
GROWTH_NECROPOLIS_DWELLING_6 = 2
GROWTH_NECROPOLIS_DWELLING_7 = 2

-- Приросты от жилищ существ Инферно
GROWTH_INFERNO_DWELLING_1 = 32
GROWTH_INFERNO_DWELLING_2 = 18
GROWTH_INFERNO_DWELLING_3 = 12
GROWTH_INFERNO_DWELLING_4 = 8
GROWTH_INFERNO_DWELLING_5 = 4
GROWTH_INFERNO_DWELLING_6 = 3
GROWTH_INFERNO_DWELLING_7 = 1

-- Приросты от жилищ существ Крепости
GROWTH_FORTRESS_DWELLING_1 = 14
GROWTH_FORTRESS_DWELLING_2 = 14
GROWTH_FORTRESS_DWELLING_3 = 6
GROWTH_FORTRESS_DWELLING_4 = 10
GROWTH_FORTRESS_DWELLING_5 = 6
GROWTH_FORTRESS_DWELLING_6 = 3
GROWTH_FORTRESS_DWELLING_7 = 1

-- Приросты от жилищ существ Цитадели
GROWTH_STRONGHOLD_DWELLING_1 = 28
GROWTH_STRONGHOLD_DWELLING_2 = 12
GROWTH_STRONGHOLD_DWELLING_3 = 10
GROWTH_STRONGHOLD_DWELLING_4 = 8
GROWTH_STRONGHOLD_DWELLING_5 = 4
GROWTH_STRONGHOLD_DWELLING_6 = 4
GROWTH_STRONGHOLD_DWELLING_7 = 1

-- Получение прироста существ Замка по уровню жилища
function getCastleCreatureGrowth(dwellingLevel)
   local creatureGrowth
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureGrowth = GROWTH_CASTLE_DWELLING_1
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureGrowth = GROWTH_CASTLE_DWELLING_2
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureGrowth = GROWTH_CASTLE_DWELLING_3
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureGrowth = GROWTH_CASTLE_DWELLING_4
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureGrowth = GROWTH_CASTLE_DWELLING_5
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureGrowth = GROWTH_CASTLE_DWELLING_6
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureGrowth = GROWTH_CASTLE_DWELLING_7
   end
   return creatureGrowth
end

-- Получение прироста существ Оплота по уровню жилища
function getRampartCreatureGrowth(dwellingLevel)
   local creatureGrowth
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureGrowth = GROWTH_RAMPART_DWELLING_1
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureGrowth = GROWTH_RAMPART_DWELLING_2
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureGrowth = GROWTH_RAMPART_DWELLING_3
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureGrowth = GROWTH_RAMPART_DWELLING_4
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureGrowth = GROWTH_RAMPART_DWELLING_5
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureGrowth = GROWTH_RAMPART_DWELLING_6
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureGrowth = GROWTH_RAMPART_DWELLING_7
   end
   return creatureGrowth
end

-- Получение прироста существ Академии по уровню жилища
function getAcademyCreatureGrowth(dwellingLevel)
   local creatureGrowth
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureGrowth = GROWTH_ACADEMY_DWELLING_1
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureGrowth = GROWTH_ACADEMY_DWELLING_2
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureGrowth = GROWTH_ACADEMY_DWELLING_3
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureGrowth = GROWTH_ACADEMY_DWELLING_4
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureGrowth = GROWTH_ACADEMY_DWELLING_5
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureGrowth = GROWTH_ACADEMY_DWELLING_6
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureGrowth = GROWTH_ACADEMY_DWELLING_7
   end
   return creatureGrowth
end

-- Получение прироста существ Темницы по уровню жилища
function getDungeonCreatureGrowth(dwellingLevel)
   local creatureGrowth
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureGrowth = GROWTH_DUNGEON_DWELLING_1
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureGrowth = GROWTH_DUNGEON_DWELLING_2
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureGrowth = GROWTH_DUNGEON_DWELLING_3
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureGrowth = GROWTH_DUNGEON_DWELLING_4
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureGrowth = GROWTH_DUNGEON_DWELLING_5
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureGrowth = GROWTH_DUNGEON_DWELLING_6
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureGrowth = GROWTH_DUNGEON_DWELLING_7
   end
   return creatureGrowth
end

-- Получение прироста существ Некрополя по уровню жилища
function getNecropolisCreatureGrowth(dwellingLevel)
   local creatureGrowth
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureGrowth = GROWTH_NECROPOLIS_DWELLING_1
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureGrowth = GROWTH_NECROPOLIS_DWELLING_2
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureGrowth = GROWTH_NECROPOLIS_DWELLING_3
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureGrowth = GROWTH_NECROPOLIS_DWELLING_4
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureGrowth = GROWTH_NECROPOLIS_DWELLING_5
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureGrowth = GROWTH_NECROPOLIS_DWELLING_6
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureGrowth = GROWTH_NECROPOLIS_DWELLING_7
   end
   return creatureGrowth
end

-- Получение прироста существ Инферно по уровню жилища
function getInfernoCreatureGrowth(dwellingLevel)
   local creatureGrowth
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureGrowth = GROWTH_INFERNO_DWELLING_1
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureGrowth = GROWTH_INFERNO_DWELLING_2
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureGrowth = GROWTH_INFERNO_DWELLING_3
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureGrowth = GROWTH_INFERNO_DWELLING_4
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureGrowth = GROWTH_INFERNO_DWELLING_5
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureGrowth = GROWTH_INFERNO_DWELLING_6
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureGrowth = GROWTH_INFERNO_DWELLING_7
   end
   return creatureGrowth
end

-- Получение прироста существ Крепости по уровню жилища
function getFortressCreatureGrowth(dwellingLevel)
   local creatureGrowth
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureGrowth = GROWTH_FORTRESS_DWELLING_1
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureGrowth = GROWTH_FORTRESS_DWELLING_2
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureGrowth = GROWTH_FORTRESS_DWELLING_3
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureGrowth = GROWTH_FORTRESS_DWELLING_4
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureGrowth = GROWTH_FORTRESS_DWELLING_5
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureGrowth = GROWTH_FORTRESS_DWELLING_6
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureGrowth = GROWTH_FORTRESS_DWELLING_7
   end
   return creatureGrowth
end

-- Получение прироста существ Цитадели по уровню жилища
function getStrongholdCreatureGrowth(dwellingLevel)
   local creatureGrowth
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureGrowth = GROWTH_STRONGHOLD_DWELLING_1
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureGrowth = GROWTH_STRONGHOLD_DWELLING_2
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureGrowth = GROWTH_STRONGHOLD_DWELLING_3
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureGrowth = GROWTH_STRONGHOLD_DWELLING_4
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureGrowth = GROWTH_STRONGHOLD_DWELLING_5
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureGrowth = GROWTH_STRONGHOLD_DWELLING_6
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureGrowth = GROWTH_STRONGHOLD_DWELLING_7
   end
   return creatureGrowth
end

-- Получение прироста существ по их городу и уровню жилища
function getCreatureGrowth(townType, dwellingLevel)
   local creatureGrowth
   if (townType == TOWN_HEAVEN) then
      creatureGrowth = getCastleCreatureGrowth(dwellingLevel)
   elseif (townType == TOWN_PRESERVE) then
      creatureGrowth = getRampartCreatureGrowth(dwellingLevel)
   elseif (townType == TOWN_ACADEMY) then
      creatureGrowth = getAcademyCreatureGrowth(dwellingLevel)
   elseif (townType == TOWN_DUNGEON) then
      creatureGrowth = getDungeonCreatureGrowth(dwellingLevel)
   elseif (townType == TOWN_NECROMANCY) then
      creatureGrowth = getNecropolisCreatureGrowth(dwellingLevel)
   elseif (townType == TOWN_INFERNO) then
      creatureGrowth = getInfernoCreatureGrowth(dwellingLevel)
   elseif (townType == TOWN_FORTRESS) then
      creatureGrowth = getFortressCreatureGrowth(dwellingLevel)
   elseif (townType == TOWN_STRONGHOLD) then
      creatureGrowth = getStrongholdCreatureGrowth(dwellingLevel)
   end
   return creatureGrowth
end

-- Получение имени существа Замка по уровню жилища
function getCastleCreatureID(dwellingLevel)
   local creatureID
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureID = CREATURE_PEASANT
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureID = CREATURE_ARCHER
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureID = CREATURE_FOOTMAN
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureID = CREATURE_GRIFFIN
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureID = CREATURE_PRIEST
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureID = CREATURE_CAVALIER
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureID = CREATURE_ANGEL
   end
   return creatureID
end

-- Получение имени существа Оплота по уровню жилища
function getRampartCreatureID(dwellingLevel)
   local creatureID
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureID = CREATURE_PIXIE
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureID = CREATURE_BLADE_JUGGLER
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureID = CREATURE_WOOD_ELF
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureID = CREATURE_DRUID
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureID = CREATURE_UNICORN
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureID = CREATURE_TREANT
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureID = CREATURE_GREEN_DRAGON
   end
   return creatureID
end

-- Получение имени существа Академии по уровню жилища
function getAcademyCreatureID(dwellingLevel)
   local creatureID
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureID = CREATURE_GREMLIN
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureID = CREATURE_STONE_GARGOYLE
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureID = CREATURE_IRON_GOLEM
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureID = CREATURE_MAGI
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureID = CREATURE_GENIE
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureID = CREATURE_RAKSHASA
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureID = CREATURE_GIANT
   end
   return creatureID
end

-- Получение имени существа Темницы по уровню жилища
function getDungeonCreatureID(dwellingLevel)
   local creatureID
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureID = CREATURE_SCOUT
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureID = CREATURE_WITCH
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureID = CREATURE_MINOTAUR
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureID = CREATURE_RIDER
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureID = CREATURE_HYDRA
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureID = CREATURE_MATRON
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureID = CREATURE_DEEP_DRAGON
   end
   return creatureID
end

-- Получение имени существа Некрополя по уровню жилища
function getNecropolisCreatureID(dwellingLevel)
   local creatureID
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureID = CREATURE_SKELETON
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureID = CREATURE_WALKING_DEAD
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureID = CREATURE_MANES
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureID = CREATURE_VAMPIRE
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureID = CREATURE_LICH
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureID = CREATURE_WIGHT
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureID = CREATURE_BONE_DRAGON
   end
   return creatureID
end

-- Получение имени существа Инферно по уровню жилища
function getInfernoCreatureID(dwellingLevel)
   local creatureID
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureID = CREATURE_FAMILIAR
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureID = CREATURE_DEMON
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureID = CREATURE_HELL_HOUND
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureID = CREATURE_SUCCUBUS
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureID = CREATURE_NIGHTMARE
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureID = CREATURE_PIT_FIEND
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureID = CREATURE_DEVIL
   end
   return creatureID
end

-- Получение имени существа Крепости по уровню жилища
function getFortressCreatureID(dwellingLevel)
   local creatureID
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureID = CREATURE_DEFENDER
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureID = CREATURE_AXE_FIGHTER
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureID = CREATURE_BEAR_RIDER
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureID = CREATURE_BROWLER
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureID = CREATURE_RUNE_MAGE
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureID = CREATURE_THANE
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureID = CREATURE_FIRE_DRAGON
   end
   return creatureID
end

-- Получение имени существа Цитадели по уровню жилища
function getStrongholdCreatureID(dwellingLevel)
   local creatureID
   if (dwellingLevel == DWELLING_LEVEL_1) then
      creatureID = CREATURE_GOBLIN
   elseif (dwellingLevel == DWELLING_LEVEL_2) then
      creatureID = CREATURE_CENTAUR
   elseif (dwellingLevel == DWELLING_LEVEL_3) then
      creatureID = CREATURE_ORC_WARRIOR
   elseif (dwellingLevel == DWELLING_LEVEL_4) then
      creatureID = CREATURE_SHAMAN
   elseif (dwellingLevel == DWELLING_LEVEL_5) then
      creatureID = CREATURE_ORCCHIEF_BUTCHER
   elseif (dwellingLevel == DWELLING_LEVEL_6) then
      creatureID = CREATURE_WYVERN
   elseif (dwellingLevel == DWELLING_LEVEL_7) then
      creatureID = CREATURE_CYCLOP
   end
   return creatureID
end

-- Получение имени существа по его городу и уровню жилища
function getCreatureID(townType, dwellingLevel)
   local creatureID
   if (townType == TOWN_HEAVEN) then
      creatureID = getCastleCreatureID(dwellingLevel)
   elseif (townType == TOWN_PRESERVE) then
      creatureID = getRampartCreatureID(dwellingLevel)
   elseif (townType == TOWN_ACADEMY) then
      creatureID = getAcademyCreatureID(dwellingLevel)
   elseif (townType == TOWN_DUNGEON) then
      creatureID = getDungeonCreatureID(dwellingLevel)
   elseif (townType == TOWN_NECROMANCY) then
      creatureID = getNecropolisCreatureID(dwellingLevel)
   elseif (townType == TOWN_INFERNO) then
      creatureID = getInfernoCreatureID(dwellingLevel)
   elseif (townType == TOWN_FORTRESS) then
      creatureID = getFortressCreatureID(dwellingLevel)
   elseif (townType == TOWN_STRONGHOLD) then
      creatureID = getStrongholdCreatureID(dwellingLevel)
   end
   return creatureID
end


towntype-building-list-dll.lua
Класс, предоставляющий полные списки строений для городов различных типов
Код:
-- Получение списка всех общих возможных построек
function getCommonTownBuildingList()
   local buildingList = {}
   push(buildingList, TOWN_BUILDING_TOWN_HALL)
   push(buildingList, TOWN_BUILDING_FORT)
   push(buildingList, TOWN_BUILDING_MARKETPLACE)
   push(buildingList, TOWN_BUILDING_SHIPYARD)
   push(buildingList, TOWN_BUILDING_TAVERN)
   push(buildingList, TOWN_BUILDING_BLACKSMITH)
   push(buildingList, TOWN_BUILDING_MAGIC_GUILD)
   push(buildingList, TOWN_BUILDING_DWELLING_1)
   push(buildingList, TOWN_BUILDING_DWELLING_2)
   push(buildingList, TOWN_BUILDING_DWELLING_3)
   push(buildingList, TOWN_BUILDING_DWELLING_4)
   push(buildingList, TOWN_BUILDING_DWELLING_5)
   push(buildingList, TOWN_BUILDING_DWELLING_6)
   push(buildingList, TOWN_BUILDING_DWELLING_7)
   push(buildingList, TOWN_BUILDING_GRAIL)
   return buildingList
end

-- Получение списка всех возможных построек в Замке
function getCastleBuildingList()
   local buildingList = getCommonTownBuildingList()
   push(buildingList, TOWN_BUILDING_HAVEN_TRAINING_GROUNDS)
   push(buildingList, TOWN_BUILDING_HAVEN_MONUMENT_TO_FALLEN_HEROES)
   push(buildingList, TOWN_BUILDING_HAVEN_STABLE)
   push(buildingList, TOWN_BUILDING_HAVEN_FARMS)
   return buildingList
end

-- Получение списка всех возможных построек в Оплоте
function getRampartBuildingList()
   local buildingList = getCommonTownBuildingList()
   push(buildingList, TOWN_BUILDING_PRESERVE_AVENGERS_BROTHERHOOD)
   push(buildingList, TOWN_BUILDING_PRESERVE_MYSTIC_POND)
   push(buildingList, TOWN_BUILDING_PRESERVE_BLOOMING_GROVE)
   push(buildingList, TOWN_BUILDING_PRESERVE_TREANT_SAMPLING)
   return buildingList
end

-- Получение списка всех возможных построек в Академии
function getAcademyBuildingList()
   local buildingList = getCommonTownBuildingList()
   push(buildingList, TOWN_BUILDING_ACADEMY_LIBRARY)
   push(buildingList, TOWN_BUILDING_ACADEMY_ARCANE_FORGE)
   push(buildingList, TOWN_BUILDING_ACADEMY_ARTIFACT_MERCHANT)
   push(buildingList, TOWN_BUILDING_ACADEMY_TREASURE_CAVE)
   return buildingList
end

-- Получение списка всех возможных построек в Темнице
function getDungeonBuildingList()
   local buildingList = getCommonTownBuildingList()
   push(buildingList, TOWN_BUILDING_DUNGEON_ALTAR_OF_ELEMENTS)
   push(buildingList, TOWN_BUILDING_DUNGEON_RITUAL_PIT)
   push(buildingList, TOWN_BUILDING_DUNGEON_TRADE_GUILD)
   push(buildingList, TOWN_BUILDING_DUNGEON_HALL_OF_INTRIGUE)
   return buildingList
end

-- Получение списка всех возможных построек в Некрополе
function getNecropolisBuildingList()
   local buildingList = getCommonTownBuildingList()
   push(buildingList, TOWN_BUILDING_NECROMANCY_AMPLIFIER)
   push(buildingList, TOWN_BUILDING_NECROMANCY_UNHOLY_TEMPLE)
   push(buildingList, TOWN_BUILDING_NECROMANCY_UNEARHED_GRAVES)
   push(buildingList, TOWN_BUILDING_NECROMANCY_DRAGON_TOMBSTONE)
   return buildingList
end

-- Получение списка всех возможных построек в Инферно
function getInfernoBuildingList()
   local buildingList = getCommonTownBuildingList()
   push(buildingList, TOWN_BUILDING_INFERNO_INFERNAL_LOOM)
   push(buildingList, TOWN_BUILDING_INFERNO_ORDER_OF_FIRE)
   push(buildingList, TOWN_BUILDING_INFERNO_HALLS_OF_HORROR)
   push(buildingList, TOWN_BUILDING_INFERNO_SACRIFICIAL_PIT)
   return buildingList
end

-- Получение списка всех возможных построек в Крепости
function getFortressBuildingList()
   local buildingList = getCommonTownBuildingList()
   push(buildingList, TOWN_BUILDING_FORTRESS_RUNIC_SHRINE)
   push(buildingList, TOWN_BUILDING_FORTRESS_ARENA)
   push(buildingList, TOWN_BUILDING_FORTRESS_GUARDPOST)
   push(buildingList, TOWN_BUILDING_FORTRESS_RUNIC_STONEWORKS)
   push(buildingList, TOWN_BUILDING_FORTRESS_RUNIC_ACADEMY)
   return buildingList
end

-- Получение списка всех возможных построек в Цитадели
function getStrongholdBuildingList()
   local buildingList = getCommonTownBuildingList()
   local indexMagicGuild = indexOf(buildingList, TOWN_BUILDING_MAGIC_GUILD)
   if (indexMagicGuild >= 0) then
      buildingList = getSlice(buildingList, indexMagicGuild)
   end
   push(buildingList, TOWN_BUILDING_STRONGHOLD_HALL_OF_TRIAL)
   push(buildingList, TOWN_BUILDING_STRONGHOLD_GARBAGE_PILE)
   push(buildingList, TOWN_BUILDING_STRONGHOLD_TRAVELLERS_SHELTER)
   push(buildingList, TOWN_BUILDING_STRONGHOLD_PILE_OF_OUR_FOES)
   push(buildingList, TOWN_BUILDING_STRONGHOLD_SLAVE_MARKET)
   return buildingList
end

-- Получение списка всех возможных построек в городе заданного типа
function getTownTypeBuildingList(townType)
   local buildingList = {}
   if (townType == TOWN_HEAVEN) then
      buildingList = getCastleBuildingList()
   elseif (townType == TOWN_PRESERVE) then
      buildingList = getRampartBuildingList()
   elseif (townType == TOWN_ACADEMY) then
      buildingList = getAcademyBuildingList()
   elseif (townType == TOWN_DUNGEON) then
      buildingList = getDungeonBuildingList()
   elseif (townType == TOWN_NECROMANCY) then
      buildingList = getNecropolisBuildingList()
   elseif (townType == TOWN_INFERNO) then
      buildingList = getInfernoBuildingList()
   elseif (townType == TOWN_FORTRESS) then
      buildingList = getFortressBuildingList()
   elseif (townType == TOWN_STRONGHOLD) then
      buildingList = getStrongholdBuildingList()
   end
   return buildingList
end


start-game-rebuilding-exe.lua
Исполнительный класс. Выполняет задачу по перестройке всех городов на старте карты в соответствии с прописанными в нём параметрами. Практически необходим для карт от стандартного ГСК, не позволяющего задавать стартовые постройки (по умолчанию ставится лишь таверна). В отличие от ИРМГ, класс позволяет задавать случайную отстройку (в показанном ниже листе используется случайная отстройка жилища 2 уровня для всех игроков, кроме красного).

Для функционирования класса необходимо исправить косяк разрабов, сделанный в advmap-startup.lua (неправильное объявление константы):
Код:
TOWN_BUILDING_INFERNO_ORDER_OF_FIRE = TOWN_BUILDING_SPECIAL_2
- правильный вариант (было TOWN_BUILDING_SPECIAL_3)

Код:
-- Очистка прироста постройки
function clearTownBuildingGrowth(town, baseBuilding)
   local creatureID
   local townType = GetTownRace(town)
   if (baseBuilding == TOWN_BUILDING_DWELLING_1) then
      creatureID = getCreatureID(townType, DWELLING_LEVEL_1)
      SetObjectDwellingCreatures(town, creatureID, 0)
   elseif (baseBuilding == TOWN_BUILDING_DWELLING_2) then
      creatureID = getCreatureID(townType, DWELLING_LEVEL_2)
      SetObjectDwellingCreatures(town, creatureID, 0)
   elseif (baseBuilding == TOWN_BUILDING_DWELLING_3) then
      creatureID = getCreatureID(townType, DWELLING_LEVEL_3)
      SetObjectDwellingCreatures(town, creatureID, 0)
   elseif (baseBuilding == TOWN_BUILDING_DWELLING_4) then
      creatureID = getCreatureID(townType, DWELLING_LEVEL_4)
      SetObjectDwellingCreatures(town, creatureID, 0)
   elseif (baseBuilding == TOWN_BUILDING_DWELLING_5) then
      creatureID = getCreatureID(townType, DWELLING_LEVEL_5)
      SetObjectDwellingCreatures(town, creatureID, 0)
   elseif (baseBuilding == TOWN_BUILDING_DWELLING_6) then
      creatureID = getCreatureID(townType, DWELLING_LEVEL_6)
      SetObjectDwellingCreatures(town, creatureID, 0)
   elseif (baseBuilding == TOWN_BUILDING_DWELLING_7) then
      creatureID = getCreatureID(townType, DWELLING_LEVEL_7)
      SetObjectDwellingCreatures(town, creatureID, 0)      
   end
end

-- Уничтожение здания в городе
function destroyTownBuilding(town, baseBuilding)
   clearTownBuildingGrowth(town, baseBuilding)
   if (baseBuilding == TOWN_BUILDING_TOWN_HALL) then
      DestroyTownBuildingToLevel(town, baseBuilding, 1)
   else
      DestroyTownBuildingToLevel(town, baseBuilding, 0)
   end
end

-- Сброс всех зданий в городе
function resetAllBuildingsInTown(town)
   local townType = GetTownRace(town)
   local townBuildingsList = getTownTypeBuildingList(townType)
   for i, baseBuilding in townBuildingsList do
      destroyTownBuilding(town, baseBuilding)
   end
end

-- Установка уровня здания в городе
function setTownBuildingLevel(town, building, targetLevel)
   local currentLevel = GetTownBuildingLevel(town, building)
   if (currentLevel <= targetLevel) then
      for i = currentLevel, targetLevel do
         UpgradeTownBuilding(town, building)
      end
   else
      DestroyTownBuildingToLevel(town, building, targetLevel)
   end
end

-- Получение числа игроков в игре
function getTotalPlayers()
   local total = 0
   for playerID = PLAYER_1, PLAYER_8 do
      if GetPlayerState(playerID) == PLAYER_ACTIVE then
         total = total + 1
      end
   end
   return total
end

-- Перестройка города игрока (форт, таверна, жилище 1 уровня, иногда жилище 2 уровня)
function rebuildPlayerTown(town)
   resetAllBuildingsInTown(town)
   setTownBuildingLevel(town, TOWN_BUILDING_FORT, 0)
   setTownBuildingLevel(town, TOWN_BUILDING_TAVERN, 1)
   setTownBuildingLevel(town, TOWN_BUILDING_DWELLING_1, 0)
   
   local totalPlayers = getTotalPlayers()
   local townPlayerID = GetObjectOwner(town)
   if (random(totalPlayers - 1) < (townPlayerID - 1)) then
      setTownBuildingLevel(town, TOWN_BUILDING_DWELLING_2, 0)
   end
end

-- Перестройка нейтрального города (цитадель, жилища 1-3 уровней)
function rebuildNeutralTown(town)
   resetAllBuildingsInTown(town)
   setTownBuildingLevel(town, TOWN_BUILDING_FORT, 1)
   setTownBuildingLevel(town, TOWN_BUILDING_DWELLING_1, 0)
   setTownBuildingLevel(town, TOWN_BUILDING_DWELLING_2, 0)
   setTownBuildingLevel(town, TOWN_BUILDING_DWELLING_3, 0)
end

-- ВЫПОЛНЕНИЕ СКРИПТА

-- Получить список городов
local townList = GetObjectNamesByType("TOWN")

-- Для каждого города осуществить перестройку
for i, town in townList do
   if (GetObjectOwner(town) == PLAYER_NONE) then
      rebuildNeutralTown(town)
   else
      rebuildPlayerTown(town)
   end
end


building-code-dll.lua
Класс, оперирующий с "билдинг-кодами" (элементарными постройками), взамен стандартных "билдинг-идов" (многоуровневых построек). С его помощью можно отслеживать факт наличия каких-либо отдельных построек, без заморочек с проверкой уровней.

Код:
-- Коэффициент перевода ID здания в его внутренний код
BUILDING_ID_TO_CODE_COEF = 10

BUILDING_LEVEL_1 = 1
BUILDING_LEVEL_2 = 2
BUILDING_LEVEL_3 = 3
BUILDING_LEVEL_4 = 4
BUILDING_LEVEL_5 = 5

-- Получить код здания по его ID и уровню
function getBuildingCode(buildingID, buildingLevel)
   local buildingCode = BUILDING_ID_TO_CODE_COEF * buildingID + buildingLevel
   return buildingCode
end

-- Получить ID здания по его коду
function getBuildingID(buildingCode)
   local buildingID = intg(buildingCode / BUILDING_ID_TO_CODE_COEF)
   return buildingID
end

-- Получить уровень здание по его коду
function getBuildingLevel(buildingCode)
   local buildingLevel = mod(buildingCode, BUILDING_ID_TO_CODE_COEF)
   return buildingLevel
end

-- Коды базовых общих зданий
TOWN_HALL_1   = getBuildingCode(TOWN_BUILDING_TOWN_HALL, BUILDING_LEVEL_1)
FORT_1      = getBuildingCode(TOWN_BUILDING_FORT, BUILDING_LEVEL_1)
MARKETPLACE_1   = getBuildingCode(TOWN_BUILDING_MARKETPLACE, BUILDING_LEVEL_1)   
SHIPYARD_1   = getBuildingCode(TOWN_BUILDING_SHIPYARD, BUILDING_LEVEL_1)
TAVERN_1   = getBuildingCode(TOWN_BUILDING_TAVERN, BUILDING_LEVEL_1)
BLACKSMITH_1   = getBuildingCode(TOWN_BUILDING_BLACKSMITH, BUILDING_LEVEL_1)
MAGIC_GUILD_1   = getBuildingCode(TOWN_BUILDING_MAGIC_GUILD, BUILDING_LEVEL_1)
DWELLING_1_1   = getBuildingCode(TOWN_BUILDING_DWELLING_1, BUILDING_LEVEL_1)
DWELLING_2_1   = getBuildingCode(TOWN_BUILDING_DWELLING_2, BUILDING_LEVEL_1)
DWELLING_3_1   = getBuildingCode(TOWN_BUILDING_DWELLING_3, BUILDING_LEVEL_1)
DWELLING_4_1   = getBuildingCode(TOWN_BUILDING_DWELLING_4, BUILDING_LEVEL_1)
DWELLING_5_1   = getBuildingCode(TOWN_BUILDING_DWELLING_5, BUILDING_LEVEL_1)
DWELLING_6_1   = getBuildingCode(TOWN_BUILDING_DWELLING_6, BUILDING_LEVEL_1)
DWELLING_7_1   = getBuildingCode(TOWN_BUILDING_DWELLING_7, BUILDING_LEVEL_1)
GRAIL_1      = getBuildingCode(TOWN_BUILDING_GRAIL, BUILDING_LEVEL_1)

-- Коды улучшенных общих зданий
TOWN_HALL_2    = getBuildingCode(TOWN_BUILDING_TOWN_HALL, BUILDING_LEVEL_2)
TOWN_HALL_3    = getBuildingCode(TOWN_BUILDING_TOWN_HALL, BUILDING_LEVEL_3)
TOWN_HALL_4    = getBuildingCode(TOWN_BUILDING_TOWN_HALL, BUILDING_LEVEL_4)
FORT_2      = getBuildingCode(TOWN_BUILDING_FORT, BUILDING_LEVEL_2)
FORT_3      = getBuildingCode(TOWN_BUILDING_FORT, BUILDING_LEVEL_3)
MARKETPLACE_2   = getBuildingCode(TOWN_BUILDING_MARKETPLACE, BUILDING_LEVEL_2)
MAGIC_GUILD_2   = getBuildingCode(TOWN_BUILDING_MAGIC_GUILD, BUILDING_LEVEL_2)
MAGIC_GUILD_3   = getBuildingCode(TOWN_BUILDING_MAGIC_GUILD, BUILDING_LEVEL_3)
MAGIC_GUILD_4   = getBuildingCode(TOWN_BUILDING_MAGIC_GUILD, BUILDING_LEVEL_4)
MAGIC_GUILD_5   = getBuildingCode(TOWN_BUILDING_MAGIC_GUILD, BUILDING_LEVEL_5)
DWELLING_1_2   = getBuildingCode(TOWN_BUILDING_DWELLING_1, BUILDING_LEVEL_2)
DWELLING_2_2   = getBuildingCode(TOWN_BUILDING_DWELLING_2, BUILDING_LEVEL_2)
DWELLING_3_2   = getBuildingCode(TOWN_BUILDING_DWELLING_3, BUILDING_LEVEL_2)
DWELLING_4_2   = getBuildingCode(TOWN_BUILDING_DWELLING_4, BUILDING_LEVEL_2)
DWELLING_5_2   = getBuildingCode(TOWN_BUILDING_DWELLING_5, BUILDING_LEVEL_2)
DWELLING_6_2   = getBuildingCode(TOWN_BUILDING_DWELLING_6, BUILDING_LEVEL_2)
DWELLING_7_2   = getBuildingCode(TOWN_BUILDING_DWELLING_7, BUILDING_LEVEL_2)

-- Коды базовых расовых зданий
CASTLE_TRAINING_GROUNDS_1      = getBuildingCode(TOWN_BUILDING_HAVEN_TRAINING_GROUNDS, BUILDING_LEVEL_1)
CASTLE_MONUMENT_TO_FALLEN_HEROES_1    = getBuildingCode(TOWN_BUILDING_HAVEN_MONUMENT_TO_FALLEN_HEROES, BUILDING_LEVEL_1)
CASTLE_STABLE_1            = getBuildingCode(TOWN_BUILDING_HAVEN_STABLE, BUILDING_LEVEL_1)
CASTLE_FARMS_1             = getBuildingCode(TOWN_BUILDING_HAVEN_FARMS, BUILDING_LEVEL_1)
INFERNO_INFERNAL_LOOM_1         = getBuildingCode(TOWN_BUILDING_INFERNO_INFERNAL_LOOM, BUILDING_LEVEL_1)
INFERNO_ORDER_OF_FIRE_1         = getBuildingCode(TOWN_BUILDING_INFERNO_ORDER_OF_FIRE, BUILDING_LEVEL_1)
INFERNO_HALLS_OF_HORROR_1      = getBuildingCode(TOWN_BUILDING_INFERNO_HALLS_OF_HORROR, BUILDING_LEVEL_1)
INFERNO_SACRIFICIAL_PIT_1      = getBuildingCode(TOWN_BUILDING_INFERNO_SACRIFICIAL_PIT, BUILDING_LEVEL_1)
DUNGEON_ALTAR_OF_ELEMENTS_1       = getBuildingCode(TOWN_BUILDING_DUNGEON_ALTAR_OF_ELEMENTS, BUILDING_LEVEL_1)
DUNGEON_RITUAL_PIT_1          = getBuildingCode(TOWN_BUILDING_DUNGEON_RITUAL_PIT, BUILDING_LEVEL_1)
DUNGEON_TRADE_GUILD_1         = getBuildingCode(TOWN_BUILDING_DUNGEON_TRADE_GUILD, BUILDING_LEVEL_1)
DUNGEON_HALL_OF_INTRIGUE_1       = getBuildingCode(TOWN_BUILDING_DUNGEON_HALL_OF_INTRIGUE, BUILDING_LEVEL_1)
ACADEMY_LIBRARY_1          = getBuildingCode(TOWN_BUILDING_ACADEMY_LIBRARY, BUILDING_LEVEL_1)
ACADEMY_ARCANE_FORGE_1          = getBuildingCode(TOWN_BUILDING_ACADEMY_ARCANE_FORGE, BUILDING_LEVEL_1)
ACADEMY_ARTIFACT_MERCHANT_1      = getBuildingCode(TOWN_BUILDING_ACADEMY_ARTIFACT_MERCHANT, BUILDING_LEVEL_1)
ACADEMY_TREASURE_CAVE_1         = getBuildingCode(TOWN_BUILDING_ACADEMY_TREASURE_CAVE, BUILDING_LEVEL_1)
RAMPART_AVENGERS_BROTHERHOOD_1      = getBuildingCode(TOWN_BUILDING_PRESERVE_AVENGERS_BROTHERHOOD, BUILDING_LEVEL_1)
RAMPART_MYSTIC_POND_1          = getBuildingCode(TOWN_BUILDING_PRESERVE_MYSTIC_POND, BUILDING_LEVEL_1)
RAMPART_BLOOMING_GROVE_1      = getBuildingCode(TOWN_BUILDING_PRESERVE_BLOOMING_GROVE, BUILDING_LEVEL_1)
RAMPART_TREANT_SAMPLING_1       = getBuildingCode(TOWN_BUILDING_PRESERVE_TREANT_SAMPLING, BUILDING_LEVEL_1)
NECROPOLIS_AMPLIFIER_1         = getBuildingCode(TOWN_BUILDING_NECROMANCY_AMPLIFIER, BUILDING_LEVEL_1)
NECROPOLIS_UNHOLY_TEMPLE_1      = getBuildingCode(TOWN_BUILDING_NECROMANCY_UNHOLY_TEMPLE, BUILDING_LEVEL_1)
NECROPOLIS_UNEARHED_GRAVES_1      = getBuildingCode(TOWN_BUILDING_NECROMANCY_UNEARHED_GRAVES, BUILDING_LEVEL_1)
NECROPOLIS_DRAGON_TOMBSTONE_1      = getBuildingCode(TOWN_BUILDING_NECROMANCY_DRAGON_TOMBSTONE, BUILDING_LEVEL_1)
FORTRESS_RUNIC_SHRINE_1          = getBuildingCode(TOWN_BUILDING_FORTRESS_RUNIC_SHRINE, BUILDING_LEVEL_1)
FORTRESS_ARENA_1         = getBuildingCode(TOWN_BUILDING_FORTRESS_ARENA, BUILDING_LEVEL_1)
FORTRESS_GUARDPOST_1          = getBuildingCode(TOWN_BUILDING_FORTRESS_GUARDPOST, BUILDING_LEVEL_1)
FORTRESS_RUNIC_STONEWORKS_1       = getBuildingCode(TOWN_BUILDING_FORTRESS_RUNIC_STONEWORKS, BUILDING_LEVEL_1)
FORTRESS_RUNIC_ACADEMY_1      = getBuildingCode(TOWN_BUILDING_FORTRESS_RUNIC_ACADEMY, BUILDING_LEVEL_1)
STRONGHOLD_HALL_OF_TRIAL_1      = getBuildingCode(TOWN_BUILDING_STRONGHOLD_HALL_OF_TRIAL, BUILDING_LEVEL_1)
STRONGHOLD_GARBAGE_PILE_1      = getBuildingCode(TOWN_BUILDING_STRONGHOLD_GARBAGE_PILE, BUILDING_LEVEL_1)
STRONGHOLD_TRAVELLERS_SHELTER_1      = getBuildingCode(TOWN_BUILDING_STRONGHOLD_TRAVELLERS_SHELTER, BUILDING_LEVEL_1)
STRONGHOLD_PILE_OF_OUR_FOES_1      = getBuildingCode(TOWN_BUILDING_STRONGHOLD_PILE_OF_OUR_FOES, BUILDING_LEVEL_1)
STRONGHOLD_SLAVE_MARKET_1      = getBuildingCode(TOWN_BUILDING_STRONGHOLD_SLAVE_MARKET, BUILDING_LEVEL_1)

-- Коды улучшенных расовых зданий
DUNGEON_ALTAR_OF_ELEMENTS_2       = getBuildingCode(TOWN_BUILDING_DUNGEON_ALTAR_OF_ELEMENTS, BUILDING_LEVEL_2)
RAMPART_AVENGERS_BROTHERHOOD_2      = getBuildingCode(TOWN_BUILDING_PRESERVE_AVENGERS_BROTHERHOOD, BUILDING_LEVEL_2)
RAMPART_MYSTIC_POND_2          = getBuildingCode(TOWN_BUILDING_PRESERVE_MYSTIC_POND, BUILDING_LEVEL_2)
FORTRESS_RUNIC_SHRINE_2       = getBuildingCode(TOWN_BUILDING_FORTRESS_RUNIC_SHRINE, BUILDING_LEVEL_2)
FORTRESS_RUNIC_SHRINE_3       = getBuildingCode(TOWN_BUILDING_FORTRESS_RUNIC_SHRINE, BUILDING_LEVEL_3)
STRONGHOLD_HALL_OF_TRIAL_2      = getBuildingCode(TOWN_BUILDING_STRONGHOLD_HALL_OF_TRIAL, BUILDING_LEVEL_2)
STRONGHOLD_HALL_OF_TRIAL_3      = getBuildingCode(TOWN_BUILDING_STRONGHOLD_HALL_OF_TRIAL, BUILDING_LEVEL_3)

-- Добавление всех уровней указанного здания в список
function addAllBuildingLevels(townType, codeBuildingList, buildingID)
   push(codeBuildingList, getBuildingCode(buildingID, 1))
   if (buildingID == TOWN_BUILDING_TOWN_HALL) then
      push(codeBuildingList, TOWN_HALL_2)
      push(codeBuildingList, TOWN_HALL_3)
      push(codeBuildingList, TOWN_HALL_4)
   elseif (buildingID == TOWN_BUILDING_FORT) then
      push(codeBuildingList, FORT_2)
      push(codeBuildingList, FORT_3)
   elseif (buildingID == TOWN_BUILDING_MARKETPLACE) then
      push(codeBuildingList, MARKETPLACE_2)
   elseif (buildingID == TOWN_BUILDING_MAGIC_GUILD) then
      push(codeBuildingList, MAGIC_GUILD_2)
      push(codeBuildingList, MAGIC_GUILD_3)
      push(codeBuildingList, MAGIC_GUILD_4)
      push(codeBuildingList, MAGIC_GUILD_5)
   elseif (buildingID == TOWN_BUILDING_DWELLING_1) then
      push(codeBuildingList, DWELLING_1_2)
   elseif (buildingID == TOWN_BUILDING_DWELLING_2) then
      push(codeBuildingList, DWELLING_2_2)
   elseif (buildingID == TOWN_BUILDING_DWELLING_3) then
      push(codeBuildingList, DWELLING_3_2)
   elseif (buildingID == TOWN_BUILDING_DWELLING_4) then
      push(codeBuildingList, DWELLING_4_2)
   elseif (buildingID == TOWN_BUILDING_DWELLING_5) then
      push(codeBuildingList, DWELLING_5_2)
   elseif (buildingID == TOWN_BUILDING_DWELLING_6) then
      push(codeBuildingList, DWELLING_6_2)
   elseif (buildingID == TOWN_BUILDING_DWELLING_7) then
      push(codeBuildingList, DWELLING_7_2)
   elseif (buildingID == TOWN_BUILDING_DUNGEON_ALTAR_OF_ELEMENTS)
      and (townType == TOWN_DUNGEON)
   then
      push(codeBuildingList, DUNGEON_ALTAR_OF_ELEMENTS_2)
   elseif (buildingID == TOWN_BUILDING_PRESERVE_AVENGERS_BROTHERHOOD)
      and (townType == TOWN_PRESERVE)   
   then
      push(codeBuildingList, RAMPART_AVENGERS_BROTHERHOOD_2)
   elseif (buildingID == TOWN_BUILDING_PRESERVE_MYSTIC_POND)
      and (townType == TOWN_PRESERVE)   
   then
      push(codeBuildingList, RAMPART_MYSTIC_POND_2)
   elseif (buildingID == TOWN_BUILDING_FORTRESS_RUNIC_SHRINE)
      and (townType == TOWN_FORTRESS)   
   then
      push(codeBuildingList, FORTRESS_RUNIC_SHRINE_2)
      push(codeBuildingList, FORTRESS_RUNIC_SHRINE_3)
   elseif (buildingID == TOWN_BUILDING_STRONGHOLD_HALL_OF_TRIAL)
      and (townType == TOWN_STRONGHOLD)   
   then
      push(codeBuildingList, STRONGHOLD_HALL_OF_TRIAL_2)
      push(codeBuildingList, STRONGHOLD_HALL_OF_TRIAL_3)
   end
end

-- Получение списка кодов зданий по типу города и списку их ID
function getBuildingCodeList(townType, townBuildingList)
   local codeBuildingList = {}
   for i, buildingID in townBuildingList do
      addAllBuildingLevels(townType, codeBuildingList, buildingID)
   end
   return codeBuildingList
end

-- Проверка, построено ли в городе указанное здание
function hasTownThisBuildingCode(town, buildingCode)
   local hasBuildingCode = NO
   local buildingID = getBuildingID(buildingCode)
   local targetLevel = getBuildingLevel(buildingCode)
   if (GetTownBuildingLevel(town, buildingID) == targetLevel) then
      hasBuildingCode = YES
   end
   return hasBuildingCode
end

-- Получение списка построенных зданий в городе
function getTownBuildingCodeList(town)
   local currentTownBuildingCodeList = {}
   local townType = GetTownRace(town)
   local townBuildingList = getTownTypeBuildingList(townType)   
   local fullTownBuildingCodeList = getBuildingCodeList(townType, townBuildingList)
   for i, buildingCode in fullTownBuildingCodeList do
      if (hasTownThisBuildingCode(town, buildingCode) == YES) then
         push(currentTownBuildingCodeList, buildingCode)
      end
   end
   return currentTownBuildingCodeList
end


dwelling-boost-exe.lua
Исполнительный класс. Обеспечивает бусты (разовые приходы) существ от постройки каких-либо зданий. В представленном ниже листе параметры настроены таким образом, чтобы:
1) за постройку базового жилища приходило только 50% прироста, кроме 6, 7 уровней (100%). В оригинале буст всегда 100%
2) за постройку улучшенного жилища приходили 100% прироста (в оригинале - 0, т.е. за апы бустов нет)
Можно как угодно варьировать эти цифры и играться с бустами. Использование dwelling-growth-класса позволяет настраивать бусты независимо от базового прироста. Т.е. можно настраивать жилища с высоким приростом и низким бустом, и наоборот.

С технической точки зрения класс интересен тем, что в нём создается имитация несуществующего триггера на появление новой постройки, через отдельные потоки проверок. Класс оптимизирован - в течение хода проверяет города только текущего игрока. Однако, данная оптимизация несовместима с одновременными ходами, т.е. под такой режим нужны некоторые несложные изменения (проверять города, принадлежащие всем игрокам, а не только одному).

Код:
-- Задержка между циклами
SLEEP_DELAY = 1

-- Коэффициент бонусного прироста от базового здания
BASIC_GROWTH_BONUS_COEF = 0.5
ADVANCED_GROWTH_BONUS_COEF = 1

-- Обновление списка построенных зданий в городе
function updateTownBuildingCodeList(town, oldTownBuildingCodeList)
   local isUpdate = NO
   local newTownBuildingCodeList = getTownBuildingCodeList(town)
   for i, buildingCode in newTownBuildingCodeList do
      if (indexOf(oldTownBuildingCodeList, buildingCode) == -1) then
         push(oldTownBuildingCodeList, buildingCode)
         isUpdate = YES
         break
      end
   end
   return isUpdate
end

-- Добавление базового бонуса существ
function addBasicBonusCreatures(town, townType, dwellingLevel)
   local bonusCreaturesCount = getCreatureGrowth(townType, dwellingLevel)
   local creatureID = getCreatureID(townType, dwellingLevel)
   local currentCreaturesCount = GetObjectDwellingCreatures(town, creatureID)
   local totalCreaturesCount = currentCreaturesCount + bonusCreaturesCount * (BASIC_GROWTH_BONUS_COEF - 1)
   SetObjectDwellingCreatures(town, creatureID, totalCreaturesCount)
end

-- Добавление улучшенного бонуса существ
function addAdvancedBonusCreatures(town, townType, dwellingLevel)
   local bonusCreaturesCount = getCreatureGrowth(townType, dwellingLevel)
   local creatureID = getCreatureID(townType, dwellingLevel)
   local currentCreaturesCount = GetObjectDwellingCreatures(town, creatureID)
   local totalCreaturesCount = currentCreaturesCount + bonusCreaturesCount * ADVANCED_GROWTH_BONUS_COEF
   SetObjectDwellingCreatures(town, creatureID, totalCreaturesCount)
end

-- Проверка только что построенного здания
function checkLastBuildingCode(town, townType, townBuildingCodeList)
   local lastBuildingCodeIndex = length(townBuildingCodeList) - 1
   local lastBuildingCode = townBuildingCodeList[lastBuildingCodeIndex]
   if (lastBuildingCode == DWELLING_1_1) then
      addBasicBonusCreatures(town, townType, DWELLING_LEVEL_1)
   elseif (lastBuildingCode == DWELLING_2_1) then
      addBasicBonusCreatures(town, townType, DWELLING_LEVEL_2)
   elseif (lastBuildingCode == DWELLING_3_1) then
      addBasicBonusCreatures(town, townType, DWELLING_LEVEL_3)
   elseif (lastBuildingCode == DWELLING_4_1) then
      addBasicBonusCreatures(town, townType, DWELLING_LEVEL_4)
   elseif (lastBuildingCode == DWELLING_5_1) then
      addBasicBonusCreatures(town, townType, DWELLING_LEVEL_5)
--   elseif (lastBuildingCode == DWELLING_6_1) then
--      addBasicBonusCreatures(town, townType, DWELLING_LEVEL_6)
--   elseif (lastBuildingCode == DWELLING_7_1) then
--      addBasicBonusCreatures(town, townType, DWELLING_LEVEL_7)
   elseif (lastBuildingCode == DWELLING_1_2) then
      addAdvancedBonusCreatures(town, townType, DWELLING_LEVEL_1)
   elseif (lastBuildingCode == DWELLING_2_2) then
      addAdvancedBonusCreatures(town, townType, DWELLING_LEVEL_2)
   elseif (lastBuildingCode == DWELLING_3_2) then
      addAdvancedBonusCreatures(town, townType, DWELLING_LEVEL_3)
   elseif (lastBuildingCode == DWELLING_4_2) then
      addAdvancedBonusCreatures(town, townType, DWELLING_LEVEL_4)
   elseif (lastBuildingCode == DWELLING_5_2) then
      addAdvancedBonusCreatures(town, townType, DWELLING_LEVEL_5)
   elseif (lastBuildingCode == DWELLING_6_2) then
      addAdvancedBonusCreatures(town, townType, DWELLING_LEVEL_6)
   elseif (lastBuildingCode == DWELLING_7_2) then
      addAdvancedBonusCreatures(town, townType, DWELLING_LEVEL_7)
   end
end

-- Проверка, закончился ли ход игрока
function isEndOfTurn(playerID)
   local turnIsEnd = NO
   if (not IsPlayerCurrent(playerID)) then
      turnIsEnd = YES
   end
   return turnIsEnd
end

-- Прослушивание указанного города
function listenTownEvent()
   local currentPlayer = g_PlayerID
   local town = g_Town
   local townType = GetTownRace(town)
   local townBuildingCodeList = getTownBuildingCodeList(town)
   while (isEndOfTurn(currentPlayer) == NO) do
      if (updateTownBuildingCodeList(town, townBuildingCodeList) == YES) then
         checkLastBuildingCode(town, townType, townBuildingCodeList)
      end
      sleep(SLEEP_DELAY)
   end
end

-- Получение игрока, который ходит следующим за указанным игроком
function getNextPlayer(playerID)
   local nextPlayer
   if (playerID == PLAYER_1) then
      nextPlayer = PLAYER_2
   elseif (playerID == PLAYER_2) then
      nextPlayer = PLAYER_3
   elseif (playerID == PLAYER_3) then
      nextPlayer = PLAYER_4
   elseif (playerID == PLAYER_4) then
      nextPlayer = PLAYER_5
   elseif (playerID == PLAYER_5) then
      nextPlayer = PLAYER_6
   elseif (playerID == PLAYER_6) then
      nextPlayer = PLAYER_7
   elseif (playerID == PLAYER_7) then
      nextPlayer = PLAYER_8
   elseif (playerID == PLAYER_8) then
      nextPlayer = PLAYER_1
   end
   return nextPlayer
end

-- Прослушивание всех городов
function listenAllTowns()
   local townList = GetObjectNamesByType("TOWN")
   local playerID = PLAYER_1
   while (true) do
      for i, currentTown in townList do
         if (GetObjectOwner(currentTown) == playerID) then
            g_PlayerID = playerID
            g_Town = currentTown
            startThread(listenTownEvent)
            sleep(SLEEP_DELAY)      
         end
      end
      while (isEndOfTurn(playerID) == NO) do
         sleep(SLEEP_DELAY)
      end
      playerID = getNextPlayer(playerID)
   end
end

-- Инициализация приростов от города
function initTown(town)
   local townBuildingCodeList = {}
   local townType = GetTownRace(town)
   while (updateTownBuildingCodeList(town, townBuildingCodeList) == YES) do
      checkLastBuildingCode(town, townType, townBuildingCodeList)
   end
end

-- Инициализация приростов от всех городов
function initAllTowns()
   local townList = GetObjectNamesByType("TOWN")
   for i, currentTown in townList do
      initTown(currentTown)
   end
end

-- ВЫПОЛНЕНИЕ СКРИПТА

initAllTowns()
listenAllTowns()

_________________
Автор HoMM 5.5 WGE / WGT 1.23 и Асимметричных шахмат
Стрим GG
YouTube
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Nargott
Ведущий WGE - HoMM5 WGE Master
Ведущий WGE - HoMM5 WGE Master



Зарегистрирован: 11.12.2010
Сообщения: 2688
Откуда: Хабаровск

СообщениеДобавлено: 21 Апр 2013, 01:31    Заголовок сообщения:      Ответить с цитатой

Задачу забора 50% ход за бой я буду решать следующим образом:

Повешу на триггер COMBAT_RESULTS_TRIGGER функцию-обработчик, в которой currentHero будет лишаться 50% от своего полного хода. Но есть проблема, сам триггер не способен передать параметр currentHero. Этот вопрос разрешается ниже.

В начале дня (на триггере NEW_DAY_TRIGGER) запоминаются полные ходы всех героев, а также туда добавляются ходы свеженанятых героев, отслеживаемых другим триггером PLAYER_ADD_HERO_TRIGGER. Эта информация потребуется для нахождения 50% штрафа.

В течение хода прослушиваются все герои текущего игрока на предмет изменения очков движения (подобную прослушку я делал в предыдущем классе, где слушались города на предмет постройки). Тот герой, который последним меняет свои очки движения, заносится в глобальную переменную currentHero - очевидно, именно он будет запускать триггер боя.

Другая задача (на запрет цепочек) будет решаться так. В предыдущей задаче уже будут прослушиваться герои на предмет изменения хода. Встреча с другим героем возможна только в том случае, когда местоположение ходящего героя не изменяется (но меняются очки движения). Следовательно, при изменении очков движения любого героя (обработчик события уже будет), нужно проверяеть его на предмет изменения позиции на карте. Если положение неизменно - значит, герой взаимодействует с каким-то объектом.

Понять, что он взаимодействует именно с другим героем, можно сопоставив координаты героя и ближайшего объекта. Поскольку, при встрече с любыми другими объектами (кроме боя, который уже отслеживается), он должен иметь те же координаты, что и объект ("зайти" в объект). Правда, сложности могут возникнуть, если координаты какого-либо объекта и его точка входа будут различаться.

Изменение положения героя можно отследить, если запоминать координаты всех героев на карте в начале дня и моменты найма (повесив на обработчики соответствующих триггеров). После чего отслеживать координаты currentHero (который прослушивается на предмет имзенения очков движения), сопоставляя их с его предыдущими координатами.
_________________
Автор HoMM 5.5 WGE / WGT 1.23 и Асимметричных шахмат
Стрим GG
YouTube
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Показать сообщения:   
Начать новую тему   Ответить на тему    Список форумов Форум Лиги Героев — HeroesLeague Forum -> Общие вопросы по Heroes V — General Discussion Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Powered by phpBB © 2001, 2005 phpBB Group