В данной теме предлагаю опытным скриптовикам делиться своими наработками, выкладывая те или иные реализованные ими сложные скрипты, выполняющие какие-либо полезные/интересные вещи. Чтобы менее опытные могли что-то перенять и чему-то у них научиться.
Также здесь собираются нетривиальные вопросы на тему, как реализовать ту или иную идею в скриптах, и приветствуется обсуждение возможных путей решения, минимизации побочных эффектов и т.д.
Работа со скриптами
- Nargott
-
Разработчик Heroes V WGE — Developer- Сообщения: 2756
- Зарегистрирован: 11 дек 2010, 17:03
- Откуда: Хабаровск
- Контактная информация:
Как реализовать через скрипты следующие вещи?
1) Перестройка городов на старте игры.
Для чего: ИРМГ генерирует некрасивые карты, а стандартный ГСК генерирует все города только 2 уровня с построенной таверной.
Нужно:
- первому игроку стартовый город 4 уровня (скажем, форт, таверна и жилище-1);
- всем последующим игрокам стартовый город 4 уровня плюс, вероятно, дополнительная постройка (жилище-2) - до 5 уровня, шанс зависит от номера игрока и равен 100% для последнего игрока
- все нейтральные города получают 6 уровень (скажем, форт-цитадель, жилище-1,2,3)
Проблема:
- Как перебрать города, существующие на карте, если их имена заранее неизвестны?
Придётся ли перебирать все существующие имена городов, прописанные в ресурсах игры на предмет их наличия на карте?
2) Забор хода у героев при встрече или после боя.
Для чего: запрет цепочек, лимит боёв.
Нужно:
- Забирать у героя 50% полного хода после сыгранной битвы (как в Disciples 2), если остаток хода героя меньше - забирать весь остаток хода. В идеале забирать только в том случае, если нейтралы не были отпущены без боя.
- При встрече дружественных героев выравнивать их остаток хода по минимуму (т.е. устанавливать остаток хода обоих героев равным наименьшему остатку хода среди них). При посещении героем гарнизонов шахт обнулять его ход (в идеале - только гарнизонов, чтобы ход не терялся при захвате шахты) - запрет шахтерских цепочек.
Проблемы:
- Как отследить факт проведения битвы (что-то типа триггера)?
- Как отследить факт встречи героев или посещения гарнизона?
Ап: первая проблема решилась, оказалось что "нерабочая" функция GetObjectNamesByType() оказалась рабочей, ошибка была в мануале и лишней букве s в имени переменной.
1) Перестройка городов на старте игры.
Для чего: ИРМГ генерирует некрасивые карты, а стандартный ГСК генерирует все города только 2 уровня с построенной таверной.
Нужно:
- первому игроку стартовый город 4 уровня (скажем, форт, таверна и жилище-1);
- всем последующим игрокам стартовый город 4 уровня плюс, вероятно, дополнительная постройка (жилище-2) - до 5 уровня, шанс зависит от номера игрока и равен 100% для последнего игрока
- все нейтральные города получают 6 уровень (скажем, форт-цитадель, жилище-1,2,3)
Проблема:
- Как перебрать города, существующие на карте, если их имена заранее неизвестны?
Придётся ли перебирать все существующие имена городов, прописанные в ресурсах игры на предмет их наличия на карте?
2) Забор хода у героев при встрече или после боя.
Для чего: запрет цепочек, лимит боёв.
Нужно:
- Забирать у героя 50% полного хода после сыгранной битвы (как в Disciples 2), если остаток хода героя меньше - забирать весь остаток хода. В идеале забирать только в том случае, если нейтралы не были отпущены без боя.
- При встрече дружественных героев выравнивать их остаток хода по минимуму (т.е. устанавливать остаток хода обоих героев равным наименьшему остатку хода среди них). При посещении героем гарнизонов шахт обнулять его ход (в идеале - только гарнизонов, чтобы ход не терялся при захвате шахты) - запрет шахтерских цепочек.
Проблемы:
- Как отследить факт проведения битвы (что-то типа триггера)?
- Как отследить факт встречи героев или посещения гарнизона?
Ап: первая проблема решилась, оказалось что "нерабочая" функция GetObjectNamesByType() оказалась рабочей, ошибка была в мануале и лишней букве s в имени переменной.
- Nargott
-
Разработчик Heroes V WGE — Developer- Сообщения: 2756
- Зарегистрирован: 11 дек 2010, 17:03
- Откуда: Хабаровск
- Контактная информация:
Буду публиковать здесь свои скриптовые разработки для WGE в качестве "библиотек" кода. Функции или классы, представленные здесь, могут быть полезными при разработке и других модов с использованием скриптов (в частности, ТЕ-мода). В свою очередь, рассчитываю на то, что скриптовики ТЕ в данной теме также будут делиться своими наработками в доступной форме.
init-exe.lua
Класс, через который запускаются все остальные новые скрипты.
list-dll.lua
Класс работы со списками
dwelling-growth-dll.lua
Класс, в котором задаётся информация о приростах существ (приросты расставлены в соответствии с WGE)
towntype-building-list-dll.lua
Класс, предоставляющий полные списки строений для городов различных типов
start-game-rebuilding-exe.lua
Исполнительный класс. Выполняет задачу по перестройке всех городов на старте карты в соответствии с прописанными в нём параметрами. Практически необходим для карт от стандартного ГСК, не позволяющего задавать стартовые постройки (по умолчанию ставится лишь таверна). В отличие от ИРМГ, класс позволяет задавать случайную отстройку (в показанном ниже листе используется случайная отстройка жилища 2 уровня для всех игроков, кроме красного).
Для функционирования класса необходимо исправить косяк разрабов, сделанный в advmap-startup.lua (неправильное объявление константы): - правильный вариант (было TOWN_BUILDING_SPECIAL_3)
building-code-dll.lua
Класс, оперирующий с "билдинг-кодами" (элементарными постройками), взамен стандартных "билдинг-идов" (многоуровневых построек). С его помощью можно отслеживать факт наличия каких-либо отдельных построек, без заморочек с проверкой уровней.
dwelling-boost-exe.lua
Исполнительный класс. Обеспечивает бусты (разовые приходы) существ от постройки каких-либо зданий. В представленном ниже листе параметры настроены таким образом, чтобы:
1) за постройку базового жилища приходило только 50% прироста, кроме 6, 7 уровней (100%). В оригинале буст всегда 100%
2) за постройку улучшенного жилища приходили 100% прироста (в оригинале - 0, т.е. за апы бустов нет)
Можно как угодно варьировать эти цифры и играться с бустами. Использование dwelling-growth-класса позволяет настраивать бусты независимо от базового прироста. Т.е. можно настраивать жилища с высоким приростом и низким бустом, и наоборот.
С технической точки зрения класс интересен тем, что в нём создается имитация несуществующего триггера на появление новой постройки, через отдельные потоки проверок. Класс оптимизирован - в течение хода проверяет города только текущего игрока. Однако, данная оптимизация несовместима с одновременными ходами, т.е. под такой режим нужны некоторые несложные изменения (проверять города, принадлежащие всем игрокам, а не только одному).
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")
Класс работы со списками
Код: Выделить всё
-- Печать массива в консоль (для отладки)
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
Класс, в котором задаётся информация о приростах существ (приросты расставлены в соответствии с 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
Класс, предоставляющий полные списки строений для городов различных типов
Код: Выделить всё
-- Получение списка всех общих возможных построек
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
Исполнительный класс. Выполняет задачу по перестройке всех городов на старте карты в соответствии с прописанными в нём параметрами. Практически необходим для карт от стандартного ГСК, не позволяющего задавать стартовые постройки (по умолчанию ставится лишь таверна). В отличие от ИРМГ, класс позволяет задавать случайную отстройку (в показанном ниже листе используется случайная отстройка жилища 2 уровня для всех игроков, кроме красного).
Для функционирования класса необходимо исправить косяк разрабов, сделанный в advmap-startup.lua (неправильное объявление константы):
Код: Выделить всё
TOWN_BUILDING_INFERNO_ORDER_OF_FIRE = TOWN_BUILDING_SPECIAL_2
Код: Выделить всё
-- Очистка прироста постройки
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
Класс, оперирующий с "билдинг-кодами" (элементарными постройками), взамен стандартных "билдинг-идов" (многоуровневых построек). С его помощью можно отслеживать факт наличия каких-либо отдельных построек, без заморочек с проверкой уровней.
Код: Выделить всё
-- Коэффициент перевода 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
Исполнительный класс. Обеспечивает бусты (разовые приходы) существ от постройки каких-либо зданий. В представленном ниже листе параметры настроены таким образом, чтобы:
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()
- Nargott
-
Разработчик Heroes V WGE — Developer- Сообщения: 2756
- Зарегистрирован: 11 дек 2010, 17:03
- Откуда: Хабаровск
- Контактная информация:
Задачу забора 50% ход за бой я буду решать следующим образом:
Повешу на триггер COMBAT_RESULTS_TRIGGER функцию-обработчик, в которой currentHero будет лишаться 50% от своего полного хода. Но есть проблема, сам триггер не способен передать параметр currentHero. Этот вопрос разрешается ниже.
В начале дня (на триггере NEW_DAY_TRIGGER) запоминаются полные ходы всех героев, а также туда добавляются ходы свеженанятых героев, отслеживаемых другим триггером PLAYER_ADD_HERO_TRIGGER. Эта информация потребуется для нахождения 50% штрафа.
В течение хода прослушиваются все герои текущего игрока на предмет изменения очков движения (подобную прослушку я делал в предыдущем классе, где слушались города на предмет постройки). Тот герой, который последним меняет свои очки движения, заносится в глобальную переменную currentHero - очевидно, именно он будет запускать триггер боя.
Другая задача (на запрет цепочек) будет решаться так. В предыдущей задаче уже будут прослушиваться герои на предмет изменения хода. Встреча с другим героем возможна только в том случае, когда местоположение ходящего героя не изменяется (но меняются очки движения). Следовательно, при изменении очков движения любого героя (обработчик события уже будет), нужно проверяеть его на предмет изменения позиции на карте. Если положение неизменно - значит, герой взаимодействует с каким-то объектом.
Понять, что он взаимодействует именно с другим героем, можно сопоставив координаты героя и ближайшего объекта. Поскольку, при встрече с любыми другими объектами (кроме боя, который уже отслеживается), он должен иметь те же координаты, что и объект ("зайти" в объект). Правда, сложности могут возникнуть, если координаты какого-либо объекта и его точка входа будут различаться.
Изменение положения героя можно отследить, если запоминать координаты всех героев на карте в начале дня и моменты найма (повесив на обработчики соответствующих триггеров). После чего отслеживать координаты currentHero (который прослушивается на предмет имзенения очков движения), сопоставляя их с его предыдущими координатами.
Повешу на триггер COMBAT_RESULTS_TRIGGER функцию-обработчик, в которой currentHero будет лишаться 50% от своего полного хода. Но есть проблема, сам триггер не способен передать параметр currentHero. Этот вопрос разрешается ниже.
В начале дня (на триггере NEW_DAY_TRIGGER) запоминаются полные ходы всех героев, а также туда добавляются ходы свеженанятых героев, отслеживаемых другим триггером PLAYER_ADD_HERO_TRIGGER. Эта информация потребуется для нахождения 50% штрафа.
В течение хода прослушиваются все герои текущего игрока на предмет изменения очков движения (подобную прослушку я делал в предыдущем классе, где слушались города на предмет постройки). Тот герой, который последним меняет свои очки движения, заносится в глобальную переменную currentHero - очевидно, именно он будет запускать триггер боя.
Другая задача (на запрет цепочек) будет решаться так. В предыдущей задаче уже будут прослушиваться герои на предмет изменения хода. Встреча с другим героем возможна только в том случае, когда местоположение ходящего героя не изменяется (но меняются очки движения). Следовательно, при изменении очков движения любого героя (обработчик события уже будет), нужно проверяеть его на предмет изменения позиции на карте. Если положение неизменно - значит, герой взаимодействует с каким-то объектом.
Понять, что он взаимодействует именно с другим героем, можно сопоставив координаты героя и ближайшего объекта. Поскольку, при встрече с любыми другими объектами (кроме боя, который уже отслеживается), он должен иметь те же координаты, что и объект ("зайти" в объект). Правда, сложности могут возникнуть, если координаты какого-либо объекта и его точка входа будут различаться.
Изменение положения героя можно отследить, если запоминать координаты всех героев на карте в начале дня и моменты найма (повесив на обработчики соответствующих триггеров). После чего отслеживать координаты currentHero (который прослушивается на предмет имзенения очков движения), сопоставляя их с его предыдущими координатами.