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

Если вас что-то интересует по Heroes V, то вам сюда
Текущая версия Heroes V: Tribes of the East 3.1
Ответить
Аватара пользователя
Nargott
Ведущий WGE - HoMM5 WGE Master
Ведущий WGE - HoMM5 WGE Master
Сообщения: 2700
Зарегистрирован: 11 дек 2010, 17:03
Откуда: Хабаровск
Контактная информация:

17 апр 2013, 02:32Сообщение

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

Также здесь собираются нетривиальные вопросы на тему, как реализовать ту или иную идею в скриптах, и приветствуется обсуждение возможных путей решения, минимизации побочных эффектов и т.д.

Аватара пользователя
Nargott
Ведущий WGE - HoMM5 WGE Master
Ведущий WGE - HoMM5 WGE Master
Сообщения: 2700
Зарегистрирован: 11 дек 2010, 17:03
Откуда: Хабаровск
Контактная информация:

17 апр 2013, 02:33Сообщение

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

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

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

Ап: первая проблема решилась, оказалось что "нерабочая" функция GetObjectNamesByType() оказалась рабочей, ошибка была в мануале и лишней букве s в имени переменной.

Аватара пользователя
Nargott
Ведущий WGE - HoMM5 WGE Master
Ведущий WGE - HoMM5 WGE Master
Сообщения: 2700
Зарегистрирован: 11 дек 2010, 17:03
Откуда: Хабаровск
Контактная информация:

18 апр 2013, 22: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 &#40;currentLevel <= targetLevel&#41; then
		for i = currentLevel, targetLevel do
			UpgradeTownBuilding&#40;town, building&#41;
		end
	else
		DestroyTownBuildingToLevel&#40;town, building, targetLevel&#41;
	end
end

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

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

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

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

-- Получить список городов
local townList = GetObjectNamesByType&#40;"TOWN"&#41;

-- Для каждого города осуществить перестройку 
for i, town in townList do
	if &#40;GetObjectOwner&#40;town&#41; == PLAYER_NONE&#41; then
		rebuildNeutralTown&#40;town&#41;
	else
		rebuildPlayerTown&#40;town&#41;
	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&#40;buildingID, buildingLevel&#41;
	local buildingCode = BUILDING_ID_TO_CODE_COEF * buildingID + buildingLevel
	return buildingCode
end

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

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

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

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

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

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

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

-- Получение списка кодов зданий по типу города и списку их ID
function getBuildingCodeList&#40;townType, townBuildingList&#41;
	local codeBuildingList = &#123;&#125;
	for i, buildingID in townBuildingList do
		addAllBuildingLevels&#40;townType, codeBuildingList, buildingID&#41;
	end
	return codeBuildingList
end

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

-- Получение списка построенных зданий в городе
function getTownBuildingCodeList&#40;town&#41;
	local currentTownBuildingCodeList = &#123;&#125;
	local townType = GetTownRace&#40;town&#41;
	local townBuildingList = getTownTypeBuildingList&#40;townType&#41;	
	local fullTownBuildingCodeList = getBuildingCodeList&#40;townType, townBuildingList&#41;
	for i, buildingCode in fullTownBuildingCodeList do
		if &#40;hasTownThisBuildingCode&#40;town, buildingCode&#41; == YES&#41; then
			push&#40;currentTownBuildingCodeList, buildingCode&#41;
		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&#40;town, oldTownBuildingCodeList&#41;
	local isUpdate = NO
	local newTownBuildingCodeList = getTownBuildingCodeList&#40;town&#41;
	for i, buildingCode in newTownBuildingCodeList do
		if &#40;indexOf&#40;oldTownBuildingCodeList, buildingCode&#41; == -1&#41; then
			push&#40;oldTownBuildingCodeList, buildingCode&#41;
			isUpdate = YES
			break
		end 
	end
	return isUpdate
end

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

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

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

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

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

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

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

-- Инициализация приростов от города
function initTown&#40;town&#41;
	local townBuildingCodeList = &#123;&#125;
	local townType = GetTownRace&#40;town&#41;
	while &#40;updateTownBuildingCodeList&#40;town, townBuildingCodeList&#41; == YES&#41; do
		checkLastBuildingCode&#40;town, townType, townBuildingCodeList&#41;
	end
end

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

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

initAllTowns&#40;&#41;
listenAllTowns&#40;&#41;

Аватара пользователя
Nargott
Ведущий WGE - HoMM5 WGE Master
Ведущий WGE - HoMM5 WGE Master
Сообщения: 2700
Зарегистрирован: 11 дек 2010, 17:03
Откуда: Хабаровск
Контактная информация:

21 апр 2013, 02:31Сообщение

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

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

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

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

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

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

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

Ответить