Novik16

Heroes of Might&Magic: 3.3. Тактический режим.

Справочник по скриптовому API HoMM V, версия 1.3

**3.3. Тактический режим.**

При старте тактического режима игра делает следующее:
1. Загружает файл /scripts/combat-startup.lua и все прописанные в нем с помощью doFile скрипты
2. Вызывает функции createCombatAliases() и createTutorialAliases()
3. Приступает к интерпретации файла тактического скрипта. Упомянутый тактический скрипт может появиться в результате
· Использования примитивов StartCombat или SetHeroCombatScript
· Дизайна файла карты (AdvMapDesc)
· Дизайна файла определения героя (AdvMapHero)
4. Так или иначе, если файл скрипта в наличии, то интерпретатор последовательно выполняет из него строки, не являющиеся телами функций, после чего приступает к последовательному вызову хуков в зависимости от ситуации. Всего в наличии четыре хука.

3.3.1 Общее положение дел.

Итак, имеется две армии. Собственно различие между ними скрипт проводит по признаку атакующий/обороняющийся. Атакующая сторона всегда содержит в своем составе героя. Обороняющаяся может героя не иметь. Имена героев и стеков не имеют никакого отношения к именам использующимся на стратегической карте. Существует единственный примитив, позволяющий соотносить имена героев между стратегическим и тактическим режимом – GetHeroName.

3.3.2 Хуки.

bool DoPrepare()
Вызывается на этапе расстановки стеков игроком. На данном этапе состав армии игрока не определен, соотв. функции будут показывать, что в наличии есть только собственно герой. Возвращаемое значение роли не играет. В файле /scripts/combat-startup.lua данный хук заменен на void Prepere(), пользуйтесь либо одним либо другим по собственному разумению.
bool DoStart()
Вызвается на старте сражения непосредственно после расстановки войск обеими сторонами. Возвращаемое значение роли не играет. В файле /scripts/combat-startup.lua данный хук заменен на void Start(), пользуйтесь либо одним либо другим по собственному разумению.
bool UnitMove(sUnitName)
Вызывается перед каждым ходом стека AI игрока. Имя стека передается в качестве параметра. Если функция возвращает true, то AI не предпринимает над стеком к/л осмысленных действий, считая, что Вы позаботились об этом в теле хука. Кстати, по поводу «true». В файле /scripts/combat-startup.lua в отличие от файла /scripts/advmap-startup.lua отсутствует определение константы true, поэтому ее нужно либо доопределить самостоятельно, либо пользовать вместо нее not nil.
В файле /scripts/combat-startup.lua данный хук заменен на целый набор функций:
bool AttackerUnitMove(sUnitName)
bool AttackerHeroMove(sUnitName)
bool AttackerCreatureMove(sUnitName)
bool AttackerWarMachineMove(sUnitName)
bool AttackerBuildingMove(sUnitName)
bool DefenderUnitMove(sUnitName)
bool DefenderHeroMove(sUnitName)
bool DefenderCreatureMove(sUnitName)
bool DefenderWarMachineMove(sUnitName)
bool DefenderBuildingMove(sUnitName)
Опять таки, пользуйтесь тем, чем Вам удобнее.
void UnitDeath(sUnitName)
Вызывается при смерти стека существ. Имя стека передается в качестве параметра.
В файле /scripts/combat-startup.lua данный хук заменен на целый набор функций:
void AttackerUnitDeath(unitName)
void AttackerHeroDeath(sUnitName)
void AttackerCreatureDeath(sUnitName)
void AttackerWarMachineDeath(sUnitName)
void AttackerBuildingDeath(sUnitName)
void DefenderUnitDeath(sUnitName)
void DefenderHeroDeath(sUnitName)
void DefenderCreatureDeath(sUnitName)
void DefenderWarMachineDeath(sUnitName)
void DefenderBuildingDeath(sUnitName)

3.3.3 Общие функции контроля боя.

void EnableDynamicBattleMode( bEnable )
Если вызвано с параметром true, то грядущая битва будет происходит в динамическом режиме, т.е. с ограничением на время хода. Внимание! Отключить динамический режим по ходу боя будет нельзя.
void EnableAutoFinish( bEnable )
Разрешает или запрещает автоматическое завершение битвы если одна из сторон осталась без войск. Таким образом после вызова EnableAutoFinish( nil ) битва может быть завершена только путем вызовов EnableAutoFinish( not nil ), Break или Finish.
void combatEnableFinish( bEnable )
Аналог EnableAutoFinish.
void EnableCinematicCamera( bEnable )
Разрешает или запрещает «кинематографическое» метание камеры с показом действий юнитов.
void SetControlMode( nSideID, nModeID )
Устанавливает режим боя для стороны nSideID. Попытка вызвать данную функцию для AI игрока приводит к ошибке. Соотв. константы для nModeID прописаны в /scripts/ combat-startup.lua и могут быть
MODE_NORMAL = 0-- обычный режим
MODE_MANUAL = 1-- ручное управление с запретом автобоя
MODE_AUTO = 2-- автобой
В частности, вызвав данную функцию из DoPrepare c параметром MODE_AUTO и, последовательно, с MODE_MANUAL из DoStart можно обеспечить автоматическую расстановку юнитов вне желания игрока.
Соотв. константы для nSideID прописаны в /scripts/ combat-startup.lua и могут быть
ATTACKER = 0
DEFENDER = 1
void Finish( nSideID )
Автоматически завершает бой победой стороны, идентификатор которой передан в качестве параметра.
void Break()
Немедленно прерывает бой. Потери, понесенные сторонами в ходе боя, в случае выхода на стратегическую карту учитываться не будут.
void combatSetPause( n1, b1 )
Устанавливает и убирает паузу в бое (при паузе курсор превращается в часы и интерфейс заблокирован). Смысл параметров мне не до конца ясен.
void showHighlighting( bShow = true )
Убирает или устанавливает подсвечивание поля боя. Функция имеет алиас с именем ShowCombatHighlighting.

3.3.3 Управление юнитами.

**void SummonCreature( nSideID, nCreatureID, nCount, nX = -1, nY = -1 )
void AddCreature( nSideID, nCreatureID, nCount, nX = -1, nY = -1 )**
Практически идентичные функции. Добавляют стороне nSideID стек из nCount существ, и размещает его по указанным координатам. Различие состоит в том, что SummonCreature создает стек только на время боя, и подсвечивает его появление эффектом. AddCreature присоединяет стек к армии героя «навсегда» (разумеется, если состав амии героя это позволяет).
В случае, если клетка по указанным координатам недоступна (например, занята препятствием или другим стеком) новый стек будет помещен на ближайшую свободную клетку. Созданный стек будет помещен в конец таблицы, которая возвращается функцией GetUnits. Если планируется что-либо предпринимать со стеками непосредственно после добавления, то необходимо добавить вызов sleep(1) непосредственно сразу после использования функций. Иначе последствия непредсказуемы – от невыполнения следующей операции без к/л диагностики до вылета игры в операционную систему.
В случае если координаты (или одна из координат) не указаны, стек будет помещен на рандомную свободную клетку.
void addUnit(nCreatureID, nSideID, nX, nY, nCount, sUnitName)
Странная функция, которая, по идее, занимается тем же, что и две предыдущие. С некоторыми отличиями. Параметр sUnitName используется только в одном месте – если уже есть стек с таким именем, то вызов функции приведет к ошибке. В противном случае имя стеку присвоится автоматически, sUnitName никак не задействуется. В случае, если клетка по указанным координатам недоступна, вызов функции приведет к ошибке.
Вывод: использование данной функции проблематично, для чего она нужна – непонятно.
Функция имеет алиас с именем AddCombatUnit.
void removeUnit( sUnitName )
Функция удаляет с поля боя стек с именем sUnitName. Удалять можно только стеки. Героев, машины и здания – нельзя. Функция имеет алиас с именем RemoveCombatUnit.

void UnitCastAimedSpell( sUnitName, nSpellID, sTarget)
Функция заставляет юнит с именем sUnitName откастовать заклинание nSpellID на юнит sTarget. Тип юнита и наличие у юнита заклинания роли не играет, играет роль только запас манны у него. Нехватка манны приводит к ошибке скрипта. Следует быть осторожным с выбором nSpellID – попытка скастовать подобным образом «площадное» заклинание например, файрболл, может привести к подвису игры. Попытка скастовать «вредоносное» заклинание на союзников и «полезное» на врага к ошибке не приводит, но и эффекта так же не дает.
void UnitCastGlobalSpell( sUnitName, nSpellID )
Функция заставляет юнит с именем sUnitName откастовать заклинание «общего действия» (т.е. не требующее прицела) nSpellID. Тип юнита и наличие у юнита заклинания роли не играет, играет роль только запас манны у него. Нехватка манны приводит к ошибке скрипта.
void UnitCastAreaSpell( sUnitName, nSpellID, nX, nY )
Функция заставляет юнит с именем sUnitName откастовать заклинание «площадного действия» nSpellID на тайл с требуемыми координатами. Тип юнита и наличие у юнита заклинания роли не играет, играет роль только запас манны у него. Нехватка манны приводит к ошибке скрипта. Опять таки не следует забывать про sleep – например, если Вы вздумаете удалить стек непосредственно после того, как он что-то откастовал, то собственно кастовки Вы не увидите. И sleep(1) тут не отделаешься – необходимо дождаться результатов кастовки, для файрбола это sleep(8), для других заклинаний может и отличаться. Собственно, замечание со sleep относится ко всем манипуляциям с юнитами.
void SetUnitManaPoints( sUnitName, nPoints )
Функция устанавливает запас маны юнита sUnitName в nPoints поинтов. Текущий запас манны может превышать максимальный. Если планируется что-либо предпринимать с юнитом непосредственно после установки запаса маны, то необходимо добавить вызов sleep(1) непосредственно сразу после SetUnitManaPoints.
number GetUnitMaxManaPoints( sUnitName )
Функция возвращает максимальный запас маны юнита sUnitName.
number GetUnitManaPoints( sUnitName )
Функция возвращает текущий запас маны юнита sUnitName.
void commandDefend( sUnitName )
Функция заставляет юнит с именем sUnitName выполнить команду «защищаться».
Функция имеет алиас с именем DefendCombatUnit.

void commandDoSpell( sUnitName, nSpellID, nX, nY )
Аналог UnitCastAreaSpell.
void commandShot( sUnitName, sVictimName, bDontShowScene = false )
Функция заставляет юнит с именем sUnitName выполнить выстрел по юниту sVictimName. Если последний параметр true, то соответствующая кинематографическая сценка «юнит натужно замахивается и что-то кидает» показана не будет. По своим стрелять нельзя. При отсутствии снарядов стрелять нельзя. Оба случая приводят к ошибке скрипта.
void commandMove( sUnitName, nX, nY, bCheckPath = false )
Функция заставляет юнит с именем sUnitName переместиться на клетку с указанными координатами. Если последний параметр true, то будет учитываться длина хода юнита. При нехватке хода юнит с места не сдвинется, а вызов функции приведет к ошибке. Если клетка недостижима (т.е. занята другим юнитом или на пути к ней есть непреодолимые препятсятвия), то в любом случае никто никуда не пойдет, а вызов функции приведет к ошибке. Функция имеет алиас с именем MoveCombatUnit.
void commandMoveAttack(sAttacker, sVictim, nX = -1, nY = -1, bCheckPath = false)
Функция заставляет юнит с именем sUnitName атаковать юнит sVictim в melee режиме. Если указаны положительные координаты, то юнит сначала дойдет до требуемой клетки, а потом произведет атаку с нее (да-да, несмотря на то, что melee, и между юнитами пол-поля – ударит, да еще и сдачи получит). В противном случае юнит подбежит к атакуемому вплотную. Если последний параметр true, то будет учитываться длина хода юнита. При нехватке хода юнит с места не сдвинется, а вызов функции приведет к ошибке. Если клетка недостижима (т.е. занята другим юнитом или на пути к ней есть непреодолимые препятсятвия), то в любом случае никто никуда не пойдет, а вызов функции приведет к ошибке. Функция имеет алиас с именем AttackCombatUnit.
void commandDoSpecial(sUnitName, nAbilityID, nX = -1, nY = -1, bCheckPath = false)
Функция заставляет юнит с именем sUnitName использовать спецспособность по клетке с указанными координатами (если они заданы – некоторые спецспособности не требуют координат). Если последний параметр true, то будет учитываться длина хода юнита. При нехватке хода юнит с места не сдвинется, а вызов функции приведет к ошибке. Если клетка недостижима (т.е. занята другим юнитом или на пути к ней есть непреодолимые препятсятвия), то в любом случае никто никуда не пойдет, а вызов функции приведет к ошибке. Константы ABILITY_* nAbilityID прописаны в /scripts/combat-startup.lua, приводить полный список не буду. На этот раз не из-за большого объема. А из-за того, что они там некорректные. Нормальные значения констант SPELL_ABILITY_* нужно смотреть в файле /types.xml. Принципиальных ограничений на использование «неродных» абилок, в принципе, нет – так, например, суккуб вполне может изображать BATTLE_DIVE. Однако, все возможные сочетания я, конечно, не проверял.
Функция имеет алиас с именем UseCombatAbility.

void displace( sUnitName, nX, nY )
Функция мгновенно телепортирует юнит на требуемую клетку. Никакими эффектами процесс не сопровождается. Если клетка уже занята кем-либо или чем-либо, то вызов функции приведет к ошибке.
Функция имеет алиас с именем SetCombatPosition.
void playAnimation( sUnitName, sAnimType, nActionTypeID = ONESHOT )
Функция заставляет юнит с именем sUnitName проигрывать анимацию sAnimType способом nActionTypeID. Возможные sAnimType следует смотреть в xdb файле определения анимации для существ. Например, для импов это файл _(AnimSet)\Creatures\Inferno\Imp-arena.(AnimSet).xdb. Как правило, анимация типа «death» существует для всех. Остальное зависит от типа существа. Константы для nActionTypeID прописаны в /scripts/combat-startup.lua и могут быть
IDLE = 1 -- проигрывается циклически
ONESHOT_STILL = 2 -- проигрывается один раз, и последний фрейм фиксируется
ONESHOT = 3 -- проигрывается один раз, потом юнит возвращается в прежнюю позу
NON_ESSENTIAL = 5 -- не знаю, что такое.
void combatPlayEmotion( nSideID, n1 )
Функция заставляет юниты стороны nSideID проигрывать эмоцию. Полагаю, второй параметр должен определять ее тип, но эксперименты ничего не дали – независимо от значения параметра все ведут себя одинаково – радуются и чего-то голосят.
void RemoveAllUnits()
Функция удаляет все стеки с поля боя. У обоих сторон. Ввиду чего полезность ее под вопросом.
void setATB( sUnitName, n1 )
Функция позволяет управлять положением юнита на ATB. Значения второго параметра большие нуля приводят к сдвигу юнита по ATB в начало шкалы, прочие – в конец. Вероятно, существует какая-то количественная интерпретация параметра, но я ее не уловил. Следует вызывать только из хуков, т.к. в противном случае можно получить рассинхронизацию ATB с действительным порядком ходов.

3.3.4 Информационные и прочие функции.

tsUnits GetUnits(nSideID, nType)
Возвращает таблицу имен юнитов типа nType для стороны nSideID. Константы nType прописаны в /scripts/combat-startup.lua и могут быть
HERO = 0
CREATURE = 1
WAR_MACHINE = 2
BUILDING = 3
С использованием данной функции в файле /scripts/combat-startup.lua реализованы примитивы более высокого уровня:
sHeroName GetHero(nSideID)
tsUnits GetCreatures(nSideID)
tsUnits GetWarMachines(nSideID)
tsUnits GetBuildings(nSideID)
sHeroName GetAttackerHero()
sHeroName GetDefenderHero()
tsUnits GetAttackerCreatures()
tsUnits GetDefenderCreatures()
tsUnits GetAttackerWarMachines()
tsUnits GetDefenderWarMachines()
tsUnits GetAttackerBuildings()
tsUnits GetDefenderBuildings()
nCreatureID GetCreatureType( sCreatureName )
Возвращает тип существ в стеке с именем sCreatureName.
nX, nY pos( sUnitName )
Возвращает координаты юнита с именем sCreatureName. Функция имеет алиас с именем GetCombatPosition.
bool combatStarted()
Возвращает false до тех пор, пока не началась былинная битва. Имеет смысл использовать только вне хуков.
sHeroName GetHeroName( sUnitName )
Возвращает «стратегическое» имя героя sUnitName. Если передано не имя героя – вызов приведет к ошибке.
number GetCreatureNumber( sUnitName )
Возвращает количество существ в стеке с именем sUnitName.
nX, nY GetUnitPosition( sUnitName )
Аналог функции pos.
bool exist( sUnitName )
Возвращает, а жив ли еще юнит с именем sUnitName. Функция имеет алиас с именем IsCombatUnit.
nHostType GetHost( nSideID )
Возвращает, под чьим управлением находится сторона nSideID – человека или AI.
Возвращаемые константы прописаны в /scripts/common.lua и могут быть
HUMAN = 0
COMPUTER = 1
С использованием данной функции в файле /scripts/combat-startup.lua реализованы примитивы более высокого уровня:
bool IsHuman( nSideID )
bool IsComputer( nSideID )
nSideID GetUnitSide( sUnitName )
Возвращает, к какой стороне относится юнит с именем sUnitName.
Возвращаемые константы прописаны в /scripts/combat-startup.lua и могут быть
ATTACKER = 0
DEFENDER = 1
С использованием данной функции в файле /scripts/combat-startup.lua реализованы примитивы более высокого уровня:
bool IsAttacker( sUnitName )
bool IsDefender( sUnitName )
number GetUnitType( sUnitName )
Возвращает тип юнита с именем sUnitName. Возвращаемые константы прописаны в /scripts/combat-startup.lua и могут быть
HERO = 0
CREATURE = 1
WAR_MACHINE = 2
BUILDING = 3
С использованием данной функции в файле /scripts/combat-startup.lua реализованы примитивы более высокого уровня:
bool IsHero( sUnitName )
bool IsCreature( sUnitName )
bool IsWarMachine( sUnitName )
bool IsBuilding( sUnitName )

number GetWarMachineType( sUnitName )
Возвращает тип машины с именем sUnitName. Возвращаемые константы прописаны в /scripts/common.lua и могут быть
WAR_MACHINE_BALLISTA = 1
WAR_MACHINE_CATAPULT = 2
WAR_MACHINE_FIRST_AID_TENT = 3
WAR_MACHINE_AMMO_CART = 4
С использованием данной функции в файле /scripts/combat-startup.lua реализованы примитивы более высокого уровня:
sUnitName GetWarMachine( nSideID, nWarMachineTypeID )
sUnitName GetAttackerWarMachine(nWarMachineTypeID)
sUnitName GetDefenderWarMachine(nWarMachineTypeID)
number GetBuildingType( sUnitName )
Возвращает тип здания с именем sUnitName. Возвращаемые константы прописаны в /scripts/combat-startup.lua и могут быть
BUILDING_WALL = 1
BUILDING_GATE = 2
BUILDING_LEFT_TOWER = 3
BUILDING_BIG_TOWER = 4
BUILDING_MOAT = 5
BUILDING_RIGHT_TOWER = 6
BUILDING_MAGIC_WALL = 7
С использованием данной функции в файле /scripts/combat-startup.lua реализованы примитивы более высокого уровня:
sUnitName GetBuilding(nSideID, nBuildingID)
sUnitName GetAttackerBuilding(nBuildingID)
sUnitName GetDefenderBuilding(nBuildingID)
sUnitName combatReadyPerson()
Возвращает имя юнита, который готов совершить ход (т.е. находится в самом начале ATB).
string unitNames()
Возвращает строку, содержащую через пробел имена всех юнитов на поле боя. Полагаю, функция нужна, в основном, для отладочных целей.
void postEvent( sEvent, n1 = -1, n2 = -1 )
Функция позволяет эмулировать событие от клавиатуры/мыши. В качестве sEvent могут выступать названия биндов, см. файл input.cfg. Полный список биндов я предоставить в настоящий момент не готов. Смысл двух последних параметров мне так же неясен.

Просмотров: 2 947

Комментарии пока отсутcтвуют