Справка MMExtension 2.3Назад
Наведите мышь на пустое место слева, чтобы увидеть содержание.
Содержание
- Общая информация
- Примеры
- Evt Commands
- evt.EnterHouse
- evt.PlaySound
- evt.MoveToMap
- evt.OpenChest
- evt.FaceExpression
- evt.DamagePlayer
- evt.SetSnow
- evt.SetTexture
- evt.SetTextureOutdoors
- evt.ShowMovie
- evt.SetSprite
- evt.Cmp
- evt.SetDoorState
- evt.Add
- evt.Subtract
- evt.Set
- evt.SummonMonsters
- evt.CastSpell
- evt.SpeakNPC
- evt.SetFacetBit
- evt.SetFacetBitOutdoors
- evt.SetMonsterBit
- evt.Question
- evt.StatusText
- evt.SetMessage
- evt.SetLight
- evt.SimpleMessage
- evt.SummonObject
- evt.ForPlayer
- evt.SetNPCTopic
- evt.MoveNPC
- evt.GiveItem
- evt.ChangeEvent
- evt.CheckSkill
- evt.SetNPCGroupNews
- evt.SetMonsterGroup
- evt.SetNPCItem
- evt.SetNPCGreeting
- evt.CheckMonstersKilled
- evt.ChangeGroupToGroup
- evt.ChangeGroupAlly
- evt.CheckSeason
- evt.SetMonGroupBit
- evt.SetChestBit
- evt.FaceAnimation
- evt.SetMonsterItem
- evt.StopDoor
- evt.CheckItemsCount
- evt.RemoveItems
- evt.Jump
- evt.IsTotalBountyInRange
- evt.CanPlayerAct
- evt.RefundChestArtifacts
- Events
- Structs\After\ Spells.lua
- Core\ events.lua
- CalcSpellDamage
- WalkToMap
- DeathMap
- NewGameMap
- NewGameDefaultParty
- NewGameClearParty
- LoadedRosterTxt
- GameInitialized0
- GameInitialized1
- GameInitialized2
- CanSaveGame
- CanCastLloyd
- IsUnderwater
- FogRange
- PopulateQuestLog
- PopulateAutonotesList
- PopulateAwardsList
- MonsterInfoPictureChanged
- WindowMessage
- KeyDown
- KeyUp
- PostRender
- Action
- MenuAction
- ExitMapAction
- KeysFilter
- BeforeSaveGame
- BeforeNewGameAutosave
- AfterNewGameAutosave
- AfterSaveGame
- SkyBitmap
- LoadSavedMap
- PlayMapTrack
- ShowMovie
- PlaySound
- FaceAnimation
- CalcStatBonusByItems
- CalcStatBonusByMagic
- CalcStatBonusBySkills
- GetSkill
- GetAttackDelay
- CalcDamageToPlayer
- GetMerchantTotalSkill
- GetDisarmTrapTotalSkill
- GetDiplomacyTotalSkill
- GetPerceptionTotalSkill
- GetLearningTotalSkill
- DoBadThingToPlayer
- GetStatisticEffect
- UseMouseItem
- CanLearnSpell
- Regeneration
- ModifyItemDamage
- GenerateItem
- ItemGenerated
- MonsterKilled
- MonsterKillExp
- ItemAdditionalDamage
- CalcDamageToMonster
- PickCorpse
- CastTelepathy
- CanMonsterCastSpell
- MonsterChooseAction
- MonsterAttacked
- AfterMonsterAttacked
- PlayerAttacked
- AfterPlayerAttacked
- Core\ evt.lua
- Core\ main.lua
- Core\ npc.lua
- EnterAnyNPC
- EnterNPC
- ShowNPCTopics
- ShowHiredNPCTopics
- DrawNPCGreeting
- SpeakWithMonster
- CanExitNPC
- CanExitStreetNPC
- CanExitHiredNPC
- ExitNPC
- ExitAnyNPC
- ExitHouseScreen
- CanTeachSkillMastery
- CanTempleHealPlayer
- GetShopItemTreatment
- CanShopOperateOnItem
- ShopItemsGenerated
- GuildItemsGenerated
- HouseMovieFrame
- ArcomageSetup
- ArcomageText
- ArcomageWin
- NewBountyHunt
- BountyHuntDone
- SetMapNoNPC
- PopulateNPCDialog
- AfterPopulateNPCDialog
- PopulateHouseDialog
- PopulateArcomageDialog
- PopulateDisplayInventoryDialog
- AfterPopulateHouseDialog
- PopulateLearnSkillsDialog
- AfterPopulateLearnSkillsDialog
- BeforeDrawDialogs
- BeforeDrawDialog
- DrawDialog
- AfterDrawDialog
- AfterDrawDialogs
- AfterDrawNoDialogs
- NewDialog
- BeforeDestroyDialog
- DestroyDialog
- AfterDestroyDialog
- BeforeShowOODialog
- AfterShowOODialog
- CloseOODialog
- DrawProgressBar
- HideProgressBar
- Core\ timers.lua
- Modules\ Faces.lua
- Modules\ PaperDoll.lua
- General Functions
- Structs\After\ 00 Mem Functions.lua
- Structs\After\ Backup.lua
- Structs\After\ Dialogs.lua
- Structs\After\ Draw.lua
- Structs\After\ Functions.lua
- SplitSkill
- JoinSkill
- XYZ
- ClearConsoleEvents
- Message
- Question
- ReplaceNPCTopic
- SuppressSound
- ExitScreen
- ReloadHouse
- SwitchHouseMovie
- DrawSimpleMessage
- HouseMessage
- AddGoldExp
- TakeItemFromParty
- CheckMonstersKilled
- EnumAvailableSkills
- RGB
- StrLeft
- StrRight
- StrColor
- PcxCache
- IconCache
- SummonMonster
- SummonItem
- RebildIDList
- ChangeSprite
- CreateSprite
- MoveModel
- Structs\After\ LocalizationAndQuests.lua
- TakeQuestOperation
- Quests
- GenerateLocalization_BakFiles
- GameLocalizationIgnore
- GameLocalizationSchema
- QuestNPC
- vars.Quests
- vars.QuestAwards
- vars.QuestAutonotes
- LocalizeAll
- Localize
- GenerateQuestsLocalization
- GenerateLocalization
- GenerateGameLocalization
- ShowQuestEffect
- ShowAwardEffect
- ShowAutonoteEffect
- AutoQuest
- AutoAward
- AutoAutonote
- GetLocalName
- Autonote
- AddAutonote
- CheckAutonote
- FindAutonote
- UpdateNPCQuests
- QuestBranch
- QuestBranchScreen
- ExitQuestBranch
- GetQuestBranchStack
- Quest
- Greeting
- NPCTopic
- KillMonstersQuest
- QCheck
- Structs\After\ Spells.lua
- Structs\After\ Text Tables.lua
- Core\ Common.lua
- Core\ Debug.lua
- Core\ ErrorFunction.lua
- Core\ RSFunctions.lua
- Core\ RSMem.lua
- Core\ RSPersist.lua
- Core\ dump.lua
- Core\ events.lua
- Core\ evt.lua
- Core\ evtdeco.lua
- Core\ main.lua
- Core\ npc.lua
- Core\ timers.lua
- Modules\ Faces.lua
- Modules\ KeepLogs.lua
- Modules\ PaperDoll.lua
- Structures
- Game
- Party
- Map
- Mouse
- Screen
- structs.ActionItem
- structs.Arcomage
- structs.ArcomageAction
- structs.ArcomageActions
- structs.ArcomageCard
- structs.ArcomagePlayer
- structs.BSPNode
- structs.BaseBonus
- structs.BaseLight
- structs.BitmapsLod
- structs.BlvHeader
- structs.Button
- structs.CurrentTileBin
- structs.CustomLods
- structs.DChestItem
- structs.DecListItem
- structs.DialogLogic
- structs.Dlg
- structs.EventLine
- structs.Events2DItem
- structs.FaceAnimationInfo
- structs.FacetData
- structs.FloatVector
- structs.Fnt
- structs.FogChances
- structs.GameClassKinds
- structs.GameClasses
- structs.GameRaces
- structs.GeneralStoreItemKind
- structs.HistoryTxtItem
- structs.HouseMovie
- structs.IFTItem
- structs.Item
- structs.ItemsTxtItem
- structs.LanguageLod
- structs.LanguageLodFile
- structs.LloydBeaconSlot
- structs.Lod
- structs.LodBitmap
- structs.LodFile
- structs.LodPcx
- structs.LodRecord
- structs.LodSprite
- structs.LodSpriteD3D
- structs.LodSpriteLine
- structs.MapChest
- structs.MapDoor
- structs.MapExtra
- structs.MapFacet
- structs.MapLight
- structs.MapModel
- structs.MapMonster
- structs.MapNote
- structs.MapObject
- structs.MapOutline
- structs.MapOutlines
- structs.MapRoom
- structs.MapSprite
- structs.MapStatsItem
- structs.MapVertex
- structs.MissileSetup
- structs.ModelFacet
- structs.ModelVertex
- structs.MonListItem
- structs.MonsterAttackInfo
- structs.MonsterKind
- structs.MonsterSchedule
- structs.MonstersTxtItem
- structs.MoveToMap
- structs.NPC
- structs.NPCNewsItem
- structs.NPCProfTxtItem
- structs.OODialogManager
- structs.ObjListItem
- structs.ObjectRef
- structs.OdmHeader
- structs.OverlayItem
- structs.PFTItem
- structs.PatchOptions
- structs.Player
- structs.ProgressBar
- structs.SFT
- structs.SFTItem
- structs.ShopItemKind
- structs.SoundsItem
- structs.SpawnPoint
- structs.SpcItemsTxtItem
- structs.SpellBuff
- structs.SpellEffect
- structs.SpellInfo
- structs.SpellsTxtItem
- structs.SpritesLod
- structs.StartStat
- structs.StdItemsTxtItem
- structs.TFTItem
- structs.TileItem
- structs.TilesetDef
- structs.TownPortalTownInfo
- structs.TravelInfo
- structs.Weather
- Constants
- const.*
- const.AIState
- const.Actions
- const.ArcomageIf
- const.CharScreens
- const.ChestBits
- const.Class
- const.Condition
- const.Damage
- const.DlgID
- const.ExitMapAction
- const.FaceAnimation
- const.FacetBits
- const.HouseScreens
- const.HouseType
- const.InfoDialog
- const.ItemSlot
- const.ItemType
- const.Keys
- const.MonsterAction
- const.MonsterBits
- const.MonsterBonus
- const.MonsterBuff
- const.MonsterKind
- const.MonsterPref
- const.NPCProfession
- const.ObjectRefKind
- const.PartyBuff
- const.PlayerBuff
- const.Race
- const.Screens
- const.Season
- const.Skills
- const.Spells
- const.SpriteBits
- const.Stats
- evt.Players
- evt.VarNum
Общая информация
Для моддинга Вам понадобится MMArchive. Также могут пригодиться mm8leveleditor и MM Map Viewer.Извлеките все файлы *.txt из соответствующих архивов LOD: icons.lod в MM6, events.lod в MM7, EnglishT.lod в MM8. Вам они понадобятся.
Проще всего начать с редактирования текстовых таблиц с помощью TxtEdit. В добавок к файлам *.txt, которые Вы извлекли из LOD-архива MMExtension создаст некоторые таблицы в папке Data\Tables при первом запуске. Вы можете менять в них любые значения и добавлять новые строки ко многим из них.
Lua – это простой, но гибкий скриптовый язык. Вы можете прочитать о нём здесь, здесь и здесь. MMExtension предоставляет все стандартные библиотеки Lua и LuaJIT.
Пока я не перешёл на Sublime Text, я использовал SciTE для редактирования скриптов Lua. Вот некоторые мои настройки для SciTE:
Откройте SciTEGlobal.properties. Найдите и установите следующие параметры: tabsize=2 indent.size=2 braces.autoclose=0 Найдите user.shortcuts=\ удалите строку с Alt+X добавьте строку: Ctrl+Shift+Z|IDM_REDO|\ добавьте строку: Ctrl+R|IDM_REPLACE|\ |
Все скрипты находятся в директории Scripts. Скрипты в разных подпапках загружаются и выгружаются в разные моменты:
Подпапка | Описание |
Core | Скрипты ядра MMExtension. Не кладите сюда свои скрипты. |
General | Эти скрипты загружаются перед началом игры и никогда не выгружается. |
Global | Эти скрипты загружаются, когда запускается новая игра или загружается сохраненная игра, и выгружаются, когда пользователь выходит в главное меню или загружает другую игру. Это хорошее место для большинства скриптов, которые не относятся к конкретной карте. В частности, для скриптов заданий. |
Localization | Эти скрипты загружаются при старте игры перед загрузкой скриптов из папки "General" и могут быть загружены снова вызовом функции ReloadLocalization(). Они предназначены для локализации модов. |
Maps |
Эти скрипты соответствуют картам. Например, скрипты под названием oute3.lua и любое_имя.oute3.lua будет загружаться при
загрузке карты Oute3.odm (Нью-Сорпигал) и выгружаться при выходе из неё. У скриптов карты здесь же могут быть глобальные скрипты: oute3.global.lua and любое_имя.oute3.global.lua соответственно. Эти скрипты работают так же, как скрипты папки Global, но загружаются после них и разделяют локальные автозаметки с соответствующим скриптом карты. |
Modules | Эти скрипты не загружаются автоматически. Вместо этого, их можно загружать при помощи функции require. |
Structs | Эти скрипты предназначены для определения структур. Эти вещи низкого уровня, так что пока я не буду описывать их. Если вы нашли интересный адрес с помощью ArtMoney или дизассемблера, свяжитесь со мной. |
Вы можете создавать свои собственные подпапки. Скрипты в них не будут загружаться автоматически и не будет выгружаться.
Слово "выгружать" означает удаление всех событий скрипта. Благодаря выгрузке и последующей повторной загрузке глобальных скриптов и скриптов карт, вы можете их изменить и протестировать изменения, просто перезагрузив сохраненную игру. Не нужно для этого выходить из игры Меч и Магия. |
Отладочная консоль – это удобный способ быстро проверить что-нибудь. Нажмите Ctrl + F1, чтобы открыть её. Здесь Вы можете писать любые скрипты. Например, dump(Party[0].Stats) выведет значения характеристик первого персонажа.
Нажмите Ctrl + Enter, чтобы выполнить скрипт.
Нажмите Ctrl + E, чтобы повторить последний скрипт.
Нажмите Esc, чтобы закрыть консоль.
Переменные, используемые скриптами, могут быть 4 типов:
Локальные переменные, объявленные со словом local в Lua. Они могут быть использованы в месте, где они были объявлены (т.е. функция, скрипт или блок кода) и не хранятся в сохранении игры.
Глобальные переменные. Они могут быть доступны из любого места, но они не хранятся в сохранении игры.
Переменные в таблице vars. Они могут быть доступны из любого места и хранятся в сохранении игры.
Переменные в таблице mapvars. Они относятся к текущей карте. При загрузке карты, соответствующая таблица с переменными устанавливается, как mapvars. Они хранятся в сохранении игры. При перезаполнении карты таблица mapvars пересоздаётся, старая таблица в этот момент доступна, как Map.Refilled.
Привет мир!
Для начала используем отладочную консоль. В игре нажмите Ctrl+F1 и вставьте следующий скрипт:Message("Hello world!")
Для того, чтобы сделать свой первый скрипт игры, создайте файл out01.lua (или oute3.lua для MM6) в каталоге Scripts\Maps и напишите в нём этот текст:
MessageBox("Hello world!")
Чтобы показать родное сообщение МM, вы можете использовать подобный скрипт:
Game.NeedRedraw = true -- I remember having problems with minimap not getting drawn
Sleep(1) -- sleep for 1 tick to let it be drawn
Message("Hello world!")
Sleep(1) -- sleep for 1 tick to let it be drawn
Message("Hello world!")
Декомпилированные скрипты
Оригинальные скрипты Меча и Магии хранятся в двоичном формате в файлах с расширением .evt. MMExtension может декомпилировать эти скрипты. Ссылка на декомпилированные скрипты.Декомпилированные скрипты представлены в виде скриптов Lua и в псевдокоде, который напрямую соответствует бинарному формату.
Просто для информации, далее приведены различия между командами псевдокода и реальными командами MMExtension:
1) "evt." в них не пишется.
2) Они используют goto, а не структурные условные операторы и циклы. Их строки пронумерованы.
3) Они почти всегда проставляют имена параметров в вызовах функций Evt. Вы можете сделать то же самое, но вы также можете использовать вызовы без имен параметров.
Некоторые команды заменены лучшими аналогами в MMExtension. Например, вы не можете использовать команду evt.OnTimer, вместо этого вы должны использовать функцию Timer.
5) Есть и другие отличия в синтаксисе скриптов – например, объявление событий.
Пример (в формате Lua):
Game.MapEvtLines:RemoveEvent(60) -- remove original event
evt.map[60] = function()
local i
if evt.Cmp("MapVar0", 4) then
evt.StatusText(5) -- "Nothing here"
else
evt.Add("MapVar0", 1)
evt.StatusText(4) -- "You found something!"
i = Game.Rand() % 6
if i == 1 then
evt.Add("Inventory", 1) -- "Longsword"
elseif i == 2 then
evt.Add("Inventory", 15) -- "Dagger"
elseif i == 3 then
evt.Add("Inventory", 58) -- "Club"
elseif i == 4 then
evt.Add("Inventory", 161) -- "Phirna Root"
elseif i == 5 then
evt.Add("Inventory", 309) -- "Inferno"
else
evt.Add("Inventory", 94) -- "Cloth Hat"
end
end
end
evt.map[60] = function()
local i
if evt.Cmp("MapVar0", 4) then
evt.StatusText(5) -- "Nothing here"
else
evt.Add("MapVar0", 1)
evt.StatusText(4) -- "You found something!"
i = Game.Rand() % 6
if i == 1 then
evt.Add("Inventory", 1) -- "Longsword"
elseif i == 2 then
evt.Add("Inventory", 15) -- "Dagger"
elseif i == 3 then
evt.Add("Inventory", 58) -- "Club"
elseif i == 4 then
evt.Add("Inventory", 161) -- "Phirna Root"
elseif i == 5 then
evt.Add("Inventory", 309) -- "Inferno"
else
evt.Add("Inventory", 94) -- "Cloth Hat"
end
end
end
Если же полноценно использовать возможности MMExtension, то скрипт, делающий то же самое (если играть с ним с самого начала игры), будет выглядеть так:
local TXT = Localize{
NothingHere = "Nothing here",
FoundSomething = "You found something!",
}
local items = {1, 15, 58, 161, 309, 94}
Game.MapEvtLines:RemoveEvent(60) -- remove original event
evt.map[60] = function()
if mapvars.Shelf60 == 4 then
return Game.StatusText(TXT.NothingHere)
end
mapvars.Shelf60 = (mapvars.Shelf60 or 0) + 1
Game.StatusText(TXT.FoundSomething)
local i = math.random(1, #items)
evt.Add("Inventory", items[i]) -- alternatively: evt.GiveItem{Id = items[i]}
end
NothingHere = "Nothing here",
FoundSomething = "You found something!",
}
local items = {1, 15, 58, 161, 309, 94}
Game.MapEvtLines:RemoveEvent(60) -- remove original event
evt.map[60] = function()
if mapvars.Shelf60 == 4 then
return Game.StatusText(TXT.NothingHere)
end
mapvars.Shelf60 = (mapvars.Shelf60 or 0) + 1
Game.StatusText(TXT.FoundSomething)
local i = math.random(1, #items)
evt.Add("Inventory", items[i]) -- alternatively: evt.GiveItem{Id = items[i]}
end
Вы можете декомпилировать скрипты самостоятельно, если Вам это когда-то понадобится. Для этого извлеките все *.evt и *.str файлы из того же архива LOD, что вы использовали для извлечения *.txt файлов. Создайте папку "Decompile" в папке с игрой, положите их туда, и выполните этот простой скрипт:
local dir = "Decompile/"
for f in path.find(dir.."*.evt") do
evt.Decompile(f, 0, dir.."Scripts/"..path.setext(path.name(f), ".lua"))
evt.Decompile(f, 0, dir.."Scripts/txt/"..path.setext(path.name(f), ".txt"), true)
end
for f in path.find(dir.."*.evt") do
evt.Decompile(f, 0, dir.."Scripts/"..path.setext(path.name(f), ".lua"))
evt.Decompile(f, 0, dir.."Scripts/txt/"..path.setext(path.name(f), ".txt"), true)
end
Примечание: Невозможно преобразовать декомпилированный скрипт даже в текстовой форме обратно в файл EVT. Если Вам надо отредактировать EVT, используйте мои шаблоны для 010Editor.
Сокращённый синтаксис объявления функций
MMExtension вносит одно дополнение в синтаксис Lua – cокращённый синтаксис объявления функций. Пример:sum = |x, y| x + y
-- превращается в
sum = function(x, y)
return x + y
end
-- превращается в
sum = function(x, y)
return x + y
end
check = |b| if b then
print(b)
end
-- превращается в
check = function(b)
if b then
print(b)
end
end
print(b)
end
-- превращается в
check = function(b)
if b then
print(b)
end
end
Timer(|| evt.DamagePlayer{Damage = 1}, const.Minute)
-- превращается в
Timer(function()
return evt.DamagePlayer{Damage = 1}
end, const.Minute)
-- превращается в
Timer(function()
return evt.DamagePlayer{Damage = 1}
end, const.Minute)
switch = (|x, y| y, x)
-- превращается в
switch = (function(x, y)
return y, x
end)
-- превращается в
switch = (function(x, y)
return y, x
end)
print2 = (|x, y|
print(x)
print(y)
)
-- превращается в
print2 = (function(x, y)
print(x)
print(y)
end)
print(x)
print(y)
)
-- превращается в
print2 = (function(x, y)
print(x)
print(y)
end)
print2 = |x, y| do
print(x)
print(y)
end
-- превращается в
print2 = function(x, y)
do
print(x)
print(y)
end
end
print(x)
print(y)
end
-- превращается в
print2 = function(x, y)
do
print(x)
print(y)
end
end
Задания
Оригинальные задания MM были разбросаны по нескольким файлам и программировались вручную, это неудобно и чревато ошибками. Поддержка заданий в MMExtension прошла несколько итераций и сейчас я ею очень доволен.Здесь 6 примеров. Они предназначены для MM8. В конце большинства примеров есть дополнительная информация об использованных функциях. В большинстве примеров используется сокращённый синтаксис объявления функций.
Начните с Quest Example Simple.lua. Это простое задание с двумя дополнительными пунктами разговора, а также приветствием.
--[[
This is the simplest quest example. Go to the Clan Leader's Hall in Dagger Wound to see it in action.
It utilises new NPCTopic function for more convenient creation of simple text-only topics.
It also uses new Quest function ability to automatically find free quest slot if the Slot parameter isn't specified.
Texts are set using SetTexts function to reduce indentation level.
--]]
QuestNPC = 32 -- Frederick Talimere
-- another way to make a greeting
Greeting{
"Hello, world!",
"Hi.",
}
-- a simple text topic
NPCTopic{
"Blah 1",
"Blah Blah Blah",
}
-- a simple quest: require item #1 (Longsword), give 1000 exp, 1000 gold and an artifact hat
Quest{
"SimpleExampleQuest",
QuestItem = 1, -- quest item index (Longsword)
Gold = 1000, -- reward: gold
Exp = 1000, -- reward: experience
RewardItem = 536, -- reward: Lucky Hat
}
.SetTexts{
Topic = "Quest",
Give = "I need a Longsword!",
Done = "That's the sword I was looking for! Thank you! I have this hat and some gold coins for you!",
Undone = "You don't have the sword yet?",
After = "Thank you for the sword!",
Quest = "Bring a Longsword (the most basic of swords) to Frederick Talimere on Dagger Wound Islands.",
Award = "Brought a sword to Frederick Talimere",
}
-- another simple text topic
NPCTopic{
"Blah 2",
"Second Blah Blah Blah!",
}
--[[
NPCTopic{topic, text} and Greeting{firstGreet, greet} functions just call Quest function with appropriate parameters.
You can specify any parameters you would normally pass to Quest function, like Slot, CanShow etc.
Note that if you pass a number as topic to NPCTopic function, it will set StdTopic to that number.
See Quest Example.lua for details on StdTopic and other parameters of Quest function.
The call of Greeting function in this script is equivalent to this:
Quest{
Slot = -1,
Texts = {
FirstGreet = "Hello, world!",
Greet = "Hi.",
}
}
The first call of NPCTopic function is equivalent to this:
Quest{
Texts = {
Topic = "Blah 1",
Ungive = "Blah Blah Blah",
}
}
]]
This is the simplest quest example. Go to the Clan Leader's Hall in Dagger Wound to see it in action.
It utilises new NPCTopic function for more convenient creation of simple text-only topics.
It also uses new Quest function ability to automatically find free quest slot if the Slot parameter isn't specified.
Texts are set using SetTexts function to reduce indentation level.
--]]
QuestNPC = 32 -- Frederick Talimere
-- another way to make a greeting
Greeting{
"Hello, world!",
"Hi.",
}
-- a simple text topic
NPCTopic{
"Blah 1",
"Blah Blah Blah",
}
-- a simple quest: require item #1 (Longsword), give 1000 exp, 1000 gold and an artifact hat
Quest{
"SimpleExampleQuest",
QuestItem = 1, -- quest item index (Longsword)
Gold = 1000, -- reward: gold
Exp = 1000, -- reward: experience
RewardItem = 536, -- reward: Lucky Hat
}
.SetTexts{
Topic = "Quest",
Give = "I need a Longsword!",
Done = "That's the sword I was looking for! Thank you! I have this hat and some gold coins for you!",
Undone = "You don't have the sword yet?",
After = "Thank you for the sword!",
Quest = "Bring a Longsword (the most basic of swords) to Frederick Talimere on Dagger Wound Islands.",
Award = "Brought a sword to Frederick Talimere",
}
-- another simple text topic
NPCTopic{
"Blah 2",
"Second Blah Blah Blah!",
}
--[[
NPCTopic{topic, text} and Greeting{firstGreet, greet} functions just call Quest function with appropriate parameters.
You can specify any parameters you would normally pass to Quest function, like Slot, CanShow etc.
Note that if you pass a number as topic to NPCTopic function, it will set StdTopic to that number.
See Quest Example.lua for details on StdTopic and other parameters of Quest function.
The call of Greeting function in this script is equivalent to this:
Quest{
Slot = -1,
Texts = {
FirstGreet = "Hello, world!",
Greet = "Hi.",
}
}
The first call of NPCTopic function is equivalent to this:
Quest{
Texts = {
Topic = "Blah 1",
Ungive = "Blah Blah Blah",
}
}
]]
local A, B, C, D, E, F = 0, 1, 2, 3, 4, 5
local Q = vars.Quests
--[[
This is an example of a simple quest, dialog topics that depend on quest state and a 'sell item' topic.
Mostly it consists of texts rather than code. Go to the Clan Leader's Hall in Dagger Wound to see it in action.
It also demonstrates short functions syntax addon (see help for more info).
--]]
QuestNPC = 1 -- The lizard in the tavern
-- a simple quest: require item #1 (Longsword), give 1000 exp, 1000 gold and an artifact hat
Quest{
"ExampleQuest", -- Same as: Name = "ExampleQuest",
Slot = A,
Texts = {
FirstGreet = "Hello, world!",
Greet = "Hi.",
Topic = "Quest!",
Give = "I need a Longsword!",
GreetGiven = "How's it going?",
-- TopicGiven can be set as well, but I keep it at "Quest!" here
Done = "That's the sword I was looking for! Thank you! I have this hat and some gold coins for you!",
Undone = "You don't have the sword yet?",
GreetDone = "Greetings to you, The Man Who Gave The Sword!",
TopicDone = "Thanks!",
After = "Thank you for the sword!",
Quest = "Bring a Longsword (the most basic of swords) to that lizard in the tavern of Dagger Wound Islands.",
Award = "Brought a sword to a tavern-dwelling lizard",
},
QuestItem = 1, -- quest item index (Longsword)
Gold = 1000, -- reward: gold
Exp = 1000, -- reward: experience
RewardItem = 536, -- reward: Lucky Hat
}
-- this will hide the standard topic in slot B
Quest{
Slot = B,
}
-- this will hide the standard topic in slot C
Quest{
Slot = C,
}
-- this topic is shown only when the quest is taken
Quest{
Slot = C,
CanShow = || Q.ExampleQuest == "Given", -- a check that the quest is taken (short function!)
-- Short function syntax language extension translates this into:
-- CanShow = function()
-- return Q.ExampleQuest == "Given"
-- end,
Texts = {
Topic = "Reverse Engineering",
Ungive = "If you bring me the sword, I can reverse-engineer it and make its copies. To tell you the truth, everything here is reverse-engineered.",
},
}
-- this topic is shown only when the quest is done in place of the topic above (sell swords)
Quest{
Slot = C,
CanShow = || Q.ExampleQuest == "Done", -- a check that the quest is finished (short function!)
Texts = {
Topic = "Buy Longsword for 50 gold",
Done = "Here's a sword I made for you!",
Undone = "No money - no Longsword, honey."
},
NeverGiven = true, -- skip "Given" state, perform Done/Undone check immediately
NeverDone = true, -- sell any number of swords. This makes the quest completable mutiple times
QuestGold = 50, -- pay: 50 gold
RewardItem = 1, -- reward: Longsword
}
--[[
Other Quest properties:
StdTopic -- use the standard topic with specified number. For example, a trainer topic or "Join" topic.
StdTopicGiven, StdTopicDone -- similarly, standard topics specific to Given and Done states.
FirstStdTopic -- standard topics specific to initial (ungiven) state.
Quest -- quest number in quests.txt, by default it's allocated automatically
BaseName -- for quests that require you to go from one NPC to another. Setting BaseName makes two quests share the same quest state defined by BaseName. See "Quest With 2 NPCs.lua".
GivenState -- by default it's "Given". This may be useful in a quest with many stages.
DoneState -- by default it's "Done". This may be useful in a quest with many stages.
If you don't pass Slot, any slot not occupied by an MMExt quest will be chosen. If you pass "same" as Slot value, the last used slot will be reused.
Localization:
To generate localization template for all scripts, press Ctrl+F1, write
GenerateLocalization()
and press Ctrl+Enter. It will generate the following items in Scripts\Localization folder:
Quests.txt -- for quests
Common.txt -- for strings passed to LocalizeAll function
Scripts.txt -- for strings passed to Localize function
These files should be edited with Txt Tables Editor from my site.
Alternatively, run GenerateLocalization(true) to generate *.lua localization files. Choose whichever format you prefer.
To generate localization for quests only you can use GenerateQuestsLocalization() instead of GenerateLocalization() command.
To generate localization excluding quests you can use GenerateLocalization(false, false) command.
Note that GenerateLocalization function assumes your scripts contain up to 1 use of LocalizeAll and up to 1 use of Localize function, both of which are at the beginning of the script.
To test localization changes without restarting the game you can create a script in Globals folder with this line:
ReloadLocalization()
Then you'll only need to reload a saved game to refresh localization.
For more complex quests you can set up the following functions:
(here 't' is the table that you passed to the Quest function, it also has some new fields set by Quest function)
Checks (return value is interpreted as true or false):
CanShow(t)
CheckGive(t)
CheckDone(t)
Called on corresponding events:
Give(t)
Ungive(t)
Done(t)
Undone(t)
For complete control - these will override default behavior:
GetGreeting(t, NotFirstVisit)
GetTopic(t)
Execute(t)
IsGiven(t)
GetGreeting and GetTopic functions return a string.
Note that you can also make custom quest states. Say, you have a quest called MyQuest. If you set vars.Quests.MyQuest = "MyState", Texts.TopicMyState (or StdTopicMyState) will be displayed. When you click it, Texts.MyState will be displayed and MyState function will be called.
]]
local Q = vars.Quests
--[[
This is an example of a simple quest, dialog topics that depend on quest state and a 'sell item' topic.
Mostly it consists of texts rather than code. Go to the Clan Leader's Hall in Dagger Wound to see it in action.
It also demonstrates short functions syntax addon (see help for more info).
--]]
QuestNPC = 1 -- The lizard in the tavern
-- a simple quest: require item #1 (Longsword), give 1000 exp, 1000 gold and an artifact hat
Quest{
"ExampleQuest", -- Same as: Name = "ExampleQuest",
Slot = A,
Texts = {
FirstGreet = "Hello, world!",
Greet = "Hi.",
Topic = "Quest!",
Give = "I need a Longsword!",
GreetGiven = "How's it going?",
-- TopicGiven can be set as well, but I keep it at "Quest!" here
Done = "That's the sword I was looking for! Thank you! I have this hat and some gold coins for you!",
Undone = "You don't have the sword yet?",
GreetDone = "Greetings to you, The Man Who Gave The Sword!",
TopicDone = "Thanks!",
After = "Thank you for the sword!",
Quest = "Bring a Longsword (the most basic of swords) to that lizard in the tavern of Dagger Wound Islands.",
Award = "Brought a sword to a tavern-dwelling lizard",
},
QuestItem = 1, -- quest item index (Longsword)
Gold = 1000, -- reward: gold
Exp = 1000, -- reward: experience
RewardItem = 536, -- reward: Lucky Hat
}
-- this will hide the standard topic in slot B
Quest{
Slot = B,
}
-- this will hide the standard topic in slot C
Quest{
Slot = C,
}
-- this topic is shown only when the quest is taken
Quest{
Slot = C,
CanShow = || Q.ExampleQuest == "Given", -- a check that the quest is taken (short function!)
-- Short function syntax language extension translates this into:
-- CanShow = function()
-- return Q.ExampleQuest == "Given"
-- end,
Texts = {
Topic = "Reverse Engineering",
Ungive = "If you bring me the sword, I can reverse-engineer it and make its copies. To tell you the truth, everything here is reverse-engineered.",
},
}
-- this topic is shown only when the quest is done in place of the topic above (sell swords)
Quest{
Slot = C,
CanShow = || Q.ExampleQuest == "Done", -- a check that the quest is finished (short function!)
Texts = {
Topic = "Buy Longsword for 50 gold",
Done = "Here's a sword I made for you!",
Undone = "No money - no Longsword, honey."
},
NeverGiven = true, -- skip "Given" state, perform Done/Undone check immediately
NeverDone = true, -- sell any number of swords. This makes the quest completable mutiple times
QuestGold = 50, -- pay: 50 gold
RewardItem = 1, -- reward: Longsword
}
--[[
Other Quest properties:
StdTopic -- use the standard topic with specified number. For example, a trainer topic or "Join" topic.
StdTopicGiven, StdTopicDone -- similarly, standard topics specific to Given and Done states.
FirstStdTopic -- standard topics specific to initial (ungiven) state.
Quest -- quest number in quests.txt, by default it's allocated automatically
BaseName -- for quests that require you to go from one NPC to another. Setting BaseName makes two quests share the same quest state defined by BaseName. See "Quest With 2 NPCs.lua".
GivenState -- by default it's "Given". This may be useful in a quest with many stages.
DoneState -- by default it's "Done". This may be useful in a quest with many stages.
If you don't pass Slot, any slot not occupied by an MMExt quest will be chosen. If you pass "same" as Slot value, the last used slot will be reused.
Localization:
To generate localization template for all scripts, press Ctrl+F1, write
GenerateLocalization()
and press Ctrl+Enter. It will generate the following items in Scripts\Localization folder:
Quests.txt -- for quests
Common.txt -- for strings passed to LocalizeAll function
Scripts.txt -- for strings passed to Localize function
These files should be edited with Txt Tables Editor from my site.
Alternatively, run GenerateLocalization(true) to generate *.lua localization files. Choose whichever format you prefer.
To generate localization for quests only you can use GenerateQuestsLocalization() instead of GenerateLocalization() command.
To generate localization excluding quests you can use GenerateLocalization(false, false) command.
Note that GenerateLocalization function assumes your scripts contain up to 1 use of LocalizeAll and up to 1 use of Localize function, both of which are at the beginning of the script.
To test localization changes without restarting the game you can create a script in Globals folder with this line:
ReloadLocalization()
Then you'll only need to reload a saved game to refresh localization.
For more complex quests you can set up the following functions:
(here 't' is the table that you passed to the Quest function, it also has some new fields set by Quest function)
Checks (return value is interpreted as true or false):
CanShow(t)
CheckGive(t)
CheckDone(t)
Called on corresponding events:
Give(t)
Ungive(t)
Done(t)
Undone(t)
For complete control - these will override default behavior:
GetGreeting(t, NotFirstVisit)
GetTopic(t)
Execute(t)
IsGiven(t)
GetGreeting and GetTopic functions return a string.
Note that you can also make custom quest states. Say, you have a quest called MyQuest. If you set vars.Quests.MyQuest = "MyState", Texts.TopicMyState (or StdTopicMyState) will be displayed. When you click it, Texts.MyState will be displayed and MyState function will be called.
]]
local A, B, C, D, E, F = 0, 1, 2, 3, 4, 5
local Q = vars.Quests
--[[
This is an example of a quest that requires you to go from one NPC to another.
Also demonstrates usage of StdTopic to make NPC join the party.
Like in Quest Example.lua, short function syntax addon is utilized.
--]]
QuestNPC = 1 -- The lizard in the tavern
-- quest start: take the quest in the tavern
Quest{
"PowerStone",
Slot = D,
GivenItem = 617, -- gives Power Stone upon giving the task
CheckDone = false, -- the quest can't be completed here
}
.SetTexts{
Topic = "Frederick Talimere",
TopicDone = false, -- don't show if it's done
Give = "Show this stone to Frederick Talimere. He is an expert in these.",
Undone = "Frederick is obsessed with these stones. What a fool...",
Quest = "Show a stone to Frederick Talimere in Dagger Wound Islands.",
}
QuestNPC = 32 -- Frederick Talimere
-- quest end: talk to Frederick to get the stone
Quest{
BaseName = "PowerStone",
Slot = D,
Exp = 1000, -- reward: experience
QuestItem = 617, -- need Power Stone
KeepQuestItem = true, -- don't take power stone away
}
.SetTexts{
-- no Topic - don't show the topic if the quest isn't taken
TopicGiven = "Power Stone",
TopicDone = "Power Stone",
Done = "Wow, this is a stone! I love stones!",
Undone = "One lizard told me you have a stone, and so do I. Why don't you show me yours and I'll show you mine?",
After = "I have about 30 of these stones. You know what, let's go looking for stones together! But I need to get a sword first. Because who knows, we might meet some enemies on our way. With a sword in my hands I'll look more persuasive and will calm down any enemy. Trust me, negotiations are my thing!",
Award = "Showed a stone to Frederick Talimere",
}
-- show Join topic when both example quests are completed
Quest{
Slot = D,
StdTopic = 602, -- Join topic of Frederick Talimere
CanShow = || Q.PowerStone == "Done" and Q.SimpleExampleQuest == "Done",
}
local Q = vars.Quests
--[[
This is an example of a quest that requires you to go from one NPC to another.
Also demonstrates usage of StdTopic to make NPC join the party.
Like in Quest Example.lua, short function syntax addon is utilized.
--]]
QuestNPC = 1 -- The lizard in the tavern
-- quest start: take the quest in the tavern
Quest{
"PowerStone",
Slot = D,
GivenItem = 617, -- gives Power Stone upon giving the task
CheckDone = false, -- the quest can't be completed here
}
.SetTexts{
Topic = "Frederick Talimere",
TopicDone = false, -- don't show if it's done
Give = "Show this stone to Frederick Talimere. He is an expert in these.",
Undone = "Frederick is obsessed with these stones. What a fool...",
Quest = "Show a stone to Frederick Talimere in Dagger Wound Islands.",
}
QuestNPC = 32 -- Frederick Talimere
-- quest end: talk to Frederick to get the stone
Quest{
BaseName = "PowerStone",
Slot = D,
Exp = 1000, -- reward: experience
QuestItem = 617, -- need Power Stone
KeepQuestItem = true, -- don't take power stone away
}
.SetTexts{
-- no Topic - don't show the topic if the quest isn't taken
TopicGiven = "Power Stone",
TopicDone = "Power Stone",
Done = "Wow, this is a stone! I love stones!",
Undone = "One lizard told me you have a stone, and so do I. Why don't you show me yours and I'll show you mine?",
After = "I have about 30 of these stones. You know what, let's go looking for stones together! But I need to get a sword first. Because who knows, we might meet some enemies on our way. With a sword in my hands I'll look more persuasive and will calm down any enemy. Trust me, negotiations are my thing!",
Award = "Showed a stone to Frederick Talimere",
}
-- show Join topic when both example quests are completed
Quest{
Slot = D,
StdTopic = 602, -- Join topic of Frederick Talimere
CanShow = || Q.PowerStone == "Done" and Q.SimpleExampleQuest == "Done",
}
local A, B, C, D, E, F = 0, 1, 2, 3, 4, 5
--[[
This is an example of an alchemic quest like those seen in MM8. It works smarter by removing weaker ingredients first.
It replaces default quest of Thistle that normally makes a Potion of Pure Speed.
Like the example with 2 NPCs, it uses BaseName property to make a cross-topic quest easily.
Then there is some stuff just for fun: I reinitiate a conversation 2 minutes after the quest is completed and show some text.
--]]
QuestNPC = 88 -- Thistle
Quest{ -- Get quest
"StreetAlchemy",
}
.SetTexts{
FirstTopic = "Street Alchemy", -- only show if it isn't given
Give = "Hey! Hey fellas! I'm chronicling a Street Alchemy special. You wanna see some alchemy?",
Quest = "Bring Thistle on the Dagger Wound Islands the basic ingredients for a Potion of Disappearance.",
}
NPCTopic{ -- Ingredients topic
"Ingredients",
"Ultimate Potions are made of a complex blending of the three basic ingredients: Swords, Boots and Armor. Potion of Disappearance requires 6 Longswords, 2 pairs of boots and 2 leather armors."
}
Quest{ -- Finish quest
BaseName = "StreetAlchemy",
QuestItem = {
{1,2,3,4,5, Count = 6}, -- all kinds of Longswords, 6 in total
{132,133,134,135,136, Count = 2}, -- all kinds of Boots, 2 in total
{84,85,86,87,88, Count = 2}, -- all kinds of Leather Armor, 2 in total
},
Exp = 1000,
RewardItem = 535, -- Ring of Fusion
Done = function(t)
evt.Add("Inventory", 220) -- add an empty bottle to make it appear as if it's the reward
-- now make him speak to us again after some time
local npc = QuestNPC -- QuestNPC is set to NPC being spoken to in a dialog
Sleep(const.Minute*3, nil, {0}) -- sleep for 3 minutes and only wake up when no dialog is active (hence, the 3rd parameter)
evt.SpeakNPC(npc)
end
}
.SetTexts{
TopicGiven = "Do you have the Ingredients?", -- only show if it's given
Done = "Hey look, the Potion of Disappearance has disappeared! Take this empty bottle, it's yours now.",
Undone = "You are missing all or some of the needed ingredients. Remember, to make a Potion of Disappearance I need 6 Longswords, 2 pairs of boots and 2 leather armors.",
}
Quest{ -- Instead of Ingredients topic
Slot = B,
CanShow = |t| Game.CurrentScreen ~= const.Screens.House, -- only show if NPC was met on the street
}
.SetTexts{
Greet = "I think there's something in your backpack...",
}
--[[
This is an example of an alchemic quest like those seen in MM8. It works smarter by removing weaker ingredients first.
It replaces default quest of Thistle that normally makes a Potion of Pure Speed.
Like the example with 2 NPCs, it uses BaseName property to make a cross-topic quest easily.
Then there is some stuff just for fun: I reinitiate a conversation 2 minutes after the quest is completed and show some text.
--]]
QuestNPC = 88 -- Thistle
Quest{ -- Get quest
"StreetAlchemy",
}
.SetTexts{
FirstTopic = "Street Alchemy", -- only show if it isn't given
Give = "Hey! Hey fellas! I'm chronicling a Street Alchemy special. You wanna see some alchemy?",
Quest = "Bring Thistle on the Dagger Wound Islands the basic ingredients for a Potion of Disappearance.",
}
NPCTopic{ -- Ingredients topic
"Ingredients",
"Ultimate Potions are made of a complex blending of the three basic ingredients: Swords, Boots and Armor. Potion of Disappearance requires 6 Longswords, 2 pairs of boots and 2 leather armors."
}
Quest{ -- Finish quest
BaseName = "StreetAlchemy",
QuestItem = {
{1,2,3,4,5, Count = 6}, -- all kinds of Longswords, 6 in total
{132,133,134,135,136, Count = 2}, -- all kinds of Boots, 2 in total
{84,85,86,87,88, Count = 2}, -- all kinds of Leather Armor, 2 in total
},
Exp = 1000,
RewardItem = 535, -- Ring of Fusion
Done = function(t)
evt.Add("Inventory", 220) -- add an empty bottle to make it appear as if it's the reward
-- now make him speak to us again after some time
local npc = QuestNPC -- QuestNPC is set to NPC being spoken to in a dialog
Sleep(const.Minute*3, nil, {0}) -- sleep for 3 minutes and only wake up when no dialog is active (hence, the 3rd parameter)
evt.SpeakNPC(npc)
end
}
.SetTexts{
TopicGiven = "Do you have the Ingredients?", -- only show if it's given
Done = "Hey look, the Potion of Disappearance has disappeared! Take this empty bottle, it's yours now.",
Undone = "You are missing all or some of the needed ingredients. Remember, to make a Potion of Disappearance I need 6 Longswords, 2 pairs of boots and 2 leather armors.",
}
Quest{ -- Instead of Ingredients topic
Slot = B,
CanShow = |t| Game.CurrentScreen ~= const.Screens.House, -- only show if NPC was met on the street
}
.SetTexts{
Greet = "I think there's something in your backpack...",
}
--[[
These are 2 example quests that require killing multiple kinds of monsters.
Go to the Clan Leader's Hall in Dagger Wound to see the quests in action.
--]]
QuestNPC = 182 -- Dirthic, an empty NPC in a house on an island
evt.MoveNPC(QuestNPC, 173) -- move him to Clan Leader's Hall
-- Quest 1: Kill all pirates
KillMonstersQuest{
-- quest name is optional
{Map = "out01.odm", Monster = {181, 182, 183}},
Exp = 2000,
Gold = 2000,
}
.SetTexts{
Greet = "Hi there!",
Topic = "Pirates!",
Give = "Kill all da Pirates on Dagger Wound Islands.",
Done = "It's great that you've killed them! 2000 gold for you.",
Undone = "Just kill 'em, ok?",
TopicDone = false, -- hide the topic when the quest is completed
Quest = "Kill all Pirates on Dagger Wound Islands. Return to Dirthic in Clan Leader's Hall.",
Award = "Killed all da Pirates on Dagger Wound Islands",
Killed = "You have killed all Pirates!", -- completion message
}
-- Quest 2: Kill all creatures in Abandoned Temple
KillMonstersQuest{
"ClearAbandonedTemple", -- quest name
{Map = "d05.blv", Monster = {7, 8, 9}},
"You have killed all Couatls! Serpentmen are yet to be killed.", -- partial completion message (optional)
{Map = "d05.blv", Monster = {94, 95, 96}},
"You have killed all Serpentmen! Some Couatls are alive.", -- partial completion message (optional)
Exp = 5000,
Gold = 5000,
}
.SetTexts{
Topic = "Snakes!",
Give = "Kill all of them creatures in Abandoned Temple.",
Done = "It's great that you've killed them! 5000 gold for you.",
Undone = "Just kill 'em, ok?",
TopicDone = false, -- hide the topic when the quest is completed
Quest = "Kill all creatures in Abandoned Temple. Return to Dirthic in Clan Leader's Hall.",
Award = "Conducted a massacre in the Abandoned Temple",
Killed = "You have killed all Couatls and Serpentmen!", -- completion message
}
--[[
KillMonstersQuest function takes a list of tasks that it checks with CheckMonstersKilled.
Here are ways of using CheckMonstersKilled:
CheckMonstersKilled{} -- killed all monsters on the map?
CheckMonstersKilled{Group = 1} -- killed all monsters belonging to group 1?
CheckMonstersKilled{Monster = 7} -- killed all monsters of kind 7 (Young Couatl)?
CheckMonstersKilled{NameId = 3} -- killed all monsters with NameId = 3 in placemon.txt (Dragon Hunter Pet)?
CheckMonstersKilled{MonsterIndex = 5} -- killed monster with index 5 in Map.Monsters array?
Instead of a single number you can pass a table with numbers, like I do in this example.
Additonal parameters:
Count -- need to kill at least this many monsters
InvisibleAsDead -- treat invisible (that is, currently disabled) monsters as dead when counting (MM8 only. 'true' by default)
MM6 currently isn't supported, because it doesn't have evt.CheckMonstersKilled command. InvisibleAsDead = false is only supported in MM8.
KillMonstersQuest tasks have an extra required Map parameter. A quest can span across multiple maps.
You can specify partial completion messages. They are placed after a group of tasks. For example:
{task1},
{task2},
{task3},
"first 3 tasks done",
{task4},
{task5},
"tasks 4 and 5 done",
{task6},
"task 6 done",
KillMonstersQuest adds completion messages to Texts under names Killed1, Killed2, Killed3 and so on, for localization.
KillMonstersQuest supports all parameters of Quest function. It sets Quest parameter to 'true' if it isn't specified.
]]
These are 2 example quests that require killing multiple kinds of monsters.
Go to the Clan Leader's Hall in Dagger Wound to see the quests in action.
--]]
QuestNPC = 182 -- Dirthic, an empty NPC in a house on an island
evt.MoveNPC(QuestNPC, 173) -- move him to Clan Leader's Hall
-- Quest 1: Kill all pirates
KillMonstersQuest{
-- quest name is optional
{Map = "out01.odm", Monster = {181, 182, 183}},
Exp = 2000,
Gold = 2000,
}
.SetTexts{
Greet = "Hi there!",
Topic = "Pirates!",
Give = "Kill all da Pirates on Dagger Wound Islands.",
Done = "It's great that you've killed them! 2000 gold for you.",
Undone = "Just kill 'em, ok?",
TopicDone = false, -- hide the topic when the quest is completed
Quest = "Kill all Pirates on Dagger Wound Islands. Return to Dirthic in Clan Leader's Hall.",
Award = "Killed all da Pirates on Dagger Wound Islands",
Killed = "You have killed all Pirates!", -- completion message
}
-- Quest 2: Kill all creatures in Abandoned Temple
KillMonstersQuest{
"ClearAbandonedTemple", -- quest name
{Map = "d05.blv", Monster = {7, 8, 9}},
"You have killed all Couatls! Serpentmen are yet to be killed.", -- partial completion message (optional)
{Map = "d05.blv", Monster = {94, 95, 96}},
"You have killed all Serpentmen! Some Couatls are alive.", -- partial completion message (optional)
Exp = 5000,
Gold = 5000,
}
.SetTexts{
Topic = "Snakes!",
Give = "Kill all of them creatures in Abandoned Temple.",
Done = "It's great that you've killed them! 5000 gold for you.",
Undone = "Just kill 'em, ok?",
TopicDone = false, -- hide the topic when the quest is completed
Quest = "Kill all creatures in Abandoned Temple. Return to Dirthic in Clan Leader's Hall.",
Award = "Conducted a massacre in the Abandoned Temple",
Killed = "You have killed all Couatls and Serpentmen!", -- completion message
}
--[[
KillMonstersQuest function takes a list of tasks that it checks with CheckMonstersKilled.
Here are ways of using CheckMonstersKilled:
CheckMonstersKilled{} -- killed all monsters on the map?
CheckMonstersKilled{Group = 1} -- killed all monsters belonging to group 1?
CheckMonstersKilled{Monster = 7} -- killed all monsters of kind 7 (Young Couatl)?
CheckMonstersKilled{NameId = 3} -- killed all monsters with NameId = 3 in placemon.txt (Dragon Hunter Pet)?
CheckMonstersKilled{MonsterIndex = 5} -- killed monster with index 5 in Map.Monsters array?
Instead of a single number you can pass a table with numbers, like I do in this example.
Additonal parameters:
Count -- need to kill at least this many monsters
InvisibleAsDead -- treat invisible (that is, currently disabled) monsters as dead when counting (MM8 only. 'true' by default)
MM6 currently isn't supported, because it doesn't have evt.CheckMonstersKilled command. InvisibleAsDead = false is only supported in MM8.
KillMonstersQuest tasks have an extra required Map parameter. A quest can span across multiple maps.
You can specify partial completion messages. They are placed after a group of tasks. For example:
{task1},
{task2},
{task3},
"first 3 tasks done",
{task4},
{task5},
"tasks 4 and 5 done",
{task6},
"task 6 done",
KillMonstersQuest adds completion messages to Texts under names Killed1, Killed2, Killed3 and so on, for localization.
KillMonstersQuest supports all parameters of Quest function. It sets Quest parameter to 'true' if it isn't specified.
]]
local A, B, C, D, E, F = 0, 1, 2, 3, 4, 5
--[[
This example demonstrates a complex branched dialog.
It isn't too easy to understand, but it's elegant.
It also shows how you can have item name as topic name and some other bells and whistles.
Go to the Clan Leader's Hall in Dagger Wound to see it in action.
--]]
local MyNPC = 2 -- Dadeross in the lizards tavern
-- For fun: play sound when entering the conversation
function events.EnterNPC(npc)
if npc == MyNPC then
Game.PlaySound(130)
end
end
local function SetBranch(t)
QuestBranch(t.NewBranch)
end
local function ItemTopic(t)
-- return 'false' if the quest is given, which means the item is given away
return not vars.Quests[t.Name] and Game.ItemsTxt[t.MyItem].Name
end
local function GiveItem(t)
evt.ForPlayer().Add("Inventory", t.MyItem) -- give item
-- Game.PlaySound(205) -- make only sound
evt.Add("Experience", 0) -- make sound and animation
evt.FaceAnimation(Game.CurrentPlayer, const.FaceAnimation.SmileHuge) -- a happy face
QuestBranch("Thanks")
end
-- sipmlify similar quests creation
local QuestBase = {}
local function MyQuest(t)
table.copy(QuestBase, t) -- copy common values
QuestBase.Slot = QuestBase.Slot and QuestBase.Slot + 1 -- auto-increment Slot
return Quest(t)
end
--[[
Now, let's get to the quests themselves.
Dialog structure:
- Weapons
- Swords
- Sword 1
- Sword 2
- Sword 3
- Daggers
- Dagger 1
- Axes
- Axe 1
- Axe 2
- Axe 3
- Blasters
- Magic
- Book 1
- Book 2
- Book 3
- Book 4
- Dadeross' Letter to Fellmoon
- Certificate of Authentication (for Axe of Balthazar)
(+ Thanks screen)
]]
QuestNPC = MyNPC
-- greeting
Greeting{
"I'm placed here to give you free stuff.",
"Please choose your free stuff.",
}
-- default topics
QuestBase = {Slot = A}
-- get rid of standard topics of this NPC
MyQuest{}
MyQuest{}
MyQuest{}
MyQuest{}
MyQuest{}
-- A topic that's shown when there are no items left. This one is a bit hackish.
-- Since the quest-matching function goes from slot A to slot F, by the time it
-- asks for topic in slot F it has done all other slots. So, I check that these
-- slots have no topics and then enable the topic of this slot
MyQuest{
Ungive = SetBranch,
NewBranch = "",
GetTopic = function(t)
for i = 0, 4 do
if Game.NPC[MyNPC].Events[i] ~= 0 then
return
end
end
return t.Texts.Topic
end,
Texts = {
Topic = "Sorry, I don't have any of these",
Ungive = "Sorry, I don't have any of these. Maybe you want something else?"
}
}
-- base branch topics
QuestBase = {Branch = "", Slot = A, Ungive = SetBranch}
MyQuest{
NewBranch = "Weapons",
Texts = {
Topic = "Weapons",
Ungive = "Choose which you prefer."
}
}
MyQuest{
NewBranch = "Magic",
Texts = {
Topic = "Magic",
Ungive = "I have a few books."
}
}
-- Weapons branch
QuestBase = {Branch = "Weapons", Slot = A, Ungive = SetBranch}
MyQuest{
NewBranch = "Swords",
Texts = {
Topic = "Swords",
}
}
MyQuest{
NewBranch = "Daggers",
Texts = {
Topic = "Daggers",
}
}
MyQuest{
NewBranch = "Axes",
Texts = {
Topic = "Axes",
}
}
MyQuest{
NewBranch = "Blasters",
Texts = {
Topic = "Blasters",
}
}
-- Swords branch
QuestBase = {
Branch = "Swords", Slot = A,
GetTopic = ItemTopic,
Give = GiveItem,
Texts = {
Give = "Use it well!"
}
}
MyQuest{MyItem = 1}
MyQuest{MyItem = 10}
MyQuest{MyItem = 502}
-- Daggers branch
QuestBase = table.copy(QuestBase, {
Branch = "Daggers", Slot = A,
})
MyQuest{MyItem = 508}
-- Axes branch
QuestBase = table.copy(QuestBase, {
Branch = "Axes", Slot = A,
})
MyQuest{MyItem = 34}
MyQuest{MyItem = 37}
MyQuest{MyItem = 541}
-- Magic branch
QuestBase = table.copy(QuestBase, {
Branch = "Magic", Slot = A,
})
MyQuest{MyItem = 460}
MyQuest{MyItem = 430}
MyQuest{MyItem = 444}
MyQuest{MyItem = 404}
-- Letter and Certificate of Authentication items in main branch
QuestBase = table.copy(QuestBase, {
Branch = "", Slot = C,
})
MyQuest{MyItem = 741} -- Dadeross' Letter to Fellmoon
MyQuest{MyItem = 732, -- Certificate of Authentication
CanShow = function()
return evt.All.Cmp("Inventory", 541) -- check for Axe of Balthazar
end
}
-- Thanks branch
NPCTopic{
Branch = "Thanks", Slot = A,
Ungive = SetBranch,
NewBranch = "",
"Thanks!",
"Maybe you want something else?",
}
--[[
Here's how dialog branches work:
A quest with Branch field is only shown if that's the current branch.
Current branch can be set with QuestBranch function:
QuestBranch("BranchName")
You can also make the branch persist after you reenter NPC dialog:
QuestBranch("BranchName", true)
Or you can obtain current branch:
local branch = QuestBranch()
If there is no persisted branch name, when you enter NPC dialog the branch is set to "".
Branches support is really simple. Previous version of this example implemented it manually.
]]
--[[
This example demonstrates a complex branched dialog.
It isn't too easy to understand, but it's elegant.
It also shows how you can have item name as topic name and some other bells and whistles.
Go to the Clan Leader's Hall in Dagger Wound to see it in action.
--]]
local MyNPC = 2 -- Dadeross in the lizards tavern
-- For fun: play sound when entering the conversation
function events.EnterNPC(npc)
if npc == MyNPC then
Game.PlaySound(130)
end
end
local function SetBranch(t)
QuestBranch(t.NewBranch)
end
local function ItemTopic(t)
-- return 'false' if the quest is given, which means the item is given away
return not vars.Quests[t.Name] and Game.ItemsTxt[t.MyItem].Name
end
local function GiveItem(t)
evt.ForPlayer().Add("Inventory", t.MyItem) -- give item
-- Game.PlaySound(205) -- make only sound
evt.Add("Experience", 0) -- make sound and animation
evt.FaceAnimation(Game.CurrentPlayer, const.FaceAnimation.SmileHuge) -- a happy face
QuestBranch("Thanks")
end
-- sipmlify similar quests creation
local QuestBase = {}
local function MyQuest(t)
table.copy(QuestBase, t) -- copy common values
QuestBase.Slot = QuestBase.Slot and QuestBase.Slot + 1 -- auto-increment Slot
return Quest(t)
end
--[[
Now, let's get to the quests themselves.
Dialog structure:
- Weapons
- Swords
- Sword 1
- Sword 2
- Sword 3
- Daggers
- Dagger 1
- Axes
- Axe 1
- Axe 2
- Axe 3
- Blasters
- Magic
- Book 1
- Book 2
- Book 3
- Book 4
- Dadeross' Letter to Fellmoon
- Certificate of Authentication (for Axe of Balthazar)
(+ Thanks screen)
]]
QuestNPC = MyNPC
-- greeting
Greeting{
"I'm placed here to give you free stuff.",
"Please choose your free stuff.",
}
-- default topics
QuestBase = {Slot = A}
-- get rid of standard topics of this NPC
MyQuest{}
MyQuest{}
MyQuest{}
MyQuest{}
MyQuest{}
-- A topic that's shown when there are no items left. This one is a bit hackish.
-- Since the quest-matching function goes from slot A to slot F, by the time it
-- asks for topic in slot F it has done all other slots. So, I check that these
-- slots have no topics and then enable the topic of this slot
MyQuest{
Ungive = SetBranch,
NewBranch = "",
GetTopic = function(t)
for i = 0, 4 do
if Game.NPC[MyNPC].Events[i] ~= 0 then
return
end
end
return t.Texts.Topic
end,
Texts = {
Topic = "Sorry, I don't have any of these",
Ungive = "Sorry, I don't have any of these. Maybe you want something else?"
}
}
-- base branch topics
QuestBase = {Branch = "", Slot = A, Ungive = SetBranch}
MyQuest{
NewBranch = "Weapons",
Texts = {
Topic = "Weapons",
Ungive = "Choose which you prefer."
}
}
MyQuest{
NewBranch = "Magic",
Texts = {
Topic = "Magic",
Ungive = "I have a few books."
}
}
-- Weapons branch
QuestBase = {Branch = "Weapons", Slot = A, Ungive = SetBranch}
MyQuest{
NewBranch = "Swords",
Texts = {
Topic = "Swords",
}
}
MyQuest{
NewBranch = "Daggers",
Texts = {
Topic = "Daggers",
}
}
MyQuest{
NewBranch = "Axes",
Texts = {
Topic = "Axes",
}
}
MyQuest{
NewBranch = "Blasters",
Texts = {
Topic = "Blasters",
}
}
-- Swords branch
QuestBase = {
Branch = "Swords", Slot = A,
GetTopic = ItemTopic,
Give = GiveItem,
Texts = {
Give = "Use it well!"
}
}
MyQuest{MyItem = 1}
MyQuest{MyItem = 10}
MyQuest{MyItem = 502}
-- Daggers branch
QuestBase = table.copy(QuestBase, {
Branch = "Daggers", Slot = A,
})
MyQuest{MyItem = 508}
-- Axes branch
QuestBase = table.copy(QuestBase, {
Branch = "Axes", Slot = A,
})
MyQuest{MyItem = 34}
MyQuest{MyItem = 37}
MyQuest{MyItem = 541}
-- Magic branch
QuestBase = table.copy(QuestBase, {
Branch = "Magic", Slot = A,
})
MyQuest{MyItem = 460}
MyQuest{MyItem = 430}
MyQuest{MyItem = 444}
MyQuest{MyItem = 404}
-- Letter and Certificate of Authentication items in main branch
QuestBase = table.copy(QuestBase, {
Branch = "", Slot = C,
})
MyQuest{MyItem = 741} -- Dadeross' Letter to Fellmoon
MyQuest{MyItem = 732, -- Certificate of Authentication
CanShow = function()
return evt.All.Cmp("Inventory", 541) -- check for Axe of Balthazar
end
}
-- Thanks branch
NPCTopic{
Branch = "Thanks", Slot = A,
Ungive = SetBranch,
NewBranch = "",
"Thanks!",
"Maybe you want something else?",
}
--[[
Here's how dialog branches work:
A quest with Branch field is only shown if that's the current branch.
Current branch can be set with QuestBranch function:
QuestBranch("BranchName")
You can also make the branch persist after you reenter NPC dialog:
QuestBranch("BranchName", true)
Or you can obtain current branch:
local branch = QuestBranch()
If there is no persisted branch name, when you enter NPC dialog the branch is set to "".
Branches support is really simple. Previous version of this example implemented it manually.
]]
Автозаметки
Чтобы избежать проблем с индексами и лимитом автозаметок, используйте функции Autonote и AddAutonote для новых автозаметок.Пример:
Maps\out01.global.lua:
Autonote('hi', 1, 'Welcome to out01!')
local TXT = Localize{
AutonoteMessage = "Check Auto Notes, it's extremely important!",
}
if not CheckAutonote'hi' then -- just to demonstrate use of CheckLocalAutonote
Game.ShowStatusText(TXT.AutonoteMessage)
end
AddAutonote'hi'
AutonoteMessage = "Check Auto Notes, it's extremely important!",
}
if not CheckAutonote'hi' then -- just to demonstrate use of CheckLocalAutonote
Game.ShowStatusText(TXT.AutonoteMessage)
end
AddAutonote'hi'
Добавленные таким образом автозаметки автоматически локализуемы. По умолчанию, автозаметки локальны по отношению к скрипту, чтобы избежать конфликтов имён. Для автозаметок, используемых несколькими скриптами, используйте ":" в начале их имени (например ":hi").
Локализация
Чтобы сделать скрипт локализуемым, Вы должны в нём вызвать функцию Localize, передав ей таблицу со строками по умолчанию. Она вернёт таблицу с локализованными строками. См. предыдущий пример.Для общих строк, используемых несколькими скриптами, используйте функцию LocalizeAll. Она работает так же, но Вам не потребуется возвращаемая ей таблица. Таблица, возвращаемая Localize, автоматически берёт отсутствующие строки из таблицы общих строк.
Вообще, таблицы локализации могут содержать любые значения, а не только строки. В том числе, подтаблицы.
Задания локализуются автоматически.
Локализация максимально автоматизирована. Функция GenerateLocalization() автоматически извлекает информацию о локализации из всех скриптов и генерирует файлы локализации. Она накладывает ограничения на скрипты в папках Maps и Modules. Эти скрипты не должны ничего делать до вызова функций Localize и/или LocalizeAll. К тому же, каждую функцию они должны вызывать только 1 раз, иначе строки, переданные в последующих вызовах, могут быть проигнорированы.
Чтобы сгенерировать файлы локализации для всех скриптов, загрузите любую игру, нажмите Ctrl+F1, напишите GenerateLocalization() и нажмите Ctrl+Enter. В папке Scripts\Localization будут созданы следующие файлы:
Файл | Описание |
Quests.txt | Локализация заданий. |
Common.txt | Строки, переданные в функцию LocalizeAll. |
Scripts.txt | Строки, переданные в функцию Localize. |
Или же можно запустить команду GenerateLocalization(true), чтобы сгенерировать файлы локализации *.lua. Выбирайте тот формат, который Вам удобнее.
Чтобы сгенерировать локализацию только для заданий, можно использовать команду GenerateQuestsLocalization().
Чтобы сгенерировать локализацию для всего, кроме заданий, можно использовать команду GenerateLocalization(false, false).
Чтобы тестировать изменения локализации без перезапуска игры, можно создать скрит в папке Global со следующей строкой:
ReloadLocalization()
Особые коды в сообщениях
В любом тексте можно использовать особые коды, создаваемые функциями StrLeft, StrRight и StrColor.В сообщениях NPC и в файле History.txt также используется следующий набор особых кодов:
Строка | Значение |
---|---|
%01 | NPC name |
%02 | Current player name |
%03 | "his"/"her" (depending on NPC sex) |
%04 | Bribe cost |
%05 | "day"/"evening"/"morning" |
%06 | "lady"/"sir" (depending on sex of current player) |
%07 | "Lady"/"Sir" (depending on sex of current player) |
%08 | Random achieved award from a hardcoded list |
%09 | Same as %03 |
%10 | "Lady"/"Lord" (depending on sex of current player) |
%11 | Reputation category of the party |
%12 | Reputation category required by the NPC |
%13 | Any name starting with the same letter as that of current player |
%14 | "sister"/"brother" (depending on NPC sex) |
%15 | "daughter" |
%16 | Same as %14 |
%17 | Gold percentage an NPC takes |
%23 | Map name |
%24 | Item name (in yellow color) |
%25 | Standard buy/sell/repair cost |
%27 | Actual buy/sell/repair cost with regards to Merchant skill |
%28 | Shop owner title |
%29 | Identification price |
MM7, MM8: | |
%30 | History entry date |
%31 | Player 1 name |
%51 – %70 | Special date |
MM7: | |
%32 | Player 2 name |
%33 | Player 3 name |
%34 | Player 4 name |
MM8: | |
%32 | "his"/"her" (depending on player 1 sex) |
%33 | "he"/"she" (depending on player 1 sex) |
%34 | "him"/"her" (depending on player 1 sex) |
Ещё о Data\Tables
Папка Data\Tables – это отличный инструмент при разработке мода, но простое распространение её с большим модом может вызвать сложности при последующем создании меньших модов для него, поскольку любое обновление большого мода их перезапишет.Во-первых, я советую настроить чтение таблиц, по которым не генерируются файлы *.bin, из LOD-архива мода, если он большой. Это позволит другим модам их перекрывать более безопасно. Вот пример, как это сделать (для Scripts\General):
table.copy({
['Chest'] = 'Chest.txt',
['Class HP SP'] = 'ClsHPSP.txt',
['Class Skills'] = 'ClsSkill.txt',
['Class Starting Skills'] = 'ClsSkilB.txt',
['Class Starting Stats'] = 'ClsStats.txt',
['House Movies'] = 'HouseMov.txt',
['Monster Kinds'] = 'MonKind.txt',
['Spells2'] = 'Spells2.txt',
['Town Portal'] = 'TownPort.txt',
['Transport Index'] = 'TripIdx.txt',
['Transport Locations'] = 'TripLoc.txt',
['Shops'] = 'Shops.txt',
['Faces'] = 'Faces.txt',
['Face Animations'] = 'FaceAnim.txt',
}, DataTables.Files, true)
-- DataTables.LazyMode = true -- see below for an explanation
['Chest'] = 'Chest.txt',
['Class HP SP'] = 'ClsHPSP.txt',
['Class Skills'] = 'ClsSkill.txt',
['Class Starting Skills'] = 'ClsSkilB.txt',
['Class Starting Stats'] = 'ClsStats.txt',
['House Movies'] = 'HouseMov.txt',
['Monster Kinds'] = 'MonKind.txt',
['Spells2'] = 'Spells2.txt',
['Town Portal'] = 'TownPort.txt',
['Transport Index'] = 'TripIdx.txt',
['Transport Locations'] = 'TripLoc.txt',
['Shops'] = 'Shops.txt',
['Faces'] = 'Faces.txt',
['Face Animations'] = 'FaceAnim.txt',
}, DataTables.Files, true)
-- DataTables.LazyMode = true -- see below for an explanation
Во-вторых, для таблиц, которые генерируют файлы *.bin, есть 2 пути:
Примеры
Вы найдёте больше примеров в теме для обсуждения MMExtension.Умения и заклинания игроков
Здесь есть кое-какие скрипты, показывающие, как можно работать с умениями и заклинаниями. Скопируйте приглянувшийся скрипт в отладочную консоль, чтобы протестировать его.-- learn all spells
for _, pl in Party do
for i in pl.Spells do
pl.Spells[i] = true
end
end
for _, pl in Party do
for i in pl.Spells do
pl.Spells[i] = true
end
end
-- give Expert Perception for all players
for _, pl in Party do
local skill, mastery = SplitSkill(pl.Skills[const.Skills.Perception])
pl.Skills[const.Skills.Perception] = JoinSkill(math.max(skill, 4), math.max(mastery, const.Expert))
end
for _, pl in Party do
local skill, mastery = SplitSkill(pl.Skills[const.Skills.Perception])
pl.Skills[const.Skills.Perception] = JoinSkill(math.max(skill, 4), math.max(mastery, const.Expert))
end
-- get all skills at Master 12
for _, pl in Party do
for i, val in pl.Skills do
local skill, mastery = SplitSkill(val)
pl.Skills[i] = JoinSkill(math.max(skill, 12), math.max(mastery, const.Master))
end
end
for _, pl in Party do
for i, val in pl.Skills do
local skill, mastery = SplitSkill(val)
pl.Skills[i] = JoinSkill(math.max(skill, 12), math.max(mastery, const.Master))
end
end
-- get all learned skills to Master 12
for _, pl in Party do
for i, val in pl.Skills do
if val ~= 0 then
local skill, mastery = SplitSkill(val)
pl.Skills[i] = JoinSkill(math.max(skill, 12), math.max(mastery, const.Master))
end
end
end
for _, pl in Party do
for i, val in pl.Skills do
if val ~= 0 then
local skill, mastery = SplitSkill(val)
pl.Skills[i] = JoinSkill(math.max(skill, 12), math.max(mastery, const.Master))
end
end
end
-- learn all available skills at Expert
for _, pl in Party do
for i, learn in EnumAvailableSkills(pl.Class) do
if learn >= const.Expert then
local skill, mastery = SplitSkill(pl.Skills[i])
skill = math.max(skill, 4) -- learn at least level 4
mastery = math.max(mastery, const.Expert) -- learn the mastery
pl.Skills[i] = JoinSkill(skill, mastery)
end
end
end
for _, pl in Party do
for i, learn in EnumAvailableSkills(pl.Class) do
if learn >= const.Expert then
local skill, mastery = SplitSkill(pl.Skills[i])
skill = math.max(skill, 4) -- learn at least level 4
mastery = math.max(mastery, const.Expert) -- learn the mastery
pl.Skills[i] = JoinSkill(skill, mastery)
end
end
end
-- learn all available skills at their maximum level
local LearnLevel = (Game.Version > 6 and {1, 4, 7, 10} or {1, 4, 12})
for _, pl in Party do
for i, learn in EnumAvailableSkills(pl.Class) do
local skill, mastery = SplitSkill(pl.Skills[i])
skill = math.max(skill, LearnLevel[learn]) -- learn at least the usual needed level
mastery = math.max(mastery, learn) -- learn the mastery
pl.Skills[i] = JoinSkill(skill, mastery)
end
end
local LearnLevel = (Game.Version > 6 and {1, 4, 7, 10} or {1, 4, 12})
for _, pl in Party do
for i, learn in EnumAvailableSkills(pl.Class) do
local skill, mastery = SplitSkill(pl.Skills[i])
skill = math.max(skill, LearnLevel[learn]) -- learn at least the usual needed level
mastery = math.max(mastery, learn) -- learn the mastery
pl.Skills[i] = JoinSkill(skill, mastery)
end
end
Бонусы артефактов
Дать кожаным доспехам Харека бонус 'Магии Земли'. (не тестированный код)function events.CalcStatBonusByItems(t)
if t.Stat ~= const.Stats.EarthMagic or t.Player.Skills[const.Skills.EarthMagic] == 0 then
return
end
for item, slot in t.Player:EnumActiveItems() do
if item.Number == 516 then
t:SetMagicBonus(SplitSkill(t.Player.Skills[const.Skill.EarthMagic]):div(2))
return
end
end
end
if t.Stat ~= const.Stats.EarthMagic or t.Player.Skills[const.Skills.EarthMagic] == 0 then
return
end
for item, slot in t.Player:EnumActiveItems() do
if item.Number == 516 then
t:SetMagicBonus(SplitSkill(t.Player.Skills[const.Skill.EarthMagic]):div(2))
return
end
end
end
Дать кожаным доспехам Харека бонус 'Оружейник + 8'. (не тестированный код)
function events.CalcStatBonusByItems(t)
if t.Stat ~= const.Stats.Armsmaster or t.Player.Skills[const.Skills.Armsmaster] == 0 then
return
end
for item, slot in t.Player:EnumActiveItems() do
if item.Number == 516 then
t:SetArtifactBonus(8)
return
end
end
end
if t.Stat ~= const.Stats.Armsmaster or t.Player.Skills[const.Skills.Armsmaster] == 0 then
return
end
for item, slot in t.Player:EnumActiveItems() do
if item.Number == 516 then
t:SetArtifactBonus(8)
return
end
end
end
Вопрос: Возможно ли изменить силу усилений предметов? Например, чтобы предметы со свойством 'Богов' давали +30 к статистикам вместо +10?
Ответ: (не тестированный код)
function events.CalcStatBonusByItems(t)
if t.Stat >= const.Stats.Might and t.Stat <= const.Stats.Luck then
for it in t.Player:EnumActiveItems() do
if it.Bonus2 == 2 then
t.Result = t.Result + 20
end
end
end
end
if t.Stat >= const.Stats.Might and t.Stat <= const.Stats.Luck then
for it in t.Player:EnumActiveItems() do
if it.Bonus2 == 2 then
t.Result = t.Result + 20
end
end
end
end
Бонусы умений
Сделать, чтобы Гранд топора добавлял +2 повреждения за очко умения вместо +1:function events.CalcStatBonusBySkills(t)
if t.Result ~= 0 and t.Stat == const.Stats.MeleeDamageBase then -- t.Result ~= 0 is for speedup
local sk, mas = SplitSkill(t.Player.Skills[const.Skills.Dagger])
if mas >= const.GM then
local it = t.Player:GetActiveItem(const.ItemSlot.MainHand)
if it and it:T().Skill == const.Skills.Dagger then
t.Result = t.Result + sk
end
end
end
end
if t.Result ~= 0 and t.Stat == const.Stats.MeleeDamageBase then -- t.Result ~= 0 is for speedup
local sk, mas = SplitSkill(t.Player.Skills[const.Skills.Dagger])
if mas >= const.GM then
local it = t.Player:GetActiveItem(const.ItemSlot.MainHand)
if it and it:T().Skill == const.Skills.Dagger then
t.Result = t.Result + sk
end
end
end
end
Урон заклинания
Изменить урон заклинания №2 – Стрела пламени. Также можно сделать его зависящим от мастерства t.Mastery в магии и здоровья t.HP монстра.local function Randoms(min, max, count)
local r = 0
for i = 1, count do
r = r + math.random(min, max)
end
return r
end
function events.CalcSpellDamage(t)
if t.Spell == 2 then -- Flame Arrow
t.Result = 100 + Randoms(1, 100, t.Skill) -- 100 + (1-100) per skill level
end
end
local r = 0
for i = 1, count do
r = r + math.random(min, max)
end
return r
end
function events.CalcSpellDamage(t)
if t.Spell == 2 then -- Flame Arrow
t.Result = 100 + Randoms(1, 100, t.Skill) -- 100 + (1-100) per skill level
end
end
Управление агрессией монстров в MM6
Положите этот скрипт в папку Scripts\Global. Это делает лучников в Свободной гавани дружественными, а крестьян – агрессивными. В других местах лучники будут по-прежнему агрессивными, а крестьяне – дружелюбными.function events.BeforeLoadMap()
if Game.Map.Name == "outc2.odm" then
LocalMonstersTxt()
Game.MonstersTxt[1].HostileType = 0 -- ArcherA
Game.MonstersTxt[2].HostileType = 0 -- ArcherB
Game.MonstersTxt[3].HostileType = 0 -- ArcherC
Game.MonstersTxt[121].HostileType = 4 -- PeasantF1A
Game.MonstersTxt[122].HostileType = 4 -- PeasantF1B
Game.MonstersTxt[123].HostileType = 4 -- PeasantF1C
end
end
if Game.Map.Name == "outc2.odm" then
LocalMonstersTxt()
Game.MonstersTxt[1].HostileType = 0 -- ArcherA
Game.MonstersTxt[2].HostileType = 0 -- ArcherB
Game.MonstersTxt[3].HostileType = 0 -- ArcherC
Game.MonstersTxt[121].HostileType = 4 -- PeasantF1A
Game.MonstersTxt[122].HostileType = 4 -- PeasantF1B
Game.MonstersTxt[123].HostileType = 4 -- PeasantF1C
end
end
Цветы, которые можно подобрать (MM8)
Положите этот скрипт в папку Scripts\Global.-- You can find such flowers in Ravenshore at X = 16921, Y = 4112
-- Flowers disappear when picked up, which makes life easier than in Barrels script
-- The game remembers which sprites are hidden by itself
local SpriteEvents = 20000
local TXT = Localize{
FlowerHint = "Flowers",
}
local function Flower(EvtId)
local i = EvtId – SpriteEvents
evt.Add("Inventory", 208)
evt.SetSprite(i, false) -- alternatively, for the same effect: Map.Sprites[i].Invisible = true
end
local function InitFlower(i, a)
a.Event = SpriteEvents + i
evt.map[SpriteEvents + i] = Flower
evt.hint[SpriteEvents + i] = TXT.FlowerHint
end
function events.LoadMap()
for i, a in Map.Sprites do
if a.DecName == "plant27" then
InitFlower(i, a)
end
end
end
-- Flowers disappear when picked up, which makes life easier than in Barrels script
-- The game remembers which sprites are hidden by itself
local SpriteEvents = 20000
local TXT = Localize{
FlowerHint = "Flowers",
}
local function Flower(EvtId)
local i = EvtId – SpriteEvents
evt.Add("Inventory", 208)
evt.SetSprite(i, false) -- alternatively, for the same effect: Map.Sprites[i].Invisible = true
end
local function InitFlower(i, a)
a.Event = SpriteEvents + i
evt.map[SpriteEvents + i] = Flower
evt.hint[SpriteEvents + i] = TXT.FlowerHint
end
function events.LoadMap()
for i, a in Map.Sprites do
if a.DecName == "plant27" then
InitFlower(i, a)
end
end
end
Необычно выглядящие бочки (MM7)
Положите этот скрипт в папку Scripts\Global, чтобы превратить деревья в бочки.-- Turns trees into barrels
local SpriteEvents = 20000
local TopicBase = 383
local TextBase = 582
local Reorder = {[0] = 0, 1, 4, 3, 5, 2, 6, 7} -- NPC topics order for barrels is messed up
local AutonotesBase = 32
local function Barrel(EvtId)
local i = EvtId – SpriteEvents
local v = mapvars.Barrels[i]
Game.ShowStatusText(Game.NPCText[TextBase + Reorder[v]])
if v > 0 then
evt.Add(evt.VarNum.BaseStats[v – 1], 2)
evt.Set("AutonotesBits", AutonotesBase + v)
mapvars.Barrels[i] = 0
evt.hint[SpriteEvents + i] = Game.NPCTopic[TopicBase]
end
end
local function InitBarrel(i, a)
mapvars.Barrels = mapvars.Barrels or {}
mapvars.Barrels[i] = mapvars.Barrels[i] or math.random(1, 7)
a.Event = SpriteEvents + i
evt.map[SpriteEvents + i] = Barrel
evt.hint[SpriteEvents + i] = Game.NPCTopic[TopicBase + Reorder[mapvars.Barrels[i]]]
end
function events.LoadMap()
for i, a in Map.Sprites do
if a.DecName and a.DecName:match("^tree") then
InitBarrel(i, a)
end
end
end
local SpriteEvents = 20000
local TopicBase = 383
local TextBase = 582
local Reorder = {[0] = 0, 1, 4, 3, 5, 2, 6, 7} -- NPC topics order for barrels is messed up
local AutonotesBase = 32
local function Barrel(EvtId)
local i = EvtId – SpriteEvents
local v = mapvars.Barrels[i]
Game.ShowStatusText(Game.NPCText[TextBase + Reorder[v]])
if v > 0 then
evt.Add(evt.VarNum.BaseStats[v – 1], 2)
evt.Set("AutonotesBits", AutonotesBase + v)
mapvars.Barrels[i] = 0
evt.hint[SpriteEvents + i] = Game.NPCTopic[TopicBase]
end
end
local function InitBarrel(i, a)
mapvars.Barrels = mapvars.Barrels or {}
mapvars.Barrels[i] = mapvars.Barrels[i] or math.random(1, 7)
a.Event = SpriteEvents + i
evt.map[SpriteEvents + i] = Barrel
evt.hint[SpriteEvents + i] = Game.NPCTopic[TopicBase + Reorder[mapvars.Barrels[i]]]
end
function events.LoadMap()
for i, a in Map.Sprites do
if a.DecName and a.DecName:match("^tree") then
InitBarrel(i, a)
end
end
end
Еще примеры
Призвать монстра (крестьянина):local mon = SummonMonster(151, Party.X, Party.Y, Party.Z, true)
mon.NPC_ID = 52
mon.Hostile = false
mon.NPC_ID = 52
mon.Hostile = false
Посмотреть номер глобального события (скопируйте в консоль, чтобы легко увидеть, какое событие вызывает пункт диалога):
-- on:
function events.EvtGlobal(evt)
Message(evt)
end
function events.EvtGlobal(evt)
Message(evt)
end
-- off:
events.EvtGlobal.clear()
events.EvtGlobal.clear()
Посмотреть номера текущего дома (2DEvent) и NPC (вызывайте из консоли):
Game.GetCurrentHouse(), GetCurrentNPC()
Вопрос: Как изменить место, где воскрешается команда после смерти?
Ответ: Впишите нужные координаты в вызов функции XYZ и присвойте Direction нужное направление:
function events.DeathMap(t)
t.Name = "out05.odm"
XYZ(Party, 0, 0, 0)
Party.Direction = 0
Party.LookAngle = 0
end
t.Name = "out05.odm"
XYZ(Party, 0, 0, 0)
Party.Direction = 0
Party.LookAngle = 0
end
Изменение стартовой карты (аналогично предыдущему примеру):
Game.NewGameMap = "out05.odm"
function events.NewGameMap()
XYZ(Party, 0, 0, 0)
Party.Direction = 0
Party.LookAngle = 0
end
function events.NewGameMap()
XYZ(Party, 0, 0, 0)
Party.Direction = 0
Party.LookAngle = 0
end
Вопрос: Как исполнить код при нажатии определённой кнопки?
Способ 1:
function Keys.F1(t)
Message("F1 pressed")
end
Message("F1 pressed")
end
function events.KeyDown(t)
if t.Key == const.Keys.F1 then
Message("F1 pressed")
end
end
if t.Key == const.Keys.F1 then
Message("F1 pressed")
end
end
Keys[const.Keys.F1] = function()
Message("F1 pressed")
end
Message("F1 pressed")
end
Evt Commands
evt.EnterHouseПараметры: |
|
Id |
In 2DEvents.txt 600 = you won 601 = you won 2 / you lost |
evt.PlaySoundПараметры: |
|
Id | |
X | |
Y | |
evt.MoveToMapNotes:If cancel is pressed, event execution is stopped If X, Y, Z, Direction, LookAngle, SpeedZ are all 0, the party isn't moved If HouseId and Icon are 0, the enter dungeon dialog isn't shown Параметры: |
|
X | |
Y | |
Z | |
Direction | -1 = special case |
LookAngle | |
SpeedZ | |
HouseId | In 2DEvents.txt |
Icon | |
Name | if unspecified or starts with "0" => current map |
evt.OpenChestПараметры: |
|
Id | |
evt.FaceExpressionПараметры: |
|
Player | |
Frame | |
evt.DamagePlayerПараметры: |
|
Player | |
DamageType | |
Damage | |
evt.SetSnowПараметры: |
|
EffectId | Only 0 available |
On | |
evt.SetTextureПараметры: |
|
Facet |
[MM6] Index in Map.Facets indoors. [MM7+] Id of facets group. |
Name | |
evt.SetTextureOutdoors[MM6]Параметры: |
|
Model | |
Facet | |
Name | |
evt.ShowMovie[MM7+]Параметры: |
|
DoubleSize | |
ExitCurrentScreen |
Use true only before using evt.MoveToMap command in houses and before showing game ending. Prevents loading of house anmation after the movie stops playing, but doesn't exit the screen properly. |
Name | |
evt.SetSpriteПараметры: |
|
SpriteId | |
Visible | bit 0x20 of sprite |
Name | If Name is unspecified or "0", the sprite isn't changed |
evt.CmpUsually performs Variable >= Value comparisonПараметры: |
|
VarNum | |
Value | |
evt.SetDoorStateПараметры: |
|
Id | |
State |
0 – state (0), 1 – state (1), 2 – switch state if the door isn't moving, 3 – switch state |
evt.AddПараметры: |
|
VarNum | |
Value | |
evt.SubtractAlso available as evt.Sub.Параметры: |
|
VarNum | |
Value | |
evt.SetПараметры: |
|
VarNum | |
Value | |
evt.SummonMonstersПараметры: |
|
TypeIndexInMapStats | |
Level | |
Count | |
X | |
Y | |
Z | |
NPCGroup | [MM7+] |
unk | [MM7+] |
evt.CastSpellПараметры: |
|
Spell | |
Mastery | |
Skill | |
FromX | |
FromY | |
FromZ | |
ToX | |
ToY | |
ToZ | |
evt.SpeakNPCПараметры: |
|
NPC | |
evt.SetFacetBitПараметры: |
|
Id |
[MM6] Index in Map.Facets indoors. [MM7+] Id of facets group. |
Bit | |
On | |
evt.SetFacetBitOutdoors[MM6]Параметры: |
|
Model | Model index in Map.Models |
Facet | -1 = for all faces of the model |
Bit | |
On | |
evt.SetMonsterBit[MM7+]Параметры: |
|
Monster | |
Bit | |
On | |
evt.QuestionUse Question function instead, e.g.if Question("Restricted area - Keep out.", "What's the password?"):lower() == "jbard" then ... Параметры: |
|
Question | |
Answer1 | |
Answer2 | |
evt.StatusTextUse Game.ShowStatusText function instead, e.g.Game.ShowStatusText("Hi!") Параметры: |
|
Str | |
evt.SetMessageUse Message function instead, e.g.Message("Hi!") Параметры: |
|
Str | |
evt.SetLightПараметры: |
|
Id |
[MM6, MM7] Map.Lights index [MM8] Light group id |
On | |
evt.SimpleMessageUse Message function instead, e.g.Message("Hi!") Нет параметров. |
|
evt.SummonObjectTo make your script compatible with all MM versions, instead of calling this function you can call SummonItem to create an item and Game.SummonObjects to create an object.Параметры: |
|
Item | [MM8] Item index. Index over 1000 means random item of the same kind as Item % 1000 of strength Item div 1000. For backward compatibility, this parameter can also be called Type. |
Type | [MM6, MM7] Object kind index (ObjList.txt) |
X | |
Y | |
Z | |
Speed | |
Count | |
RandomAngle | |
evt.ForPlayerSets current player and returns evt. You can thus write things like this: evt.ForPlayer("All").Add("Exp", 1000) You can also manipulate evt.Player and evt.CurrentPlayer variables directly. Usually a better approach is to specify player after evt, this way it only effects one call that follows: evt.All.Add("Exp", 1000) evt[0].Add("Gold", 1000) Параметры: |
|
Player | |
evt.SetNPCTopicПараметры: |
|
NPC | |
Index | |
Event | |
evt.MoveNPCПараметры: |
|
NPC | |
HouseId | In 2DEvents.txt |
evt.GiveItemПараметры: |
|
Strength | 1-6 (like described at the end of STDITEMS.TXT) |
Type | |
Id |
If Id is 0, a random item is chosen from the specified class with specified strength, otherwise, Type and Strength determine the enchantments |
evt.ChangeEventПараметры: |
|
NewEvent | Changes global event for barrels, pedestals etc. The kinds of sprites with such events are hard-coded. |
evt.CheckSkillChecks that the skill meets specified Level requirement and that Mastery exactly matches that of the player (Novice matches any mastery). Was supposed to include "Double effect" enchantments and NPC bonuses, but doesn't.Параметры: |
|
Skill | |
Mastery | |
Level | |
evt.SetNPCGroupNews[MM7+]Параметры: |
|
NPCGroup | |
NPCNews | |
evt.SetMonsterGroup[MM7+]Параметры: |
|
Monster | |
NPCGroup | |
evt.SetNPCItem[MM7+]Параметры: |
|
NPC | |
Item | |
On | |
evt.SetNPCGreeting[MM7+]Параметры: |
|
NPC | |
Greeting | |
evt.CheckMonstersKilled[MM7+]Параметры: |
|
CheckType | 0 – any monster, 1 – in group, 2 – of type, 3 – specific monster, 4 – specific monster by name (MM8) |
Id | Depending on CheckType: 0 – not used, 1 – group id, 2 – monster type minus 1, 3 – monster id, 4 – id in placemon.txt (MM8 only) |
Count | 0 – all must be killed, else a number of monsters that must be killed |
InvisibleAsDead | [MM8] 1 (default) – treat invisible (that is, currently disabled, like pirates in Ravenshore before you enter Regna) monsters as dead when counting, 0 – include invisible monsters |
evt.ChangeGroupToGroup[MM7+]Параметры: |
|
Old | |
New | |
evt.ChangeGroupAlly[MM7+]Параметры: |
|
NPCGroup | |
Ally | Monster class that guards this group. That is, (Id + 2):div(3), like in Hostile.txt. |
evt.CheckSeason[MM7+]Параметры: |
|
Season | |
evt.SetMonGroupBit[MM7+]Параметры: |
|
NPCGroup | |
Bit | |
On | |
evt.SetChestBit[MM7+]Параметры: |
|
ChestId | |
Bit | |
On | |
evt.FaceAnimation[MM7+]Параметры: |
|
Player | |
Animation | |
evt.SetMonsterItem[MM7+]Параметры: |
|
Monster | |
Item | |
Has | |
evt.StopDoor[MM8]Параметры: |
|
Id | |
evt.CheckItemsCount[MM8]Параметры: |
|
MinItemIndex | |
MaxItemIndex | |
Count | |
evt.RemoveItems[MM8]Параметры: |
|
MinItemIndex | |
MaxItemIndex | |
Count | |
evt.Jump[MM8]Параметры: |
|
Direction | |
ZAngle | |
Speed | |
evt.IsTotalBountyInRange[MM8]Параметры: |
|
MinGold | |
MaxGold | |
evt.CanPlayerAct[MM8]Параметры: |
|
Id | from Roster.txt |
evt.RefundChestArtifactsTo be added in 2.5.6 or 2.6 of the patches. Removes all artifacts randomly generated in the chest from Party.ArtifactsFound.Параметры: |
|
Id |
Events
Structs\After\ Spells.luaСобытия: |
|
MonsterCastSpell{Action CallDefault Direction Handled Monster MonsterIndex ObjectType Skill [MM7+] Sound Spell } |
Can be used to change how a spell works when cast by a monster. Sound and ObjectType aren't assigned initially, you can set them to change what sound the spell makes and what projectiles it has. CallDefault(FakeSpell, FakeSkill) would use logic from FakeSpell with FakeSkill, but change sound and any created projectiles to match what you've defined in the table. Example: -- allow Poison Spray to be cast by monsters events.MonsterCastSpell = |t| if t.Spell == 24 then local sk, mas = SplitSkill(t.Skill) if mas >= const.Expert then t.CallDefault(15, JoinSkill(sk, mas - 1)) -- use Sparks as a template else t.CallDefault(2) -- use Fire Bolt as a template end end |
EventCastSpell{CallDefault FromX FromY FromZ Handled Mastery ObjectType Skill Sound Spell ToX ToY ToZ } |
Can be used to change how a spell works when cast by evt.CastSpell. Sound and ObjectType aren't assigned initially, you can set them to change what sound the spell makes and what projectiles it has. CallDefault(FakeSpell, FakeMastery, FakeSkill, x1, y1, z1, x2, y2, z2) would use logic from FakeSpell with FakeMastery and FakeSkill, but change sound and any created projectiles to match what you've defined in the table. Coordinates can also be changed. Complex example: -- Enables Paralyze spell to be used by monsters and evt.CastSpell
-- You would also need to add the projectiles to ObjList.txt and SFT.txt in Data\Tables\ local spPara = const.Spells.Paralyze local objPara = Game.SpellObjId[spPara] local handler = |t| if t.Spell == spPara then t.CallDefault(2) -- Fire Bolt, because it simply plays a sound and creates a projectile end events.MonsterCastSpell = handler events.EventCastSpell = handler events.ReadMonsterSpell = |t| if t.Name == "paralyze" then t.Result = spPara end events.PlayerAttacked = |t| if not t.Handled then local o = t.Attacker.Object if o and o.Type == objPara then t.Handled = true t.Player:DoBadThing(const.MonsterBonus.Paralyze, t.Attacker.Monster or Map.Monsters[0]) end end events.MonsterAttacked = |t| if not t.Handled then local o, mon = t.Attacker.Object, t.Monster if o and o.Type == objPara then t.Handled = true if mon:CalcHitByEffect(Game.SpellsTxt[spPara].DamageType) then mon.CurrentActionLength = 128 mon.AIState = 0 mon.SpeedX = 0 mon.SpeedY = 0 mon.SpeedZ = 0 mon:UpdateGraphicState() mon.SpellBuffs[const.MonsterBuff.Paralyze]:Set(Game.Time + 3*const.Minute*o.SpellSkill, o.SpellLevel) mon:ShowSpellEffect() end end end |
ReadMonsterSpell{word1, word2, ...;Name Result } |
If spell name is "Hour of Power", the table passed to event would be {"hour", "of", "power", Name = "hour of power"}, all in lower case. Example: -- allow Poison Spray to be read from Monsters.txt events.ReadMonsterSpell = |t| if t.Name == "poison spray" then t.Result = 24 end |
Core\ events.luaСобытия: |
|
CalcSpellDamage{HP HitPoints Mastery Result Skill Spell } | |
WalkToMap{Days [MM7+] EnterMap EnterSide [MM7+] LeaveMap LeaveSide [MM7+] X Y } |
Sides: 0, "up", "down", "left", "right". 0 means "party start" sprite. |
DeathMap{Name Set } | |
NewGameMap{AutoFallStart Set } | Set(x, y, z, direction, lookAngle, speedZ) function sets both party position (saved in autosave) and map transition (used on start immediately). |
NewGameDefaultParty() | |
NewGameClearParty() | |
LoadedRosterTxt() | Loaded roster.txt and pcnames.txt |
GameInitialized0() | loaded icons.lod, events.lod[MM7], language LODs[MM8]; about to start loading global.txt |
GameInitialized1() | loaded all archives except games.lod, loaded global.txt and .bin data |
GameInitialized2() | loaded .txt data, global.evt and all archives, intro shown, various bitmaps, sprites and sounds loaded |
CanSaveGame{IsArena SaveKind } |
SaveKind: 0 – normal, 1 – autosave, 2 – quick save If IsArena is true, the "No saving on the Arena" message is displayed |
CanCastLloyd() | |
IsUnderwater{Map Result } | [MM7+] |
FogRange() | |
PopulateQuestLog() | Use this event to add quest indexes to Game.DialogLogic.List or rearrange them |
PopulateAutonotesList{Category } | Use this event to add autonote indexes to Game.DialogLogic.List or rearrange them |
PopulateAwardsList{NoShuffle Player PlayerIndex } | Use this event to add award indexes to Game.DialogLogic.List or rearrange them. Awards would later be arranged into groups of different colors. If NoShuffle is set to true, their order within groups would be preserved, otherwise default game code will sort them in an unpredictable manner. |
MonsterInfoPictureChanged(MonId) | Called when monster kind in monster info dialog changes. Game.DialogLogic.MonsterInfoMonster holds the monster prototype being displayed. This is the event you can use to change Game.PatchOptions.MonSpritesSizeMul. |
WindowMessage{Handled LParam Msg Result WParam Window } | |
KeyDown{Alt ExtendedKey Handled Key WasPressed } | |
KeyUp{Alt ExtendedKey Handled Key WasPressed } | |
PostRender() | |
Action{Action Handled Param Param2 } | |
MenuAction{Action Handled Param Param2 } | |
ExitMapAction{Action } | |
KeysFilter{Key On Result } | |
BeforeSaveGame() | |
BeforeNewGameAutosave() | |
AfterNewGameAutosave() | |
AfterSaveGame() | |
SkyBitmap{FirstVisit Result } | |
LoadSavedMap{Data = Raw ddm or dlv data FacetsCount = [MM7+] Total numuber of facets on the map IsIndoor IsOutdoor } |
You can do a number of things here: 1. Set Map.LastRefillDay to 0 to force a refill. 2. In MM7+ you could handle games saved in an older version of your mod. The game checks Map.SanitySpritesCount against Map.Sprites.Count, Map.SanityFacetsCount against FacetsCount, and on outdoor maps Map.SanityModelsCount against Map.Models.Count. If all sanity fields are non-zero and either of them doesn't match the real count, the game forcibly refills the map. You can do a similar check, and either change Data (use mem.free and mem.malloc if needed) or backup monsters, objects, chests and visible map data and restore them in CancelLoadingMapScripts event (that's the first of events that fires once the map is loaded). Not an easy task, but it will provide saves compatibility when signinficant changes to maps happen. Important: Map.Name at this point is changed from "map.odm"/"map.blv" to "map.ddm"/"map.dlv". Another note: Map.SanityDoorDataSize was added in MMExtension. At this point you can check it against Map.IndoorHeader.DoorDataSize, later on DoorDataSize gets replaced with SanityDoorDataSize if the latter is non-zero. |
PlayMapTrack{MapIndex Track } | |
ShowMovie{Allow CallDefault = function() DoubleSize ExitCurrentScreen Name Y } | |
PlaySound{Allow CallDefault = function() Loops ObjRef Sound Speed UnkParam Volume X Y } | |
FaceAnimation{Allow Animation CallDefault = function() Face ForceSound Player PlayerIndex Sound SoundCount SoundOffset } | |
CalcStatBonusByItems{ArtifactBonus [MM7+] IgnoreExtraHand MagicBonus [MM7+] Player PlayerIndex Result SetArtifactBonus SetMagicBonus Stat } |
Here's how SetArtifactBonus(value) method works: [MM7+] If value is bigger than ArtifactBonus, it modifies ArtifactBonus and increases Result. [MM6] It just adds the value to Result. The game does the same, but only takes one instance of each artifact into consideration. SetMagicBonus does the same to MagicBonus. |
CalcStatBonusByMagic{Player PlayerIndex Result Stat } | |
CalcStatBonusBySkills{Player PlayerIndex Result Stat } | |
GetSkill{Player PlayerIndex Result Skill } | [MM7+] |
GetAttackDelay{Player PlayerIndex Ranged Result } | |
CalcDamageToPlayer{Damage DamageKind Player PlayerIndex Result } | |
GetMerchantTotalSkill{Player PlayerIndex Result } | |
GetDisarmTrapTotalSkill{Player PlayerIndex Result } | |
GetDiplomacyTotalSkill{Player PlayerIndex Result } | [MM6] |
GetPerceptionTotalSkill{Player PlayerIndex Result } | [MM7+] |
GetLearningTotalSkill{Player PlayerIndex Result } | [MM7+] |
DoBadThingToPlayer{Allow Monster [MM7+] MonsterIndex [MM7+] Player PlayerIndex Thing } | |
GetStatisticEffect{Result Value } | |
UseMouseItem{ActivePlayer ActivePlayerIndex Allow CallDefault = function() IsPortraitClick Player PlayerSlot } | |
CanLearnSpell{NeedMastery Player PlayerIndex Spell } | |
Regeneration{HP Player PlayerIndex SP } |
HP and SP don't include regeneration values assigned by the game, but setting them takes care of conditions !k{Player :structs.Player} |
ModifyItemDamage{Damage Item MonsterId Player PlayerIndex Result Slot } | |
GenerateItem{AlwaysEnchant Handled Item Kind Strength } | |
ItemGenerated{AlwaysEnchant Handled Item Kind Strength } | |
MonsterKilled(mon, monIndex, defaultHandler) | |
MonsterKillExp{Exp Handled Monster MonsterIndex } | |
ItemAdditionalDamage{DamageKind Item Result Vampiric } | [MM7+] |
CalcDamageToMonster{Damage DamageKind Monster MonsterIndex Result } | |
PickCorpse{Allow CallDefault = function() Monster MonsterIndex } | |
CastTelepathy{Allow CallDefault = function() Monster MonsterIndex } | [MM7+] |
CanMonsterCastSpell{Allow Distance [MM8] Monster MonsterIndex Spell } | [MM7+] |
MonsterChooseAction{Action CallDefault = function() Distance [MM8] Monster MonsterIndex } | Action starts uninitialized. Each time you call CallDefault, it generates new result, assigns it to Action and returns the value. |
MonsterAttacked({Attacker = table returned by WhoHitMonster Handled Monster MonsterIndex }, attacker) |
Called when a player or a projectile tries to hit a monster. Can be used to completely replace what happens. Doesn't get triggered when using Armageddon or Finger of Death. |
AfterMonsterAttacked({Attacker = table returned by WhoHitMonster Handled = carried over from MonsterAttacked event Monster MonsterIndex }, attacker) | |
PlayerAttacked({Attacker = table returned by WhoHitPlayer Handled Player PlayerSlot }, attacker) |
Called when a monster or a projectile tries to hit a player. Can be used to completely replace what happens. Doesn't get triggered when using Armageddon. |
AfterPlayerAttacked({Attacker = table returned by WhoHitPlayer Handled = carried over from PlayerAttacked event Player PlayerSlot }, attacker) |
Core\ evt.luaСобытия: |
|
LeaveMap() | |
LeaveGame() | |
BeforeLoadMap(WasInGame, WasLoaded) | |
CancelLoadingMapScripts(WasInGame) | Return true to cancel execution of map scripts. Used by the Editor. |
BeforeLoadMapScripts(WasInGame) | |
LoadMapScripts(WasInGame) | Use this event instead of LoadMap in Global and General scripts |
LoadMap(WasInGame, NoScripts) | NoScripts = true if map scripts execution was cancelled by CancelLoadingMapScripts event. |
AfterLoadMap(WasInGame) | |
GetEventHint(evtId) | |
GetMazeInfo() | |
EvtMap(evtId, seq) | |
EvtGlobal(evtId, seq) |
Core\ main.luaСобытия: |
|
StructsLoaded() | |
ScriptsLoaded() |
Core\ npc.luaСобытия: |
|
EnterAnyNPC({Index Kind NPC }, npc) | Happens before events.EnterNPC. Kind ("NPC", "HiredNPC", "StreetNPC") defines the array NPC belongs to and Index is index in that array. |
EnterNPC(Index) | Only called for NPCs from Game.NPC array, not for street or hired NPCs |
ShowNPCTopics(Index) | NPC topics are about to be shown and you can update them here |
ShowHiredNPCTopics(Index, RealNPC) |
Happens only in MM6 when you talk to a hired NPC. Index is the index in Party.HiredNPC array. RealNPC is the index of the prototype NPC in Game.NPC array or nil. |
DrawNPCGreeting{NPC Seen Text } | |
SpeakWithMonster{Monster MonsterIndex Result } | [MM7+] Called when you speak with a guard or any other monster with a generic message from NPCGroup.txt. Assign Result a string to override default monster group message. Assign an empty string to show no message. Initially Result is nil. |
CanExitNPC{Allow Must NPC } | If Must is true, the handler can still set Allow to false, but can't fully cancel the exit. After CanExitNPC cancels it 100 times, the exit will happen unconditionally. |
CanExitStreetNPC{Allow Index Kind Must NPC } | |
CanExitHiredNPC{Allow Index Kind Must NPC RealNPC } | RealNPC is the index of the prototype NPC in Game.NPC array or nil. |
ExitNPC(CurrentNPC) | |
ExitAnyNPC{Index Kind NPC } | |
ExitHouseScreen(Game.HouseScreen) | |
CanTeachSkillMastery{Allow Cost Mastery Skill Text } | |
CanTempleHealPlayer{House Player PlayerIndex Result } | |
GetShopItemTreatment{Action House HouseType Item Player PlayerIndex Result } |
Action: "buy", "sell", "identify", "repair" Result: 0-based option from merchant.txt GetDefault(HouseType, House, Item, Action, Player) function lets you get item treatment by another shop type (all parameters are optional) |
CanShopOperateOnItem{Action House HouseType Item Result } |
Action: "buy", "sell", "identify", "repair" GetDefault(House, Item) function lets you get item treatment by another shop type (all parameters are optional) |
ShopItemsGenerated{House HouseType } | |
GuildItemsGenerated{House HouseType } | Note that you'll have to update Game.GuildItemIconPtr if you change items in this event (see an example there). |
HouseMovieFrame{House } | |
ArcomageSetup(arcomage, house) | |
ArcomageText{House Result } |
Lets you modify Victory Conditions text. Result is not pre-initialized. Instead, you need to call GetDefault function to get the default string. |
ArcomageWin(house) | |
NewBountyHunt{House Index Result } | Assign Result to specify the target monster for the hunt |
BountyHuntDone{Gold House Index } | If you modify Gold here, it wouldn't be in line with the promised sum, but you may introduce other rewards for example |
SetMapNoNPC() | [MM7] Use this event if you need to set Map.NoNPC |
PopulateNPCDialog({DlgKind Index Kind NPC Result }, npc) |
Change topics of an NPC dialog. Result is an array of NPC commands from const.HouseScreens. Names from const.HouseScreens as text are also allowed. You can also add a table with extra parameters, see the example below. Kind ("NPC", "HiredNPC", "StreetNPC") defines the array NPC belongs to and Index is index in that array. The following DlgKind values are possible: "Main" – Regular NPC conversation. In MM6 this is also the Dismiss conversation with a hired NPC. "StreetNPC" – Conversation with a street NPC that you can hire. In MM7 this is also the Dismiss conversation with a hired NPC. In MM6 it ratains items you add to beg/threat/bribe menu. "LackFame" – Not enough fame to communicate with a street NPC. Unused. "BegThreatBribe" – Beg/Threat/Bribe menu in MM6. "ThreatBribe" – Beg/Threat/Bribe menu, but "Beg" option won't do anything, because you've already begged the NPC before. "JoinMenu" – Join party menu in MM6, MM7. "JoinRoster" – Join party menu in MM8. "TeachSkill" – Expert/Master/GM teaching. "JoinGuild" – Join a guild. "BountyHuntNPC" – Bounty Hunt NPC topic. Only utilized by MM6. "ArenaMenu" – Any Arena menu. "SeerPilgrimage" – Pilgrimage in MM6. |
AfterPopulateNPCDialog({DlgKind ExtraParams Index Kind NPC Result }, npc) | |
PopulateHouseDialog{House PicType Result } |
Change topics in the main dialog menu in a house, unless isn't an NPC conversation. Unfortunately, the captions displayed won't change as they are hard-coded in various places. Result is an array of topic numbers from const.HouseScreens. Names from const.HouseScreens as text are also supported. Example: events.PopulateHouseDialog = |t| if t.PicType == const.HouseType.Training then t.Result = {"Train"} -- disable learning skills at training halls end |
PopulateArcomageDialog{House PicType Result } | |
PopulateDisplayInventoryDialog{House PicType Result } | |
AfterPopulateHouseDialog{ExtraParams House PicType Result } | There are also similar AfterPopulateArcomageDialog and AfterPopulateDisplayInventoryDialog events |
PopulateLearnSkillsDialog{House PicType Result } |
[MM7+] Change skills in Learn Skills dialog. Result is an array of skill numbers. Skill names from const.Skills are also allowed. Example: events.PopulateLearnSkillsDialog = |t| if t.PicType == const.HouseType.Tavern then t.Result[#t.Result + 1] = "Blaster" -- devs apperently forgot to make taverns teach you Blaster skill end |
AfterPopulateLearnSkillsDialog{House PicType } | |
BeforeDrawDialogs() | |
BeforeDrawDialog{Dialog DlgID DrawnCount Index } | Called when a dialog is just about to be drawn. Index goes from 1 to Game.Dialogs.Count and you can change if you have to. |
DrawDialog{Dialog DlgID DrawnCount Index } | Note that some dialogs get destroyed once they are drawn. When that happens, Dialog is nil. |
AfterDrawDialog{Dialog DlgID DrawnCount Index } | |
AfterDrawDialogs(DrawnCount) | Called after drawing dialogs |
AfterDrawNoDialogs(0) | Called in place of drawing dialogs when no dialog is active. The reason it's separated from AfterDrawDialogs event is to improve performance, because this event would usually stay unused. |
NewDialog(dlg, id) | This function is called once a new dialog finishes creation. Note that in case of house dialogs, they internally create an extra dialog with DlgID = 1 for dialog topics, this leads to NewDialog event getting triggered for that extra dialog before the one for the base dialog, however both dialogs are already created and added to Game.Dialogs when either event fires. |
BeforeDestroyDialog(dlg, id) | |
DestroyDialog(dlg, id) | |
AfterDestroyDialog(dlg, id) | |
BeforeShowOODialog{ClassPtr = This lets you know what dialog is being created even if DialogPtr got changed by the event DialogPtr Param } | |
AfterShowOODialog{ClassPtr = This lets you know what dialog is being created even if DialogPtr got changed by the event DialogPtr Param Result } | |
CloseOODialog{DialogPtr } | |
DrawProgressBar() | |
HideProgressBar() |
Core\ timers.luaСобытия: |
|
Tick() |
Modules\ Faces.luaСобытия: |
|
BeforeUpdateFaces(JustRead) | Triggered when "Faces.txt" is read or when Update is called. |
AfterUpdateFaces(JustRead) | Triggered after the changes to Faces were applied. |
Modules\ PaperDoll.luaСобытия: |
|
ReloadPaperDollGraphics() | When corresponding ReloadPaperDollGraphics function is called |
PaperDollHiddenPieces({arm1 = 1st arm when holding a weapon arm1f = 1st arm without a weapon arm2 = 2nd arm without 2-handed weapon arm2b = 2nd arm without 2-handed weapon, drawn behind armor arm2f = 2nd arm when not holding anything arm2fb = 2nd arm when not holding anything, drawn behind armor arm2h = 2nd arm for 2-handed weapon arm2hb = 2nd arm for 2-handed weapon, drawn behind armor evil = evil path interface in MM7 game = in game (for BackDoll in MM8) good = good path interface in MM7 hand1 = 1st hand when holding a weapon hand1a = 1st hand (always drawn) hand1f = 1st hand when not holding a weapon hand2 = 2nd hand for dual-wielding hand2f = 2nd hand when not holding anything hand2h = 2nd hand for 2-handed weapon menu = in new game menu (for BackDoll in MM8) neutral = neutral interface noring = rings menu closed ring = rings menu open shield = drawn when holding a shield }, player, InMenu, DrawOffsetX, DrawOffsetY) |
Here I've described pieces that PaperDoll module handles automatically. You can define when your own pieces are drawn through PaperDollDrawOrder array and hide them conditionally here. InMenu is true if it's a new game menu in MM8, in which case DrawOffsetX and DrawOffsetY are non-zero. |
PaperDollGetItems(t, player, InMenu, DrawOffsetX, DrawOffsetY) |
Lets you modify weared items, such as add new weared item slots. E.g. setting t.My = 1 would draw pl.Items[1]. Setting t.My = true would make ":My" drawn the same way ":Player" is drawn. You'll also need to add "My" to PaperDollDrawOrder. InMenu is true if it's a new game menu in MM8, in which case DrawOffsetX and DrawOffsetY are non-zero. |
PaperDollBeforeDoll(player, InMenu, DrawOffsetX, DrawOffsetY) |
Called before the paper doll is drawn after drawing the background. InMenu is true if it's a new game menu in MM8, in which case DrawOffsetX and DrawOffsetY are non-zero. |
PaperDollAfterDoll(player, InMenu, DrawOffsetX, DrawOffsetY) |
Called after the paper doll is drawn before drawing UI elements. InMenu is true if it's a new game menu in MM8, in which case DrawOffsetX and DrawOffsetY are non-zero. |
PaperDollAfterDraw(player, InMenu, DrawOffsetX, DrawOffsetY) |
Called after the paper doll is drawn. InMenu is true if it's a new game menu in MM8, in which case DrawOffsetX and DrawOffsetY are non-zero. |
General Functions
Structs\After\ Backup.luaФункции: |
|
LocalFile(t) | Pass any table from Game.* to this function to make it restore its original state after the player exits the map. |
LocalMonstersTxt() | |
LocalHostileTxt() | [MM7+] |
LocalNPCNews() |
Structs\After\ Dialogs.luaФункции: |
|
CustomDialog{...;CustomDialog DlgID Height Left Param StrParam Top Width } |
Structs\After\ Draw.luaФункции: |
|
DrawScreenEffectD3D(BitmapIndex, u, v, du, dv, x1, y1, x2, y2, cl, cl2, cl3, cl4) |
Structs\After\ Functions.luaФункции: |
|
SplitSkill(val) | |
JoinSkill(skill, mastery) | |
XYZ(t, x, y, z) |
Get X,Y,Z fields: local x, y, z = XYZ(Party) Set X,Y,Z fields: XYZ(Party, x, y, z) Enumerate "X", "Y", "Z" strings: for X in XYZ do print(Party[X]) end |
ClearConsoleEvents() | |
Message(text, KeepSound, global) | |
Question(text, qtext) |
Returns the reply. text is shown as message, qtext is shown at the beginning of reply field. Doesn't work in houses in MM7. |
ReplaceNPCTopic(old, new) | Searches through all NPC topics and replaces one topic with another |
SuppressSound(on) | |
ExitScreen(process) | Simulates Esc press |
ReloadHouse(id) |
Rebuilds house dialog, e.g. after you've moved an NPC to or from this house. Can seemlessly transition between different houses if id is specified. Simply closes the house if id is '-1'. |
SwitchHouseMovie(s, loop) | Exits currently playing movie and loads the specified one |
DrawSimpleMessage() | Draw simple message in screens where it isn't normally supposed to be |
HouseMessage(text) | show a message in houses in screens that don't normally support it |
AddGoldExp(gold, exp) | |
TakeItemFromParty(id, keep) | id can also be a table or a table of tables. See Quest Alchemy.lua from quest examples |
CheckMonstersKilled{Group Monster MonsterIndex NameId Count InvisibleAsDead } | See Quest Kill Monsters.lua from quest examples |
EnumAvailableSkills(class) | Returns Skill, MaxMastery |
RGB(r, g, b) |
else end end |
StrLeft(v) | |
StrRight(v) | |
StrColor(r, g, b, s) | |
PcxCache(EnglishD) |
Example – loading: local t = PcxCache(true) local win = t["winBG.PCX"] local lose = t["LOSEBG.PCX"] Drawing: Screen.DrawPcx(0, 0, win) Clearing cache deletes all loaded images: t("Clear") You can also reload all images, say, if you conditionally load a LOD with an inteface skin (all obtained addresses stay the same): t("Reload") Pass file name as second argument when invoking "Clear" or "Reload" to handle a specific file only. |
IconCache() | Same as PcxCache, but for in-place icons, which means loaded icons aren't stored in Game.IconsLod.Bitmaps, but instead stored in the cache until it's cleared |
SummonMonster(id, x, y, z, treasure, place) |
Unless treasure is true, the monster doesn't have any items or gold. place defines monster index in Map.Monsters array if specified. |
SummonItem(number, x, y, z, speed) | |
RebildIDList() | |
ChangeSprite(n, name) | |
CreateSprite{name, x, y, z;Bits X Y Z } |
Warning: In MM7+ sprite bits are stored in the save game. Thus, adding sprites would cause mismatch between Map.SanitySpritesCount and Map.Sprites.Count next time the game is loaded (see LoadSavedMap event for more info on that). If you do decide to use this function in a live MM7+ game, I recommend setting Map.Sprites.Count to normal amount in BeforeSaveGame event and restoring current amount in AfterSaveGame. |
MoveModel(m, dx, dy, dz, MoveParty) | MoveParty isn't supported yet |
Structs\After\ LocalizationAndQuests.luaПеременные: |
|
TakeQuestOperation |
Should be either "Add" or "Set". This determines the overlay flash on character face when a quest is taken. [MM6, MM8] Defaults to "Add". [MM7] Defaults to "Set". |
Quests | |
GenerateLocalization_BakFiles | Set it to false in a General script to turn off *.bak files creation when generating localization |
GameLocalizationIgnore | List of table names in Game structure that shouldn't be included in localization by GenerateGameLocalization |
GameLocalizationSchema | Defines which files contain which names of Game structure tables and more (see in code) |
QuestNPC | |
vars.Quests[name] | Quest states: nil, "Given", "Done" or a custom state. |
vars.QuestAwards[name] | |
vars.QuestAutonotes[name] | |
Функции: |
|
LocalizeAll(t, over) |
See Localization. Possible values of over: true: permanent setup – overwrite all (used in Localization scripts only) false: temporary setup – overwrite temporary setup only "update": remove all previous temporary setup, overwrite temporary setup only |
Localize(t, over, lev = 1) |
See Localization. Possible values of over: true: permanent setup – overwrite all (used in Localization scripts only) false: temporary setup – overwrite temporary setup only "update": remove all previous temporary setup, overwrite temporary setup only |
GenerateQuestsLocalization(IsLua) | Generates localization file for quests created with functions from this file. |
GenerateLocalization(IsLua, IncludeQuests) |
Generates localization files for scripts that call Localize or LocalizeAll functions. Pass IsLua = true to generate *.lua files instead of *.txt tables. Whichever is more convenient for you. Unless IncludeQuests is false, localization for quests is also generated. |
GenerateGameLocalization() | Generates localization files for various game data found in TXT files. Returns(in text form) the list of files not included in the generated localization. |
ShowQuestEffect(flash_book, operation) |
Plays sound and shows visual effect on current character's face. If flash_book is true, the quest book will start flashing. |
ShowAwardEffect(exclude, operation) |
Plays sound and shows visual effect on all characters' faces. exclude can be a function(player, slot) that returns true if the character should be excluded from the effect. |
ShowAutonoteEffect(category, just_sound, operation) | Plays sound and shows visual effect on current character's face |
AutoQuest(t, text) | t can be a function(t), which returns true if quest should be visible in the quest log |
AutoAward(t, text, sort) | t can be a function(t, player_index, player), which returns true if award should be visible on the Awards page |
AutoAutonote(t, text, category) | t can be a function(t), which returns true if autonote should be visible |
GetLocalName(name, lev) | |
Autonote(name, cat, text) | Creates a named autonote. To operate on global named autonotes, use ":" at the beginning of its name. |
AddAutonote(name, force) | Adds a named autonote to Auto Notes. force = true makes it emit the sound even if autonote is already added |
CheckAutonote(name) | Returns true if named autonote was added to Auto Notes |
FindAutonote(name, must) | |
UpdateNPCQuests() | |
QuestBranch(branch, persist) |
Sets current dialog branch to branch if it's specified. persist parameter makes the branch persist after you reenter NPC dialog. Returns current branch when called without parameters. If there is no persisted branch name, when you enter NPC dialog the branch is set to "". |
QuestBranchScreen(branch) | Switches dialog branch to branch, but returns to current branch upon pressing Esc. |
ExitQuestBranch(all) | Exits current branch opened with QuestBranchScreen. If no branch screens are left open, simulates Esc press to exit the dialog. |
GetQuestBranchStack() | Returns a table with branch names stored by QuestBranchScreen function (on each call it adds previous branch to the end of this table). |
Quest{name;AddAutonote AddAward AddQuestBit After Award AwardIndex Awards BaseName Branch CanAddAutonote CheckDone CheckGive Done DoneState Event Execute Exp Experience FirstStdTopic GetGreeting GetTopic Give GivenItem GivenState Gold IsAwarded IsGiven KeepQuestItem NPC Name NeverDone NeverGiven Quest QuestGold QuestIndex QuestItem RewardItem SetTexts Slot StdTopic StdTopicDone StdTopicGiven StoreAwards TakeQuestOperation Texts Undone Ungive } | See quest examples |
Greeting{text, textSeen;Text TextSeen ... Quest() parameters ... } | See quest examples |
NPCTopic{topic, text;Topic Text ... Quest() parameters ... } | See quest examples |
KillMonstersQuest{name = nil, ... A list of either tables with CheckMonstersKilled() parameters or partial completion messages ...;... Quest() parameters ... } | See Quest Kill Monsters.lua from quest examples |
QCheck(name, state) |
Mostly for backward compatibility. A function to show a topic only when the name quest is in state state. name defaults to current quest name. Examples: QCheck('MyQuest') = || vars.Quests.MyQuest == nil QCheck('MyQuest', 'Done') = || vars.Quests.MyQuest == 'Done' QCheck() = |t| vars.Quests[t.BaseName] == nil QCheck(nil, 'Done') = |t| vars.Quests[t.BaseName] == 'Done' |
Structs\After\ Spells.luaФункции: |
|
BeginGrabObjects() | Starts recording all spawned objects. You can call it prior to calling evt.SummonObject or Game.SummonObjects and then call GrabObjects afterwards to get all created objects. |
GrabObjects() | Returns all (up to 1000) objects spawned since last call to BeginGrabObjects |
Core\ Common.luaФункции: |
|
assertnum(v, level, msg) | |
tget(t, k, ...) |
Returns t[k] if it exists, otherwise sets t[k] = {} and returns t[k]. The process is repeated for additional parameters, e.g. t[k][k1] |
pcall2(...) | Like pcall, but in case of an error shows error message |
xpcall2(...) | Like xpcall, but in case of an error shows error message |
cocall(f, ...) | Same as coroutine.resume(coroutine.create(f), ...) |
cocall2(f, ...) | Like cocall, but in case of an error shows error message |
dofile2(path, ...) | Loads file in protected mode, in case of an error shows error message. Return format is the same as that of pcall |
coroutine.resume2(...) | Like coroutine.resume, but in case of an error shows error message |
os.GetErrorText(code) | |
path.find(filter, dir) | |
path.FindFirst(filter, dir) | |
path.findfirst(filter, dir) | |
os.chdir([dir]) | Returns previous current directory. Call without parameters to look up current dirrectory |
os.mkdir(dir) | |
os.copy(old, new, FailIfExists) | |
path.GetRelativePath(from, to, isDir) | |
string.convert(s, encFrom, encTo, defChar) | |
debug.FunctionFile(f) |
Core\ Debug.luaФункции: |
|
debug.HideConsole() |
Core\ ErrorFunction.luaФункции: |
|
errorinfo(s) | |
tostring2(v, lim, tabs) |
Core\ RSMem.lua…Переменные: |
|
mem.i1[p], mem.i2[p], mem.i4[p], mem.i8[p] |
Read/write signed integer at address p. Can also be called to convert a number to specified format. For example, for a function that returns a signed byte: return mem.i1(mem.call(func, 0)) This would treat function call result as a signed byte, ignoring 3 higher-order bytes. |
mem.u1[p], mem.u2[p], mem.u4[p], mem.u8[p] | Read/write unsigned integer at address p. Can also be called to convert a number to specified format. |
mem.r4[p], mem.r8[p], mem.r10[p] | Read/write a floating-point number at address p |
Функции: |
|
mem.string(p, size, ReadNull) |
mem.string(p) – read null-terminated string mem.string(p, size) – read null-terminated string no bigger than size bytes mem.string(p, size, true) – read size bytes as string |
mem.call(p, cc, ...) |
p is the function address, cc is the number of parameters passed through registers: 0 – __stdcall or __cdecl, 1 – __thiscall, 2 – __fastcall, 3 – 3rd parameter in eax (eventhough the game doesn't use it), ... are the parameters. Another way to call: mem.call{p = 0x441EFD, cc = 0, ...} |
mem.IgnoreProtection(on) | Pass true to be able to modify code with mem.i4 and such, pass false after you've finished. |
mem.prot(on) | Same as above. |
mem.malloc(size) | Allocate memory with the malloc function of the game. Shouldn't be called before the game starts initializing, it may cause slowness, because the allocator isn't yet initilized. Instead call mem.allocMM or mem.StaticAlloc. |
mem.alloc(size) | Same as above. |
mem.free(p) | |
mem.realloc(p, size) | |
mem.new(size, f, ...) | |
mem.StaticAlloc(size) | |
mem.copy(dest, src, count) | count can be omitted if src is a string or a structure |
mem.fill(ptr, n, c = 0) | |
mem.cmp(ptr1, ptr2, n) | |
mem.LuaAlloc(size) | |
mem.func(...) | |
mem.LoadDll(name, cc) | |
mem.UnloadDll(t) | |
mem.GetProcAddress(p, proc) | |
mem.structs.getdefine() | |
mem.structs.getunions() | |
mem.structs.CustomType(name, size, f) | |
mem.struct(f, class, p) | |
mem.GetHookSize(p) |
Returns n, short, long. n is the number of bytes occupied by instructions at address p. n is 5 or more, because placing a hook requires 5 bytes. short is true if the code contains a short jump leading outside of it. long is true if the code contains a near jump or call to a relative address. |
mem.GetInstructionSize(p) |
Returns n, short, long. n is the number of bytes occupied by the instruction at address p. short is true if the instruction is a short jump and it doesn't lead to itself. long is true if the instruction is a near jump or call to a relative address. |
mem.findcode(p, s, p2) | Takes a string to search for. Only checks for a match at the start of a new instruction. |
mem.findcall(p, fptr, p2) | Finds a call to fpts starting at p and stopping at p2 (optional). If fptr isn't specified, searches for any call instruction. |
mem.enumcalls(p1, p2, fptr) | Enumerates all calls to fptr. If fptr isn't specified, enumerates all function calls. |
mem.hook(p, f, size) | Primitive call hook: 5-byte call instruction that calls into Lua code |
mem.hookjmp(p, f, size) | Primitive jump hook |
mem.hookalloc(size) | Allocate memory for code |
mem.hookfree(p) | |
mem.copycode(ptr, size, MemPtr, NoJumpBack, DuplicateHooks) |
Copies standard code into a memory block and then writes a jump back into the function (the copied code must not contain short jumps that lead outside of it) MemPtr can optionally specify a pre-allocated memory address. If DuplicateHooks is true, Lua hooks are kept in both new and old code, otherwise they're moved to the new location. |
mem.autohook(p, f, size) |
hookjmp with automatic calling of overwritten code (see copycode note) If the function returns true, the jump to original code isn't performed |
mem.autohook2(p, f, size) |
hookjmp with automatic calling of overwritten code (see copycode note) The function is called after the overwritten code If the function returns true, the jump to original code isn't performed |
mem.bytecodehook(p, code, size) |
Like autohook, but takes a compiled Asm code string as parameter code can also be a function f(ptr). ptr is the address of memory allocated for hook code or nil (to calculate size) |
mem.bytecodehook2(p, code, size) |
Like autohook2, but takes a compiled Asm code string as parameter See note of bytecodehook about code |
mem.bytecodepatch(p, code, size) |
Replaces original instructions with new ones, jumping out if needed See note of bytecodehook about code |
mem.asm(code) | Compiles Asm code and returns resulting binary as string |
mem.asmhook(p, code, size) |
Like autohook, but takes an Asm code string as parameter. Example (from MM7): mem.asmhook(0x441D4C, [[ cmp dword [0xE31AF0], 0 jnz absolute 0x441D51 ]]) Original Asm code: .text:00441D4C call sub_4C2E6C .text:00441D51 mov ecx, offset unk_511768 Resulting Asm code: .text:00441D4C jmp @p .text:00441D51 mov ecx, offset unk_511768 @p: cmp dword [0xE31AF0], 0 jnz 0x441D51 call sub_4C2E6C jmp 0x441D51 |
mem.asmhook2(p, code, size) |
Like autohook2, but takes an Asm code string as parameter Example (from MM6): local p = mem.asmhook2(0x43C8E3, [[ mov [edi], esi ]]) Original Asm code: .text:0043C8E3 mov edi, offset CurrentEvtLines .text:0043C8E8 rep movsd Resulting Asm code: .text:0043C8E3 jmp @p .text:0043C8E8 rep movsd @p: mov edi, offset CurrentEvtLines mov [edi], esi jmp 0x43C8E8 |
mem.asmpatch(p, code, size) | Replaces original instructions with new ones, jumping out if needed |
mem.asmproc(code) | Creates an Asm function |
mem.hookfunction(p, nreg, nstack, f, size) |
Set hook at the beginning of a function, allows calling the original function (see copycode note) Function f is as follows: f(d, def, params...) Here d is HookData object, def is the default function defined as def(params...) and params... are the parameters. |
mem.hookcall(p, nreg, nstack, f) | Replaces an existing CALL instruction and uses the same protocol as hookfunction |
mem.luaproc(f, nreg, nstack) | Creates a Lua callback (because any use of FFI for function calls leads to random bugs) |
mem.nop(p, n) | Writes n NOPs. If n is omitted, replaces a single instruction at the given address with NOPs |
mem.nop2(p, p2) | Writes NOPs from p to p2 - 1 |
Core\ RSPersist.luaФункции: |
|
persist(t, perm) | |
unpersist(buf, perm, data) |
Core\ events.luaПеременные: |
|
VFlipUnfixed | [MM6] Textures on horizontal outdoor surfaces are flipped vertically. This is default to preserve look of standard maps. |
RespectMonsterExp |
Set it to true to take experience from map monster structure rather than from monsters.txt based on monster Id. In MM8 only Armageddon uses monster XP from monsters.txt, other ways of killing monsters use experience value from monster structure. |
Функции: |
|
HookManager(ref) |
Allows switching all hooks installed by it on/off. ref table is used for substitutions in Asm code: "%key%" is replaced with ref[key], "%%" is replaced with "%". All hook functions are supported, but memory-editing arrays are supported through set function. Example 1 – substitution: local ArtifactBonus = mem.StaticAlloc(8) HookManager{ buf = ArtifactBonus, }.asmhook2(0x48F60A, [[ mov [%buf%], eax mov [%buf%+4], ecx ]]) Example 2 – on/off: local hooks function ArcomageRequireDeck(on) if hooks then hooks.Switch(not on) elseif not on then hooks = HookManager() hooks.nop(0x4B3A06) -- no arcomage deck requirement hooks.nop(0x4B8A31) -- no arcomage deck requirement end end Example 3 – editing memory: local hooks = HookManager() hooks.set('i4', 0x469BBE+1, 0x10000) -- instead of mem.prot(true); mem.i4[0x469BBE+1] = 0x10000; mem.prot(false) hooks.set('u2', 0x472FB7, 0x9090) -- instead of mem.prot(true); mem.u2[0x472FB7] = 0x9090; mem.prot(false) hooks.asmpatch(0x472F5E, "add eax, ecx", 2) DisableVFlipFix = |on| hooks.Switch(not on) P.S. Don't try to run the code of these examples, they are for illustration. |
CallDefaultWindowProc(Msg, WParam, LParam) | |
EnableLuaDataCompression(on) | |
FixVFlip() | [MM6] Turns off texture flip on horizontal outdoor surfaces. Note that the editor accounts for vertical flip, so you probably shouldn't ever call this function. |
EnableMonstersCastingAnimation(on) | [MM7+] Makes monsters play their regular attack animation rather then idle animation when casting damage spells if on is true. |
IsAttackOnPlayer() |
As first value returns true if the target of attack currently being handled is a player, false if it's a monster As second value returns attack information structure as returned by WhoHitMonster and WhoHitPlayer functions |
WhoHitMonster() |
If a monster is being attacked, returns t, TargetMonsterIndex. t.Player and either t.PlayerSlot[MM6-7] or t.PlayerIndex[MM8] are set if monster is attacked by the party. t.Monster, t.MonsterIndex and t.MonsterAction fields are set if monster is attacked by another monster. t.Object and t.ObjectIndex are set if monster is hit by a missile. t.Spell, t.SpellSkill and t.SpellMastery are set if a spell is being used. Note that t.Object can be set at the same time as t.Monster or t.Player. |
WhoHitPlayer() |
If a player is being attacked, returns t, PlayerSlot. t.Monster, t.MonsterIndex and t.MonsterAction fields are set if player is attacked by a monster. t.Object and t.ObjectIndex are set if player is hit by a missile. t.Spell, t.SpellSkill and t.SpellMastery are set if a spell is being used. Note that t.Object and t.Monster can be set at the same time if the projectile was fired by a monster. |
Core\ evt.luaПеременные: |
|
vars | Variables that are stored in saved game |
mapvars | Variables stored in a saved game that belong to current map. On map refill mapvars are cleared, but old table is stored in Map.Refilled. |
evt.CanShowTopic[] | [MM7+] Functions that can return true or false to change topic visibility |
evt.map[] |
Event handlers Event indexes convention: Indexes 20000 – 22999 are for sprite events, so that event (20000 + i) corresponds to Map.Sprites[i]. |
evt.hint[] | |
evt.MazeInfo | [MM6] |
evt.str[] | |
evt.house[] | House name used for hint |
evt.Player | |
evt.CurrentPlayer | |
Функции: |
|
evt.InGlobal() | |
evt.ForPlayer(n) | |
evt.HouseDoor(evtId, houseId) |
Here's what it does: evt.house[evtId] = houseId evt.map[evtId] = function() evt.EnterHouse(houseId) end |
Core\ evtdeco.luaФункции: |
|
evt.Decompile(fileName, funcMode, outFile, asTxt) |
Core\ main.luaПеременные: |
|
mem.EditPChar | Editable PChar |
mem.ConstPChar | Editable write-protected PChar |
Функции: |
|
mem.allocMM(size) | Calls allocation function that MM uses for most of things. Note that my patch intersects these calls and uses Delphi memory manager to do the allocation. |
mem.freeMM(p) | Free memory allocated by mem.allocMM. |
mem.reallocMM(p, OldSize, NewSize, NoFree) |
Resizes memory, reallocating as necessary, preserving content. Returns new (or the same if no reallocation occured) address. If NoFree is true, the memory at p isn't freed. This is useful for extending static arrays of the game. p can be a sctrucure, in which case its '?ptr' field is modified automatically. |
mem.resizeArrayMM(t, n) | Resizes an array allocated with mem.allocMM function. n is the new count. |
MessageBox(text, caption, typ) | typ can be a numeric value that MessageBox WinAPI function accepts or one of predefined strings: "error" (OK), "warning" (OK), "warn" (OK/Cancel), "confirm" (OK/Cancel), "confirmsnd" (OK/Cancel). Returns a number returned by the WinAPI funciton: 1 – OK, 2 – Cancel. |
debug.Message(...) | Shows debug console. Message includes file name and line number, and than each argument is added to the message as a new line of text. |
debug.ErrorMessage(msg) | |
ErrorMessage(msg) | |
AddScriptsPath(s) | |
ReloadLocalization() |
Core\ npc.luaФункции: |
|
FindHiredNPC(NPC) | Finds the prototype NPC in Game.NPC array for the supplied hired NPC. Returns nil if it's a street NPC. |
HireAllPeasants(on) |
[MM7] Normally first level of each peasant kind just talls you some news and can't be hired. Pass on = true to this function to make all peasants hireable. Pass on = nil to obtain current state of it. |
GetCurrentNPC() | Returns NPC index |
GetCurrentAnyNPC() | Returns NPC, Index, Kind |
ArcomageRequireDeck(on) |
[MM7] Pass false to remove the deck requirement. Pass on = nil to obtain current state of it. |
TrainPerWeek(n) | [MM7+] Set number of levels the party can train per training session. 0 means any number of levels, as in MM6. 1 is MM7+ default. If n isn't specified, returns current setting. |
SkillToHouseTopic(i) | |
HouseTopicToSkill(i) |
Core\ timers.luaExamples:Damage selected player every minute: Timer(function() evt.DamagePlayer{Damage = 1} end, const.Minute) Check some condition (e.g. that you killed all monsters) every 5 minutes, including the moment you enter the map: Timer(CheckCondition, 5*const.Minute, true) Refill a well each time a week passes: RefillTimer(RefillWell, const.Week) Refill a well every week on Tuesday at 3 AM: RefillTimer(RefillWell, const.Week, const.Day + 3*const.Hour) Make "eat" sound at 3 AM every day: Timer(function() evt.PlaySound(Game.Version == 8 and 144 or 211) end, const.Day, 3*const.Hour, false) Переменные: |
|
Keys[key] |
Example 1 (recommended): function Keys.F2(t) Message("F2 pressed") end Example 2 (not recommended): Keys[const.Keys.F2] = function() Message("F2 pressed") end These examples are actually handled differently. The first one is equivalent to using events.KeyDown and checking t.Key. The second is mostly for backward compatibility. Instead of relying on messages, it checks key state on every frame and calls the function if the key was pressed. It may miss a very short key press. |
Функции: |
|
timeGetTime() | Returns time since Windows has started in milliseconds |
Timer(f, Period = const.Minute, [Start,] [PastAware,] [Exact]) |
f = function(TriggerTime, Period, LastTick, Tick): Function to call when the timer is triggered. Start defaults to Game.Time + Period if not specified (unless PastAware = true, in which case it deafults to Game.Time). PastAware = remember last visit time and fire right away if timer condition was met in the period of your absence. Defaults to true if Start is specified and false otherwise. Possible Exact values: false: re-fires after at least Period passes since last invocation (this is the default if Start is not specified). true: fires whenever (Start + Period*N) line is crossed (this is the default if Start is specified). function(TriggerTime, Period, LastTick, IsInit): returns next trigger time when called. IsInit = true if it's called by Timer function itself which happens if Start has already passed. Note that the timer remembers last time you were in the location, so for example, an exact weekly timer would fire right away if you haven't visited the map for a week. |
RefillTimer(f, Period = const.Day, Start) |
f = function(TriggerTime, Period, LastTick, Tick): Called when the timer is triggered. If Start is not specified, triggers when Period passes since last time it was triggered and on map refill. If Start is specified, acts like exact Timer, but also fires at map refills. |
Sleep(time, realtime, screens, NoYield) | |
Sleep2(f, time, realtime, screens) | |
RemoveTimer(f) | You can remove the timer being executed by calling this function without a parameter |
Keys.IsPressed(key) | String representations of const.Keys are also supported, e.g. Keys.IsPressed"SHIFT" |
Keys.IsToggled(key) | String representations of const.Keys are also supported, e.g. Keys.IsToggled"CAPSLOCK" |
Modules\ Faces.luaTogether with PaperDoll.lua can be used to create new character portraits and voices, or add them from other games. Unlike PaperDoll.lua, everything here is 0-based. If included, creates and/or loads "Faces.txt" and "Face Animations.txt" data tables.Including the module: local P = require"Faces" You can add extra columns into "Faces.txt": AllowVoice – [MM7+] Enable/disable selecting voice on start (if not specified, the value of Allow is used). Voice – [MM7+] Use specified default voice instead of the one with the same number as the face. Expressions – Expressions list to use. Default is "Expressions". Use if you combine MM6 faces with faces from other games. Sounds – Sounds list to use. Default is "Sounds". Use if you combine MM6 voices with faces from other games. SoundsOffset – This value will be added to the sound id (the one being searched in dsounds.bin). You will need this if you add voices from all 3 games. Note that AllowVoice, Female, Sounds and sound counts are properties of voice, the rest are properties of face. If you leave any field empty, the default value would be used. You can add extra columns into "Face Animations.txt". If their names are valid identifiers, thay would be read as lists. E.g. imagine you've added MM6 characters into another game – then you can add "Expressions6" and "Sounds6" columns there and set Expressions and Sounds columns for these characters to "Expressions6" and "Sounds6" respectively. You would however also need to join PFT.txt files and replace indexes in expressions lists accordingly. The way animations work: random expression is picked from the list in "Expressions" column of "Face Animations.txt" (or "Expressions6" column in the above example). This number is looked up in PFT.txt and the animation is played. Expression 21 is special – it shows the character speaking the voice line as long as it lasts. When it comes to voice, sound index is picked at random from the "Sounds" column list (or "Sounds7" in the above example), then sounds count for the voice is looked up and one of the variations of the sound is played. Up to 2 variations are supported. Переменные: |
|
P.ExtraFields | You can define you own functions to read extra fields from Faces.txt |
P.Faces | |
P.FaceAnimations | |
Функции: |
|
P.Update() | Call it if you change Faces table manually. Triggers UpdateFaces event. |
Modules\ KeepLogs.luaФункции: |
|
ViewLog(n) |
Shows contents of console log from previous run of the game. n is the log index or 0 to show current output log. |
Modules\ PaperDoll.luaTo use, first place the PaperDol.txt file from here corresponding to your game of choice into DataFiles folder (create it right next to Data folder of the game if it doesn't exist). Modify it as needed. You'll later distribute this file inside a LOD achive of your mod.Including the module: require"PaperDoll" How it works: PaperDollDrawOrder defines the order in which pieces of body and clothing are drawn. PaperDollHiddenPieces event can be used to change which pieces would be drawn. PaperDol.txt can specify custom graphics and coordinates for any piece. Lines further in the table take precedence. If Doll includes current player, Piece matches piece being drawn and ItemPicture matches picture of the item being drawn (or ":Player" for a piece of player body), specified Image, X and Y values are used. A special case is when you specify item slot as ItemPicture, e.g. ":Armor". In this case X and Y act as offsets added to whatever coordinates are specified for the item in Armor slot. If you specify Mul for a slot, coordinates of the item are multiplied by it. It can also contain 4 values "a1,a2,a3,a4" that work this way: x = a1*X + a2*Y; y = a3*X + a4*Y. Setting Mul to "0,-1,1,0" or similar 90 degree rotation matrices would cause the item to be drawn rotated in MM8. Coordinates are given relative to the following point: MM6 and MM7 – (481, 0), MM8 – (467, 23). You can change it by modifying Game.DialogLogic.PaperDollPositionX and Game.DialogLogic.PaperDollPositionY, but changing it only affects paper doll position and not BACKDOLL or interface above paper doll. Options for ItemPicture values: item1 – Override "item1" graphics :Player – Override piece of the body :ExtraHand.item1 – Override "item1" graphics if equipped in the second hand :Player:if:Armor – Override piece of the body if any Armor is equipped :Player:if.item1 – Override piece of the body if "item1" is equipped :Player:if:Armor.item1 – Override piece of the body if "item1" is equipped as Armor :Belt:if:Armor.item1 – Override any belt if "item1" if equipped as Armor :Belt.item2:if:Armor – Override "item2" equipped as Belt if anything is equipped as Armor :Belt.item2:if.item1 – Override "item2" equipped as Belt if "item1" is equipped :Belt.item2:if:Armor.item1 – Override "item2" equipped as Belt if "item1" is equipped as Armor "insert" command: ItemPicture may start with ":insert" in order to insert a new piece to draw into PaperDollDrawOrder. It's an alternative to doing that in Lua code. TODO: I'll describe it some other day. Переменные: |
|
PaperDollCategories | Maps category name to a function(i) that returns true if player face number i belongs to the category. Use PaperDollAddBodies or PaperDollAddRace to populate in a custom way. |
PaperDollMainPieces |
Specifies which pieces inherit item graphics by default. For slots not specified here piece with empty name is the main one. Default: {ExtraHand = {hand2 = true, shield = true}, Gauntlets = {ring = true}, Amulet = {ring = true}, Ring1 = {ring = true}, Ring2 = {ring = true}, Ring3 = {ring = true}, Ring4 = {ring = true}, Ring5 = {ring = true}, Ring6 = {ring = true}} |
PaperDollBaseRace |
[MM7] Races that share the "Base" paper doll. Default: {[const.Race.Human] = true, [const.Race.Goblin] = true, [const.Race.Elf] = true} After altering it, call this command: PaperDollAddRace('Base', PaperDollBaseRace) |
PaperDollSpecialBodies |
After altering it, call PaperDollAddBodies. Here are default MM8 values: {[20] = 'Minotaur', [21] = 'Minotaur', [22] = 'Troll', [23] = 'Troll', [24] = 'Dragon', [25] = 'Dragon'} |
PaperDollTwoHandedSpear | If set to true (default in MM6 and MM7), spears are treated as two-handed weapons when used without a second weapon. Gets initialized according to game version. |
PaperDollDrawOrder |
List of things to draw in the form of "Slot.Piece.DrawStyle" (or "Slot.Piece", or "Slot"). Slot is either one of the wearable item slots (e.g. "Bow") or a pseudo-slot like "Player". Piece defines what element of that item gets drawn. DrawStyle can be set to "opaque" for opaque bitmaps ("red" and "green" are also supported) or "rect" to have the whole item rect count as item in regards to clicks. Default: {'BackDoll..opaque', 'BackDoll.menu.opaque', 'BackDoll.game.opaque', 'BeginDoll', 'Bow', 'Cloak', 'Armor.back', 'Belt.back', 'Player', 'Player.arm1', 'Player.arm1f', 'Player.arm2b', 'Player.arm2hb', 'Player.arm2fb', 'Player.shield', 'Player.hair', 'Armor.back2', 'Helm.back', 'Boots.back', 'Armor', 'Boots', 'Armor.front', 'Armor.arm1', 'Armor.arm1f', 'Belt', 'Player.arm2', 'Player.arm2h', 'Armor.arm2', 'Armor.arm2h', 'Player.arm2f', 'Cloak.scarf', 'Player.scarf', 'Helm', 'Cloak.scarf2', 'MainHand', 'Player.hand1a', 'Player.hand1', 'Player.hand1f', 'Armor.hand1a', 'Armor.hand1', 'Armor.hand1f', 'ExtraHand.hand2', 'ExtraHand.shield', 'Player.hand2', 'Player.hand2f', 'Player.hand2h', 'Armor.hand2', 'Armor.hand2f', 'Armor.hand2h', 'EndDoll', 'Magnify.noring', 'BackHand.ring', 'Border.good', 'Border.evil', 'Border.neutral', 'Ring1.ring.rect', 'Ring2.ring.rect', 'Ring3.ring.rect', 'Ring4.ring.rect', 'Ring5.ring.rect', 'Ring6.ring.rect', 'Amulet.ring.rect', 'Gauntlets.ring.rect', 'Magnify.ring', } See PaperDollHiddenPieces event for conditions under which each piece is visible. |
Функции: |
|
PaperDollAddRace(name, races) | |
PaperDollAddBodies(bodies) |
Defines doll categories for bodies array together with male and female variations of each. If bodies table isn't specified, uses PaperDollSpecialBodies table and defines the "Base" paper dolls as well. |
AddPaperDollGraphics(t) |
t can be a string following the "PaperDol.txt" convention or a table that's similar to the result of calling ParseNamedColTable for such file. Example – loading additional paper doll file for mods: events.ReloadPaperDollGraphics = || AddPaperDollGraphics(Game.LoadTextFileFromLod'PaperMod.txt') |
ReloadPaperDollGraphics() | Reloads "PaperDol.txt" and calls ReloadPaperDollGraphics event. Very handy while tweaking "PaperDol.txt" |
Structures
GameСвойства: |
|
Version | (6 – 8) |
Arcomage | [MM7+] |
Races | [MM7] |
Classes | |
ClassKinds | |
Party | |
Map | |
Mouse | |
Weather | |
Screen | |
PatchOptions | |
CustomLods | |
WindowHandle | |
Windowed | |
CurrentPlayer | |
SkillRecoveryTimes[skill] | |
MinMeleeRecoveryTime | |
CurrentScreen | :const.Screens |
CurrentCharScreen | :const.CharScreens |
MainMenuCode | -1 = in game, 0 = in main menu, 1 = show new game, 2 = show credits, 3 = show load menu, 4 = exit, 5 = loading game, 6 = in new game screen, 8 = in credits, 9 = load game, 10 = load level [MM7+] |
LoadingScreen | |
DialogNPC | |
NPCCommand | |
HouseScreen | |
HouseNPCSlot |
If Game.HouseOwnerPic isn't 0, the value of 1 refers to the shop keeper and higher value needs to be reduced by 1 before accessing . If Game.HouseExitMap isn't 0, last slot is occupied by map enter icon. |
HouseNPCSlotsCount | |
HouseCost | |
HouseAllowAction | |
HouseActionInfo | |
HouseTeachMastery | |
HousePicType | |
HouseOwnerPic | |
HouseExitMap | |
HouseNPCs[] | If Game.HouseExitMap isn't 0, last slot is occupied by map enter pseudo-NPC. |
HouseItemsCount | Number of interactive items of the dialog. Items count of the dialog object gets changed to this or 0 depending on selected player being concious. |
DialogsArray[] | |
DialogIndexes[] | |
Dialogs[] |
List of currently open dialogs, from lowest to topmost. Doesn't include object-oriented dialogs in MM8. Dialog at index 0 contains adventure interface that you see when no dialog is open. Even when you boot into the main menu, this dialog is present. |
CurrentNPCDialog | |
CurrentHouseDialog | |
InQuestionDialog | [MM8] |
OODialogs | [MM8] |
OODialogPtr | [MM8] Same as Game.OODialogs.CurrentDialogPtr |
GuildJoinCost[] | |
StatsNames[stat] | |
StatsDescriptions[stat] | |
SkillNames[skill] | |
SkillDescriptions[skill] | |
SkillDesNormal[skill] | |
SkillDesExpert[skill] | |
SkillDesMaster[skill] | |
SkillDesGM[skill] | [MM7+] |
ClassNames[class] | |
ClassDescriptions[class] | |
Actions[] | |
ActionsNext[] | [MM7+] |
ExitMapAction | :const.ExitMapAction |
FlashHistoryBook | [MM7] |
FlashAutonotesBook | [MM7] |
FlashQuestBook | [MM7] |
NeedRedraw | |
StatusMessage | |
StatusMessageBytes[] | |
MouseOverStatusMessage | |
MouseOverStatusMessageBytes[] | |
StatusDisappearTime | |
NeedUpdateStatusBar | [MM7+] |
FoodGoldVisible | [MM7] Set it to false to skip 1 draw call of drawing food and gold |
TextInputLimit | |
TextInput | |
TextInputBytes[] | |
TextInputLength | |
TextInputMode | |
TextInputDialog | |
EscMessageLastScreen | |
EscMessageDialog | |
NPCMessage | Current message displayed in a dialog with some NPC |
StreetMessage | Message displayed by Message, Question, evt.SimpleMessage and evt.Question when not talking to NPC. |
DelayedFaceAnimation.Delay | |
DelayedFaceAnimation.Animation | |
DelayedFaceAnimation.PlayerIndex | |
ItemsTxt[] | |
StdItemsTxt[] | |
SpcItemsTxt[] | |
ScrollTxt[] | |
PotionTxt[][] | |
PotNotesTxt[][] | [MM7+] |
MonstersTxt[] | |
PlaceMonTxt[] | [MM7+] |
MapStats[] | |
MapDoorSound[] | |
MapFogChances[] | |
FlyCeiling | [MM6, MM7] 3000 in MM6, 4000 in MM7+, in MM8 it's configured per map (Map.OutdoorExtra.Ceiling) |
MoveToMap | |
ProgressBar | |
DialogLogic | |
Lucida_fnt | |
FontLucida | |
Smallnum_fnt | |
FontSmallnum | |
Arrus_fnt | |
FontArrus | |
Create_fnt | |
FontCreate | |
Comic_fnt | |
FontComic | |
Book_fnt | |
FontBook | |
Book2_fnt | |
FontBook2 | |
Cchar_fnt | [MM6, MM7] |
FontCchar | [MM6, MM7] |
Autonote_fnt | |
FontAutonote | |
Spell_fnt | |
FontSpell | |
TextBuffer | |
TextBufferBytes[] | Lets you get address of TextBuffer or access it byte by byte (note: traversing it like that is very slow) |
TextBuffer2 | |
TextBuffer2Bytes[] | Lets you get address of TextBuffer2 or access it byte by byte (note: traversing it like that is very slow) |
WordWrappedText | |
WordWrappedTextBytes[] | Lets you get address of WordWrappedText or access it byte by byte (note: traversing it like that is very slow) |
KeyCodes[] | |
KeyTypes[] | |
Time | Since 00 AM, January 1st, 1165/1168/1172 |
Year | Actual value, like 1172 |
Month | (0 – 11) |
WeekOfMonth | (0 – 3) |
DayOfMonth | (0 – 27) |
Hour | (0 – 23) |
Minute | (0 – 59) |
Second | (0 – 59) |
BaseYear | |
MaxBirthYear | |
NeedRender | Same as Party.NeedRender |
TurnBased | |
TurnBasedPhase | 1 = monsters move, 2 = combat, 3 = party walking |
TurnBasedDelays[] | |
RedbookHandle | |
MSSHandle | |
BinkVideo | [MM7+] |
DialogTopicsLimit | [MM7+] |
SmackVideo | |
EquipStat2ItemSlot[] | |
MonsterClassSex[] | [MM7] MonClass = (Id + 2):div(3) |
MonsterClassRace[] | [MM7] MonClass = (Id + 2):div(3) |
MonsterSex[] | [MM6] |
MonsterClassInfoY[] | |
Paused | Game logic is paused |
Paused2 | Updates of 3D view are paused |
TimeDelta | Time since last tick |
TimeDelta2 | Time since last tick of updating 3D view |
PauseCount | See Game.Pause and Game.Resume |
PauseCount2 | See Game.Pause2 and Game.Resume2 |
FrameCounter | |
ShopItems[house][slot] | |
ShopSpecialItems[house][slot] | |
GuildItems[house][school][slot] | In MM8 in each guild items for all 12 schools of magic are generated. In MM6 and MM7 school can only be 0. |
GuildAwards[] | |
GuildItemIconPtr[slot] |
Loaded icons for current guild's items. Example: function events.GuildItemsGenerated(t) local a = Game.GuildItems[t.House][0] -- items array for this guild (for MM6 and MM7) a[0]:Randomize(5, const.ItemType.Book) -- put random powerful book into first slot a[0].Identified = true Game.GuildItemIconPtr[0] = Game.IconsLod:LoadBitmapPtr(a[0]:T().Picture) end |
ShopNextRefill[house] | |
GuildNextRefill[house] | |
ShopWeaponKinds[] | |
ShopWeaponKindsSpecial[] | |
ShopArmorKinds[][] | |
ShopArmorKindsSpecial[][] | |
ShopMagicLevels[] | |
ShopMagicLevelsSpecial[] | |
TrainingLevels[] | |
GuildSpellLevels[] | |
ShopAlchemistLevels[] | [MM7+] |
ShopAlchemistLevelsSpecial[] | [MM7+] |
ShopTheftExpireTime[] | [MM7+] |
GeneralStoreItemKinds[] | [MM6] |
GeneralStoreItemKindsSpecial[] | [MM6] Yes, MM6 generates special items in general stores, but doesn't support buying them. |
ShopBackgroundByType[] | |
ScanlineOffset[] | [MM6, MM7] |
ObjectByPixel[y][x] | |
ArmageddonTimeLeft | maximum is 417 |
ArmageddonSkill | damage is 50 + skill |
OutdoorViewMul | Acts as the opposite of FOV |
OutdoorViewDiv | = math.floor(0x10000/Game.OutdoorViewMul) |
GlobalTxt[] | |
Houses[] | 2DEvents.txt |
HouseMovies[] | |
TransTxt[] | |
SpecialEnterX[] | Used for Free Haven Sewer entrances in MM6. Negative Questbit Restrictions field in 2DEvents.txt corresponds to array index |
SpecialEnterY[] | |
SpecialEnterZ[] | |
SpecialEnterDirection[] | |
NPCTopic[] | |
NPCText[] | |
NPCGreet[][] | [MM7+] |
NPCGroup[] | [MM7+] |
NPCNews[] | |
HistoryTxt[] | [MM7+] |
NPCNewsCountByMap[] | [MM6] |
NPCDataTxt[] | |
NPC[] | |
NPCProfNames[] | |
NPCNames[][] | [MM6, MM7] |
NPCProfTxt[] | [MM6, MM7] |
NPCNamesCount[] | [MM6, MM7] |
StreetNPC[] | |
Spells[] | |
SpellsTxt[] | |
SpellSounds[] | |
SpellObjId[] | |
TitleTrack | |
TitleTrackOffset | |
NarratorTrack | [MM6] |
MissileSetup[] | |
SummonElementalA | [MM7+] |
SummonElementalB | [MM7+] |
SummonElementalC | [MM7+] |
QuestsTxt[] | |
AwardsTxt[] | |
AwardsSort[] | |
AutonoteTxt[] | |
AutonoteCategory[] |
[MM7+] 0 = potion 1 = stat 2 = obelisk 3 = seer 4 = misc 5 = teacher |
AutonotesByCategory[][] | [MM6] |
MerchantTxt[][] | |
CtrlPressed | |
RightButtonPressed | |
TownPortalInfo[] | |
TownPortalX[] | (Town portal picture: townport) |
TownPortalY[] | (Town portal icons [MM7+]: tpharmndy, tpelf, tpwarlock, tpisland, tpheaven, tphell) |
TownPortalHeight[] | [MM6, MM7] |
TownPortalWidth[] | [MM6, MM7] |
TransportLocations[] | |
TransportIndex[][] | |
HostileTxt[mon1][mon2] | [MM7+] 0 – 4. Attitude of mon1 towards mon2. mon2 = 0 is party. mon1 and mon2 are monster classes: mon1 = (Id1 + 2):div(3) |
NewGameMap | |
WinMapIndex |
Number represented as a string. [MM6] Index in games.lod [MM7+] Index in mapstats.txt |
GlobalEvtLines[] | |
MapEvtLines[] | |
SFTBin | |
DecListBin[] | |
PFTBin[] | |
IFTBin[] | |
TFTBin[] | |
ChestBin[] | |
OverlayBin[] | |
ObjListBin[] | |
MonListBin[] | |
SoundsBin[] | |
TileBin[] | |
Tile2Bin[] | [MM8] |
Tile3Bin[] | [MM8] |
CurrentTileBin | [MM8] |
ExitLevelCode | 0 = in game, 2 = load other map, 8 = death |
SoundVolume | |
PlayerFaces[] | |
StandardFaceAnimations[] | |
StandardPlayerSoundsCount[][] | |
GamesLod | |
IconsLod | |
BitmapsLod | |
SpritesLod | |
SaveGameLod | |
EnglishTLod | [MM8] |
EnglishDLod | [MM8] |
EventsLod | [MM7] |
dist_mist | |
IsD3D | |
RendererD3D | [MM7+] |
ModelClimbRequirement | [MM7+] Minimum required Z coordinate of the normal to climb a building surface. MM6 default is 1 (any non-vertical surface), MM7+ default is 46378, which corresponds to Lua[[46378/0x10000 = 0.7]]. |
RandSeed | |
IsMovieLooped | |
MovieKind | 0 – No movie, 1 – Smack, 2 – Bink |
MonsterKinds[] | [MM7+] |
Функции: |
|
ExitHouseScreen() | |
OODialogProcessKey() | [MM8] |
GetAdventureInnInfo() |
[MM8] Returns PlayerIndex, InInventory or nothing if Adventure Inn dialog isn't active. PlayerIndex is the index of currently selected player in Party.PlayersArray. Compare it against Party.PlayersIndexes[Party.CurrentPlayer] to see if selected player is part of the party. InInventory is true if player inventory (or Stats, Skills, Awards) screen is open. |
ProcessActions() | |
Rand() | |
DoPause() | Pauses game logic |
DoResume() | Resumes game logic |
Pause() | Pauses game logic, increments Game.PauseCount by 1 and updates Game.BackupPaused |
Resume() | Subtracts 1 from Game.PauseCount and resumes game logic upon reaching 0 if the the game wasn't paused before Game.Pause was called |
DoPause2() | Pauses updating 3D view (honored by the game only if logic is also paused) |
DoResume2() | Resumes updating 3D view |
Pause2() | Pauses updating 3D view, increments Game.PauseCount2 by 1 and updates Game.BackupPaused2 (honored by the game only if logic is also paused) |
Resume2() | Subtracts 1 from Game.PauseCount2 and resumes updating 3D view upon reaching 0 if the the game wasn't paused before Game.Pause2 was called |
SetInterfaceColor(Color, Unk = 1) | [MM7] 0 = good, 1 = neutral, 2 = evil |
DoShowMovie(Name, Y, DoubleSize, ExitCurrentScreen) | Only call from events.ShowMovie, use evt.ShowMovie otherwise. |
IsMoviePlaying() | [MM7+] |
LoadHouseMovie(Name, Loop = true) | |
EndMovie() | |
RestartHouseMovie() | |
PlayShopSound(House, SoundIndex) | |
GetNPCPtrFromIndex(Index) | [MM7+] |
GetCurrentNPCPtr() | |
CalcSpellDamage(Spell, Skill, Mastery, MonsterHP) | |
GetSpellDamageType(Spell) | |
GetStatisticEffect(Stat) | |
SummonMonster(Id, X, Y, Z) | |
SummonObjects(Type, X, Y, Z, Speed, Count = 1, RandomAngle = false, Bits = 0, pItem [MM7+]) | This function is called by evt.SummonObject internally. If you specify the pItem parameter, it will only work properly in MM8. |
GenerateChests() | You can add random items (Number = -1 to -6 for different power or -7 for artifact) to some chests and then call this function to generate them |
IsMonsterOfKind(Id, Kind) | [MM7+] |
FileRead(pTarget, Size, Count, FileStream) | Reads Size*Count bytes from FileStream into pTarget buffer. The FileStream can be obtained by calling FindFile method of a Lod archive. |
FileSeek(FileStream, Offset, Origin = 0) |
Sets current position of FileStream. Origin = 0 sets absolute position to Offset. Origin = 1 adds Offset to current position. Origin = 2 sets position to end of file plus Offset. |
FileTell(FileStream) | Returns current position of FileStream. |
Uncompress(pTarget, pTargetSize, pSrc, SrcSize) | pTargetSize must point to a 4-byte buffer specifying unpacked size. |
Compress(pTarget, pTargetSize, pSrc, SrcSize, Compression[MM7+] = -1) | pTargetSize must point to a 4-byte buffer specifying max size. The function sets it to actual size it has used up. If successful, returns 0. |
PlayMapTrack() | |
PlayTrack(Index) | |
LoadSound(SoundId, Unk = 0, Unk2 = 0) | Unk2 is present only in MM8 |
PlaySound(SoundId, Object = 0, Loops = 0, X = -1, Y = 0, Unk = 0, Volume = 0, PlaybackRate = 0) | Each object kind has a number of sound channels to use. Special Object values of '-1' and '-2' also have 1 channel reserved for each (lower values have the same effect as '-2'). So, when many sounds are played at once you could use one of these negative values instead of the default Object = 0. |
StopAllSounds(KeepMin = -1, KeepMax = -1) | |
LoadDecSprite(Name) | Loads a sprite and returns its ID. |
LoadBitmap(Name) | Loads a texture and returns its ID. |
UpdateDialogTopics() | |
NewDialog(Left, Top, Width, Height, DlgID, Param, StrParam, InitProc, InitParam) | If specified, InitProc(dlg, InitParam) is called before any calls to the NewDialog event. |
GetDialogFromPoint(Returns the dialog that the mouse is over.) | |
GetButtonFromPoint(Returns item, dialog that the mouse is over. Uses the logic of hint updates rather than clicks. That is, stops iteration upon finding an item in specified position or encountering a dialog with Height equal to 480, beyond which it wouldn't go. Note that the logic of clicks is generally less permissive: it's GetDialogFromPoint followed by GetFromPoint of said dialog.) | |
GetTopDialog(Returns the dialog that the mouse is over.) | |
ShowStatusText(Text, Seconds = 2, NoRedraw) | |
ShowStatusHint(Text, AcceptEmpty) | Unless AcceptEmpty is true, passing an empty string won't do anything. |
EscMessage(Text, ActionOnClose = 0) | |
StartTextInput(MaxLength = 50, Numerical = false, Dialog = nil) | |
EndTextInput(State) | |
LoadPalette(PalNum) | |
LoadDataFileFromLod(Name, UseMalloc) | |
LoadTextFileFromLod(Name) | |
CanLoadFileFromLod(Name) |
Returns true if specified file exists in LOD archives that LoadTextFileFromLod and LoadTextFileFromLod functions use. The archives are: icons.lod in MM6, events.lod in MM7, EnglishD.lod and EnglishT.lod in MM8. |
LoadPcx(Name, PcxBuffer, FromEnglishD = false, LoadKind = 0) | Returns loaded pcx. PcxBuffer can be nil, a pcx strucutre or a pointer to the buffer. If it's nil, the buffer gets allocated and must freed via a call to Destroy function. |
LoadFont() | |
GetCurrentHouse() | |
GetCurrentNoHouseNPC() | |
GetNPCFromPtr() | |
GetNPCFromIndex() |
PartyСвойства: |
|
Pos[] | |
X | |
Y | |
Z | |
Direction | 0 – 2047. 0 is East, 512 is North and so on. |
LookAngle | -512 – 512. Values allowed with mouse look: -240 – 300 (prior to patch 2.5: -200 – 200). Without mouse look: -128 – 128 |
LastX | |
LastY | |
LastZ | |
LastDirection | |
LastLookAngle | |
LastEyeLevel | |
SpeedX | |
SpeedY | |
SpeedZ | |
StableZ | Z changes up and down while flying, StableZ stays the same |
LastStandFacet | |
FallStartZ | |
Flying | |
PlayersArray[] | Array of all players |
PlayersIndexes[] | [MM8] Array of players indexes in PlayersArray corresponding to each player slot |
Players[] | (Default) Array of players corresponding to each player slot |
HiredNPC[] | [MM6, MM7] |
HiredNPCName[] | [MM6, MM7] |
LastRegenerationTime | |
SpellBuffs[buff] | |
Gold | |
BankGold | |
Food | |
Deaths | |
PrisonTerms | |
BountiesCollected | |
Fine | [MM7+] |
BountyHuntTarget[] | Only index 0 is normally used in MM8 |
MonsHuntTarget[] | (deprecated old name) |
BountyHuntKilled[] | Only index 0 is normally used in MM8 |
MonsHuntKilled[] | (deprecated old name, integer in MM7+ instead of boolean) |
NextBountyHunt[] | |
MonsHuntReset[] | (deprecated old name) |
QBits[] | |
AutonotesBits[] | |
InArenaQuest | |
ArenaWinsPage | |
ArenaWinsSquire | |
ArenaWinsKnight | |
ArenaWinsLord | |
ArtifactsFound[] | |
Alignment | [MM7] 0 = good, 1 = neutral, 2 = evil |
Reputation | |
History[] | [MM7+] |
SpecialDates[] |
[MM7+] E.g. set date 1: evt.Add("SpecialDate1", 0) Use date 1: "%51" in any NPC message |
ArcomageWins[] | [MM7+] |
CurrentPlayer | |
StateBits | |
NeedRender | |
Drowning | |
InAir | |
EnemyDetectorRed | |
EnemyDetectorYellow | |
FlyingBit | |
WaterWalkingBit | |
InJumpSpell | |
InLava | |
Функции: |
|
RestAndHeal() | |
Wait(Minutes) | |
FindActivePlayer() | |
GetFame() | |
GetReputation() | |
AddGold(Gold, Kind = 0) |
Kind values: 0 = increase by Banker, give some part to followers 1 = take exect amount, ignore followers 2 = [MM7+] take all and don't show message, just clear status message 3 = [MM7+] take all and don't change status message |
AddKillExp(Experience) | Experience is shared among conscious players and effected by Learning skill |
HasNPCProfession(arg1) | [MM6, MM7] |
CountItems({item1, item2, ...}) | |
GetCurrentPlayer() | |
Методы: |
|
ResetStartingPlayer(arg1 = false, arg2 = false) | [MM8] |
MapСвойства: |
|
Refilled | If the map has been refilled this visit, contains the last mapvars table. |
Name | |
IndoorOrOutdoor | |
Monsters[] | |
Vars[] | Variables for barrels/contests/etc events start at 75 |
Objects[] | Items, spells effects |
Sprites[] | |
SoundSprites[] | |
Chests[] | |
MapStatsIndex | |
NoNPC | [MM7] |
OutdoorHeader | |
Tilesets[] | |
HeightMap[y][x] | [(64 - Party.Y / 0x200):round()] [(64 + Party.X / 0x200):round()] = (Party.Z / 32):floor() |
TileMap[y][x] | [(64 - Party.Y / 0x200):floor()] [(64 + Party.X / 0x200):floor()] |
UnknownMap[][] | |
Models[] | |
IDList[] | IDs of sprites on map (in ObjectRef form) |
IDOffsets[y][x] | OMAP – offsets in IDList |
LoadedSkyBitmap | |
OutdoorSpawns[] | |
OutdoorRefillCount | |
OutdoorLastRefillDay | The day of refill plus 1 |
OutdoorReputation | [MM7+] |
OutdoorAlertState | [MM7+] |
OutdoorSanityFacetsCount | [MM7+] |
OutdoorSanitySpritesCount | [MM7+] |
SanityModelsCount | [MM7+] |
OutdoorExtra | |
OutdoorLastVisitTime | |
VisibleMap1[][] | |
VisibleMap2[][] | |
TilesetsFile | [MM8] 0 = dtile.bin, 1 = dtile2.bin, 2 = dtile3.bin |
UnknownMap2[][] | [MM8] |
Notes[] | [MM8] |
TerNormDist[][][] | [MM7+] |
TerNormId[][][] | [MM7+] |
TerNorm[] | [MM7+] |
IndoorHeader | |
Vertexes[] | |
Facets[] | |
FacetData[] | |
Rooms[] | |
Lights[] | |
Doors[] | |
BSPNodes[] | |
Outlines | |
IndoorSpawns[] | |
IndoorRefillCount | |
IndoorLastRefillDay | The day of refill plus 1 |
IndoorExtra | |
IndoorLastVisitTime | |
VisibileOutlines[] | |
IndoorReputation | [MM7+] |
IndoorAlertState | [MM7+] |
IndoorSanityFacetsCount | [MM7+] |
IndoorSanitySpritesCount | [MM7+] |
SanityDoorDataSize | [MM7+] Added in MMExtension. Instead of being checked against, it actually replaces Map.IndoorHeader.DoorDataSize when loading the .dlv, if it's non-zero. |
Spawns | |
RefillCount | |
LastRefillDay | The day of refill plus 1 |
Extra | |
LastVisitTime | |
Reputation | [MM7+] |
AlertState | [MM7+] |
SanityFacetsCount | [MM7+] |
SanitySpritesCount | [MM7+] |
SpriteLights[] | [MM7+] |
Функции: |
|
RemoveObject(Index) | |
Render() | |
IsIndoor() | |
IsOutdoor() | |
LoadTileset(Id) | |
RoomFromPoint(x, y, z) | |
GetFloorLevel(x, y, z, room) | Returns FloorZ, FacetId. |
GetGroundLevel(x, y) | |
GetFacet(Id) |
MouseСвойства: |
|
Target | Use Mouse.GetTarget instead. |
X | |
Y | |
Item | |
Функции: |
|
GetTarget() | Returns ObjectRef of current mouse target |
GetPos() |
Returns floating-point mouse position that includes sub-pixel difference caused by upscaling. In UILayout mode this is the only way to find mouse coordinates when it's over 3D view. Mouse.X and Mouse.Y would just return the middle of the view. When mouse is over interface items, both this function and Mouse.X, Mouse.Y get coordinates within traditional interface to which UI layout is mapped. |
Методы: |
|
SetIcon(Icon = "MICON1") |
There are 3 special values: "MICON1" = arrow cursor "MICON2" = crosshair cursor for spells "MICON3" = this cursor doesn't exist, don't use it Other values change the picture of item carried by mouse. |
RemoveItem() | Deletes item carried by the mouse and restores arrow cursor. |
AddItem(Item) | If there already was an item carried by the mouse, it will be taken into inventory or dropped. |
ReleaseItem() | If there is an item carried by the mouse, it will be taken into inventory or dropped. |
ScreenСвойства: |
|
IsD3D | [MM7+] |
Width | |
Height | |
Pitch | |
cx1 | |
cy1 | |
cx2 | |
cy2 | |
Buffer | |
ObjectByPixel | |
RedBits | |
BlueBits | |
GreenBits | |
RedMask | |
GreenMask | |
BlueMask | |
Pitch2 | [MM7+] |
ClipTop | [MM7+] |
ClipLeft | [MM7+] |
ClipBottom | [MM7+] |
ClipRight | [MM7+] |
Методы: |
|
SaveToPcx(name, x = 0, y = 0, width = 640, height = 480) | x, y, width, height can only be specified in MM6. MM7 and MM8 save a shot of whole screen area. |
SaveBufferToPcx(name, buf, width = 640, height = 480) | [MM7+] |
SetClipRect(left = 0, top = 0, right = 640, bottom = 480) | [MM7+] |
Draw(x, y, pic, style, rotate, EnglishD) |
style: "transparent", false – draw treating color index 0 as transparent (default) "opaque", true – draw without transparency "red" – draw broken item "green" – draw unidentified item Adding "p" in the beginning of style string signals that pic is a pointer to an image rather than its index. Note that "pred" and "pgreen" aren't supported in MM6. |
DrawItemEffect(x, y, shapePic, effectPic, palShift, palAnimateFrom, palAnimateTo, rotate, EnglishD, effectEnglishD) | |
DrawToObjectByPixel(x, y, pic, index, rotate, EnglishD) | |
DrawToObjectByPixelOpaque(x, y, pic, index, EnglishD) | [MM7+] |
DrawPcx(x, y, LoadedPcx) | |
DrawMessageBox(Dialog, Text = nil, SnapToViewBox = false) |
Draws a message box border with optional text inside. In place of Dialog you can pass a table in form of {Left, Top, Width, Height}. The function modifies the dialog position to make it fit on the screen. If you pass a table with box position and size, it's modified accordingly. If Text is specified or Dialog.StrParamPtr is not 0, the text is drawn in the middle of the dialog and dialog box is drawn with appropriate height, but dialog height is not modified to reflect that. |
DrawMessageBoxBorder(Left, Top, Width, Height) |
Draws a message box border. Minimal dimensions for proper display are 64. |
structs.ActionItemСвойства: |
|
Action | |
Param | |
Param2 |
structs.Arcomage[MM7+]Свойства: |
|
StartingTower | |
StartingWall | |
StartingIncome[3] | |
StartingIncomeBricks | |
StartingIncomeGems | |
StartingIncomeBeasts | |
CardsCount | Internally up to 10 cards are supported. |
MinIncome[3] | If you change these values, StartingIncome and player income would also change. |
TowerToWin | |
ResToWin | |
StartingRes[3] | |
StartingBricks | |
StartingGems | |
StartingBeasts | |
AI | 0 – 2 |
Players[2] | (Default) Player 0 is the human, player 1 is AI |
CardKinds[] | |
Deck[] |
structs.ArcomageAction[MM7+]Свойства: |
|
Income[] | |
Res[] | |
Damage | |
Wall | |
Tower |
structs.ArcomageActions[MM7+]Свойства: |
|
PlayAgain | |
DiscardCards | |
Me | |
Enemy | |
All |
structs.ArcomageCard[MM7+]Свойства: |
|
Name | |
Sprite | |
CostKind | |
CostIncome[] | |
CostRes[] | |
Discardable | |
If | :const.ArcomageIf |
Then | |
Else |
structs.ArcomagePlayer[MM7+]Свойства: |
|
Name | |
Human | |
Tower | |
Wall | |
Income[3] | |
Res[3] | |
Cards[10] | |
unk[10][2] |
structs.BSPNodeСвойства: |
|
FrontNode | |
BackNode | |
CoplanarOffset | |
CoplanarSize |
structs.BaseBonusСвойства: |
|
Base | |
Bonus |
structs.BaseLight[MM7+]Свойства: |
|
Pos[] | |
X | |
Y | |
Z | |
Radius | |
R | |
G | |
B | |
Type |
structs.BitmapsLodСвойства: |
|
File | |
FileName | |
Loaded | |
IOBuffer | |
IOBufferSize | |
LodHeaderSignature | |
Description | |
ArchivesCount | |
ArchivesCArray | |
Type | |
ChapterHandle | |
ChapterSize | |
Files[] | |
FilesOffset | |
Bitmaps[] | |
BitmapsCount | |
RedBits | |
GreenBits | |
BlueBits | |
NonTmpCount | |
TmpIndex | |
KeepCompressed | |
IsHardware | [MM7+] |
D3D_Surfaces[] | [MM7+] |
D3D_Textures[] | [MM7+] |
Методы: |
|
HasFile(name) | Does a slow search for a file. For sorted LOD archives FindFile works faster. |
FindFile(name, unsorted = false) |
Finds a file and returns file stream address or 0 if file isn't found. By default performs fast binary search. Pass unsorted = true when searching in Game.GamesLod and Game.SaveGameLod, because these archives aren't sorted lexicographically and thus binary search can't be used for them. Returned file stream can be used in Game.FileRead, Game.FileSeek and Game.FileTell functions. Its position is set to the beginning of specified file. |
LoadBitmap() | |
LoadBitmapPtr() | |
LoadTFTBitmap() | |
LoadBitmapInPlace(bmp, name, unused_must_be_2 = 2) | Used for loading of progress bar bitmaps |
ReplaceBitmap(bmp, name, unused_must_be_2 = 2) | [MM7+] Used for changing party faces and in MM7 for recoloring of interface. Assumes the new bitmap has the same dimensions. |
BeginTmp() | |
EndTmp() | |
Cleanup() |
structs.BlvHeaderСвойства: |
|
Name | |
FacetDataSize | |
RoomDataSize | |
RoomLightDataSize | |
DoorDataSize |
structs.ButtonСвойства: |
|
Left | |
Top | |
Width | |
Height | |
RightPixel | = Left + Width - 1 (it was called Right before MMExtension v2.3, old name is supported for backward compatibility) |
BottomPixel | = Top + Height - 1 (it was called Bottom before MMExtension v2.3, old name is supported for backward compatibility) |
Shape |
1 – Rectangle. 2 – Ellipse. Left and Top are center coordinates, Width and Height are radii. In MM6 it's always a circle and Height is 0. 3 – Skill rectangle. |
HintAction | |
Action | Was called ActionType before MMExtension v2.3, old name is supported for backward compatibility |
ActionParam | |
ActionParam2 | [MM7+] |
Pressed | |
PrevItemPtr | |
NextItemPtr | |
Parent | |
ParentPtr | |
Sprites[] | A list of pointers to associated icons |
Key | Was called ShortCut before MMExtension v2.3, old name is supported for backward compatibility |
Hint | |
Методы: |
|
Destroy() | Make sure to update Parent.KeyboardItemsCount on your own if you delete one of them |
MoveBefore(Target) |
If Target is 0 or nil, moves the item to the end of the items list Note that first item in the list is topmost and the last one is at the bottom. |
MoveAfter(Target) | If Target is 0 or nil, moves the item to the beginning of the items list |
structs.CurrentTileBin[MM8]Свойства: |
|
Items[] | (Default) |
structs.CustomLodsСвойства: |
|
RecordIndex | |
Records[] | |
Функции: |
|
Load(StdLod, Name) | |
Free(Ptr) |
structs.DChestItemСвойства: |
|
Name | |
Width | |
Height | |
ImageIndex |
structs.DialogLogicСвойства: |
|
List[] | List of indexes to be displayed |
ScrollPage | |
CountOnScreen | |
ListCount | |
ScrollPos | |
AutonoteTab6Clicked | [MM7+] |
AutonoteTab5Clicked | |
MapMoveRightClicked | |
AutonoteTab4Clicked | |
MapMoveLeftClicked | |
AutonoteTab3Clicked | |
MapMoveDownClicked | |
AutonoteTab2Clicked | |
MapMoveUpClicked | |
AutonoteTab1Clicked | |
ScrollDownClicked | |
ScrollUpClicked | |
SpellBookSelection | Selected spell index within current page (1..11) |
SpellBookSelectedNewSpell | [MM7+] |
AutonotesCategory | |
ArmorSkills[] | [MM7+] |
WeaponSkills[] | [MM7+] |
MiscSkills[] | [MM7+] |
MagicSkills[] | [MM7+] |
MonsterInfoMonster | |
PlayerRingsOpen | |
PaperDollPositionX | |
PaperDollPositionY |
structs.DlgСвойства: |
|
Left | |
Top | |
Width | |
Height | |
RightPixel | = Left + Width - 1 (it was called Right_ before MMExtension v2.3, old name is supported for backward compatibility) |
BottomPixel | = Top + Height - 1 (it was called Bottom_ before MMExtension v2.3, old name is supported for backward compatibility) |
DlgID | |
Param | 2D Events Id / Chest Id / ... |
ItemsCount | |
KeyboardItemsCount | |
KeyboardItem | |
KeyboardNavigationTrackMouse | |
KeyboardLeftRightStep | |
KeyboardItemsStart | |
Index | Current index in Game.Dialogs array. |
TextInputState | |
UseKeyboadNavigation | |
StrParam | |
StrParamPtr | |
FirstItemPtr | |
LastItemPtr | |
Методы: |
|
SetKeyboardNavigation(KeyboardItemsCount, KeyboardNavigationTrackMouse, KeyboardLeftRightStep, KeyboardItemsStart) | |
GetItemPtrByIndex(Index) | |
AddButton(Left, Top, Width, Height, Shape = 1, HintAction, ActionType, ActionParam, Key, Hint = "", [EnglishD] = true, Sprites...) |
Can also accept a table where some parameters are supplied by their name. In this case EnglishD and Sprites must be supplied by name. Returns button address and the wrap function. Pass the returned address to the wrap function to create a dialog item structure to access it. Example: -- make area to the left of first player portrait bring up the Maps dialog (note: this would interfere with object-oriented dialogs in MM8 and cause bugs when clicked inside them) local p, wrap = Game.Dialogs[0]:AddButton{0, 384, 31, 80, ActionType = 202, Hint = "Another Maps Button", Sprites = {"ib-td3-A"}} local btn = wrap(p) btn:MoveAfter(0) -- make it take priority over other buttons |
Destroy(KeepMonsterPicture [MM8]) | |
Enum(Backwards) |
To be used in a for statement. Enumerates dialog items returning item index, dialog item and the wrap function each time. If Backwards is true, enumeration goes in reverse order. Note that the same Lua table gets reused for the item structure during enumeration. If you want to create separate Lua tables for each item, use the Wrap function. Here's an example: local t = {} -- this table will be populated with all dialog items from adventure screen for i, it, wrap in Game.Dialogs[0]:Enum() do t[i] = wrap(it) end If you're wandering, the wrap function itself simply does the following: structs.Button:new(it['?ptr'] or tonumber(it)) |
GetByIndex(Index) | Returns dialog item at specified index in the items list. |
GetRelativePoint(X, Y) | Returns relative coordinates or nothing if the coordinates don't fall within the dialog. |
GetFromPoint(X, Y, Absolute) | Returns dialog item at specified relative or absolute coordinates. |
structs.FaceAnimationInfoСвойства: |
|
Sounds[] | |
Sound1 | |
Sound2 | |
Expressions[] | |
Expression1 | |
Expression2 | |
Expression3 | |
Expression4 | |
Expression5 |
structs.FacetDataСвойства: |
|
FacetIndex | |
BitmapIndex | |
TFTIndex | |
BitmapU | Bitmap U Offset |
BitmapV | Bitmap V Offset |
Id | |
Event |
structs.FloatVector[MM7+]Свойства: |
|
1 | same as X |
X | |
2 | same as Y |
Y | |
3 | same as Z |
Z |
structs.FntСвойства: |
|
MinChar | |
MaxChar | |
Height | |
PalettesCount | |
Palettes[] | |
ABC[][] | |
GlyphOffsets[] | |
GlyphData[] | |
Методы: |
|
GetLineWidth(Text) | |
GetTextHeight(Text, Dialog = nil, X = 0, IgnoreStrRightSymbol = false [MM7+]) |
In place of Dialog you can pass a table in form of {Left, Top, Width, Height}. Calls WordWrap internally and stores the result in Game.WordWrappedText. |
WordWrap(Text, Dialog = nil, X = 0, IgnoreStrRightSymbol = false [MM7+], ReturnPointer = false) |
Returns text with extra line breaks inserted. In place of Dialog you can pass a table in form of {Left, Top, Width, Height}. If ReturnPointer = true, returns Game.WordWrappedTextBytes table instead of Lua string. You can then pass this table to any of the font methods. |
Draw(Text, Dialog = nil, X = 0, Y = 0, Color = 0, ShadowColor [MM7+], Bottom [MM7+], Opaque [MM7+]) |
In place of Dialog you can pass a table in form of {Left, Top, Width, Height}. If X is 0, in MM6 and MM7 it gets set to 12 by the function. Passing 0 as Color would draw text using default color. Unless Bottom is specified, it calls WordWrap internally and stores the result in Game.WordWrappedText. Bottom is specified in absolute coordinates, not relative to dialog. When specified, the text doesn't get word-wrapped, but doesn't get drawn below its value. If not specified, text gets ward-wrapped when it exceeds dialog width horizontally, but is not limited vertically. |
DrawLimited(Text, Dialog = nil, Width, X = 0, Y = 0, Color = 0, TruncateStart = false) |
In place of Dialog you can pass a table in form of {Left, Top, Width, Height}. X should not be 0 in MM6 and MM7, because it then gets set to 12 by the function if text fits and is kept at '0 if it doesn't. Passing 0 as Color would draw text using default color. If TruncateStart is true, end of the string is kept and beginning is truncated to fit the required size. Calls WordWrap internally and stores the result in Game.WordWrappedText. |
DrawCentered(Text, Dialog = nil, X = 0, Y = 0, Color = 0, ReduceLineHeight = 3) |
In place of Dialog you can pass a table in form of {Left, Top, Width, Height}. Passing 0 as Color would draw text using default color. Calls WordWrap internally and stores the result in Game.WordWrappedText. |
structs.FogChancesСвойства: |
|
Thick | |
Medium | |
Light |
structs.GameClassKindsСвойства: |
|
HPBase[] | [MM6, MM7] |
SPBase[] | [MM6, MM7] |
StartingStats[][stat] | [MM6] |
StartingSkills[][skill] |
[MM6] 0 = not available, 1 = given on start, 2 = can choose on start, 3 = can learn [MM7+] 0 = can't choose, 1 = can choose on start, 2 = given on start |
structs.GameClassesСвойства: |
|
HPFactor[class] | |
SPFactor[class] | |
HPBase[class] | [MM8] |
SPBase[class] | [MM8] |
Skills[class][skill] | [MM7+] 0 = not available, 1 = Basic, 2 = Expert, 3 = Master, 4 = GM |
StartingStats[class] | [MM8] |
SPStats[class] | 0 = no SP, 1 = Intellect, 2 = Personality, 3 = both |
structs.GameRaces[MM7]Свойства: |
|
StartingStats[race][stat] |
structs.GeneralStoreItemKind[MM6]Свойства: |
|
Level | |
Items[1..6] | (Default) If it's zero, random Boots or Gauntlets are generated. |
structs.HistoryTxtItem[MM7+]Свойства: |
|
Text | |
Title | |
Time |
structs.HouseMovieСвойства: |
|
FileName | |
Background | EVTPAR* index, used only in MM6 |
NPCPic | |
HouseType | |
Sounds | 30000 + Sounds*100 is the Id in Sounds.txt |
structs.ItemСвойства: |
|
Number | |
Bonus | From STDITEMS.TXT. You can use const.Stats, just add 1 to a supported value from it. |
BonusStrength | |
Bonus2 | From SPCITEMS.TXT. Value in case of gold. |
Charges | |
Identified | |
Broken | |
TemporaryBonus | |
Stolen | |
Hardened | |
Refundable | Added in patch v2.5.4. Used internally to remove artifacts generated in unopened chests from ArtifactsFound upon map refill. |
Condition | |
BodyLocation | |
MaxCharges | |
Owner | |
BonusExpireTime | [MM7+] |
Методы: |
|
GetValue() | |
GetName() | |
GetIdentifiedName() | |
GenerateArtifact() | |
Clear() | |
Randomize(Strength, Type, AlwaysEnchant [MM8]) | Generates a random item. The chance that it would be enchanted depends on Strength. In MM8 you can guarantee its enchantment by passing true as AlwaysEnchant parameter. |
T() | Returns ItemsTxt entry. |
InitSpecial() | [MM7+] Sets up enchantments if the item is "Special" as marked by "material" column of items.txt |
structs.ItemsTxtItemСвойства: |
|
Picture | |
Name | |
NotIdentifiedName | |
Notes | |
Value | |
EquipStat | Subtract 1 from const.ItemType value |
Skill | |
Mod1DiceCount | |
Mod1DiceSides | |
Mod2 | |
Material | 0 = normal, 1 = artifact, 2 = relic, 3 = special |
ChanceByLevel[] | |
IdRepSt | |
SpriteIndex | |
EquipX | |
EquipY | |
Bonus2 | [MM7+] VarA |
Bonus | [MM7+] VarA |
BonusStrength | [MM7+] VarB |
structs.LanguageLod[MM8]Свойства: |
|
File | |
FileName | |
Loaded | |
IOBuffer | |
IOBufferSize | |
LodHeaderSignature | |
Description | |
ArchivesCount | |
ArchivesCArray | |
Type | |
ChapterHandle | |
ChapterSize | |
Files[] | |
FilesOffset | |
Методы: |
|
FindFile(name, unsorted = false) |
Finds a file and returns file stream address or 0 if file isn't found. Performs fast binary search (unless unsorted is set to true, which you shouldn't do for language LODs). Returned file stream can be used in Game.FileRead, Game.FileSeek and Game.FileTell functions. Its position is set to the beginning of specified file. |
structs.LanguageLodFile[MM8]Свойства: |
|
Name | |
Offset | |
Size |
structs.LloydBeaconSlotСвойства: |
|
ExpireTime | |
Pos[] | |
X | |
Y | |
Z | |
Direction | |
LookAngle | |
Active | |
MapIndex | |
Map |
structs.LodСвойства: |
|
File | |
FileName | |
Loaded | |
IOBuffer | |
IOBufferSize | |
LodHeaderSignature | |
Description | |
ArchivesCount | |
ArchivesCArray | |
Type | |
ChapterHandle | |
ChapterSize | |
Files[] | |
FilesOffset | |
Методы: |
|
HasFile(name) | Does a slow search for a file. For sorted LOD archives FindFile works faster. |
FindFile(name, unsorted = false) |
Finds a file and returns file stream address or 0 if file isn't found. By default performs fast binary search. Pass unsorted = true when searching in Game.GamesLod and Game.SaveGameLod, because these archives aren't sorted lexicographically and thus binary search can't be used for them. Returned file stream can be used in Game.FileRead, Game.FileSeek and Game.FileTell functions. Its position is set to the beginning of specified file. |
structs.LodFileСвойства: |
|
Name | |
Offset | |
Size |
structs.LodPcxСвойства: |
|
BufSize | |
Width | |
Height | |
WidthLn2 | |
HeightLn2 | |
WidthMinus1 | |
HeightMinus1 | |
Bits | |
Image | |
Методы: |
|
Destroy(FreeBuffer = true) |
structs.LodRecordСвойства: |
|
LodPtr | |
NamePtr | Pointer passed to Load* function |
Name |
structs.LodSpriteСвойства: |
|
Name | |
DataSize | |
Width | |
Height | |
Palette | |
YSkip | |
UnpackedSize | |
Lines[] | |
Buffer |
structs.LodSpriteD3DСвойства: |
|
Name | |
Palette | |
Surface | |
Texture | |
AreaX | |
AreaY | |
BufferWidth | |
BufferHeight | |
AreaWidth | |
AreaHeight |
structs.LodSpriteLineСвойства: |
|
L | |
R | |
Pos[] |
structs.MapChestСвойства: |
|
ChestPicture | 0..7 chest id |
Trapped | |
ItemsPlaced | |
Identified | |
Bits | |
Items[] | |
Inventory[] | (Items index) for main item cell, -(1 + main Inventory cell index) for other cells |
Методы: |
|
RefundArtifacts() |
structs.MapFacetСвойства: |
|
NormalF[] | [MM7+] normal float |
NormalFX | [MM7+] normal X float |
NormalFY | [MM7+] normal Y float |
NormalFZ | [MM7+] normal Z float |
NormalFDistance | [MM7+] normal distance float |
Normal[] | normal fixed pt (0..0x10000) |
NormalX | normal X fixed pt (0..0x10000) |
NormalY | normal Y fixed pt (0..0x10000) |
NormalZ | normal Z fixed pt (0..0x10000) |
NormalDistance | normal distance fixed pt (0..0x10000) |
ZCalc1 | = -(NormalX * 2^16) / NormalZ (or 0 if NormalZ is 0) |
ZCalc2 | = -(NormalY * 2^16) / NormalZ (or 0 if NormalZ is 0) |
ZCalc3 | = -(NormalDistance * 2^16) / NormalZ (or 0 if NormalZ is 0) |
IsPortal | |
IsSecret | [MM7+] show in red with Perception |
ScrollDown | [MM7+] moving texture |
AlignTop | [MM7+] align door texture in D3D |
IsWater | |
ScrollUp | [MM7+] moving texture |
ScrollLeft | [MM7+] moving texture |
ProjectToXY | |
ProjectToXZ | |
ProjectToYZ | |
ScrollRight | [MM7+] moving texture |
AlignLeft | [MM7+] align door texture in D3D |
Invisible | |
AnimatedTFT | |
AlignRight | [MM7+] align door texture in D3D |
AlignBottom | [MM7+] align door texture in D3D |
MoveByDoor | |
IsEventJustHint | [MM7+] |
AlternativeSound | |
IsSky | outdoor in software mode: horizontal flow |
FlipU | |
FlipV | |
TriggerByClick | |
TriggerByStep | |
DisableEventByCtrlClick | [MM8] indoor only: click event gets disabled by Ctrl+Click |
EventDisabledByCtrlClick | [MM8] |
TriggerByMonster | [MM6, MM7] happens even if there's no event assigned |
TriggerByObject | [MM6, MM7] happens even if there's no event assigned |
Untouchable | great for vertical facets of stairs. [MM7+] Shouldn't be used for sloped floor, like it's used in MM6. |
IsLava | |
HasData | |
Bits | |
VertexIds[] | |
XInterceptDisplacement[] | |
YInterceptDisplacement[] | |
ZInterceptDisplacement[] | |
UList[] | |
VList[] | |
DataIndex | |
BitmapId | Bitmap Index |
Room | Room # |
RoomBehind | Room # Behind facet |
MinX | Bounding Box Min X |
MaxX | Bounding Box Max X |
MinY | Bounding Box Min Y |
MaxY | Bounding Box Max Y |
MinZ | Bounding Box Min Z |
MaxZ | Bounding Box Max Z |
PolygonType |
Polygon type: 0 = empty 1 = wall 2 = unused 3 = horizontal floor 4 = irregular floor (non-horizontal) 5 = horizontal ceiling 6 = irregular ceiling (non-horizontal) |
VertexesCount | |
Методы: |
|
GetData(Create) |
Returns Map.FacetData structure associated with the facet. If Create is true, the data gets automatically allocated if it doesn't exist. On outdoor maps the method returns the facet itself, because all data is inside its own structure. |
structs.MapLightСвойства: |
|
Pos[] | |
X | |
Y | |
Z | |
Off | |
Bits | |
Brightness | |
Radius | |
R | [MM7+] |
G | [MM7+] |
B | [MM7+] |
Type | [MM7+] |
Id | [MM8] |
structs.MapModelСвойства: |
|
Name | |
Name2 | |
ShowOnMap | |
Bits | |
Vertexes[] | |
ConvexFacetsCount | |
Facets[] | |
Ordering[] | |
BSPNodes[] | |
GridX | center X |
GridY | center Y |
Pos[] | |
X | |
Y | |
Z | |
MinX | Bounding MIN X |
MinY | Bounding MIN Y |
MinZ | Bounding MIN Z |
MaxX | Bounding MAX X |
MaxY | Bounding MAX Y |
MaxZ | Bounding MAX Z |
BFMinX | |
BFMinY | |
BFMinZ | |
BFMaxX | |
BFMaxY | |
BFMaxZ | |
BoxCenterX | Bounding center X |
BoxCenterY | Bounding center Y |
BoxCenterZ | Bounding center Z |
BoundingRadius |
structs.MapMonsterСвойства: |
|
Name | [MM6] |
NPC_ID |
[MM6] Index in Game.StreetNPC + 1 [MM7+] Index in Game.NPC or index in Game.StreetNPC + 5000 |
Active | inside the active radius |
ShowOnMap | monster was once seen by party |
Invisible | |
NoFlee | |
Hostile | |
OnAlertMap | |
TreasureGenerated | treasure is in Items[0] and Items[1], gold is in Items[3] |
ShowAsHostile | show as hostile on map |
IsObeliskChest | [MM8] |
Bits | |
HP | |
HitPoints | |
Id | Changing may cause random crashes after loading the game! Be careful. |
Level | |
TreasureItemPercent | |
TreasureDiceCount | |
TreasureDiceSides | |
TreasureItemLevel | |
TreasureItemType | |
Fly | |
MoveType | |
AIType | |
HostileType | |
Prefers.Necro | [MM8] |
Prefers.Knight | |
Prefers.Paladin | [MM6, MM7] |
Prefers.Archer | [MM6, MM7] |
Prefers.Druid | [MM6, MM7] |
Prefers.Cleric | |
Prefers.Troll | [MM8] |
Prefers.Minotaur | [MM8] |
Prefers.DarkElf | [MM8] |
Prefers.Vampire | [MM8] |
Prefers.Dragon | [MM8] |
Prefers.Sorcerer | [MM6, MM7] |
Prefers.Ranger | [MM7] |
Prefers.Thief | [MM7] |
Prefers.Monk | [MM7] |
Prefers.Male | in monsters.txt it's "M" in MM6 and "X" in MM7 and MM8 |
Prefers.Female | |
Prefers.Human | [MM7] |
Prefers.Elf | [MM7] |
Prefers.Dwarf | [MM7] |
Prefers.Goblin | [MM7] |
PrefClass | Preferred target |
Bonus | (steal, curse, ...) |
BonusMul | Disease1x5 etc. The chance that a monster would use the bonus is Level*BonusMul |
Attack1 | |
Attack2Chance | |
Attack2 | |
SpellChance | |
Spell | |
Spell2Chance | [MM7+] |
Spell2 | [MM7+] |
SpellSkill | |
Resistances[kind] | For immunity use const.MonsterImmune |
FireResistance | |
AirResistance | [MM7+] |
WaterResistance | [MM7+] |
EarthResistance | [MM7+] |
MindResistance | [MM7+] |
SpiritResistance | [MM7+] |
BodyResistance | [MM7+] |
LightResistance | [MM7+] |
DarkResistance | [MM7+] |
ElecResistance | [MM6] |
ColdResistance | [MM6] |
PoisonResistance | [MM6] |
PhysResistance | |
Special | [MM7+] 1 = shot, 2 = summon, 3 = explode |
SpecialA |
[MM7+] shot: C = count summon: A = {RandomLevel = 0, fixed = 1} – monster level (0 means A, B or C is chosen randomly, monster index should be that of A variation. Values of 2 and 3 are the same as 1, but in MM7 before GrayFace Patch v2.1 it was causing a bug), B = {ground = 0, air = 1}, C = already summoned count (up to 3), D = monster index explode: AdB + C, D = attack type |
SpecialB | [MM7+] |
SpecialC | [MM7+] |
MagicResistance | [MM6] |
PrefNum | Number of party members to hit using Attack1 & Attack2 |
BloodSplat | [MM7+] |
Spell2Skill | [MM7+] |
SpecialD | [MM7+] (summoned monster or damage type in case of explosive attack) |
QuestItem | [MM6] |
FullHP | |
FullHitPoints | |
ArmorClass | |
Exp | |
Experience | |
MoveSpeed | |
AttackRecovery | |
RangeAttack | |
Id2 | |
BodyRadius | |
BodyHeight | |
Velocity | |
Pos[] | |
X | |
Y | |
Z | |
VelocityX | |
VelocityY | |
VelocityZ | |
Direction | |
LookAngle | |
Room | |
CurrentActionLength | |
StartX | |
StartY | |
StartZ | |
GuardX | |
GuardY | |
GuardZ | |
GuardRadius | |
AIState | |
GraphicState | |
Item | |
CurrentActionStep | |
Frames[] | |
FramesStand | |
FramesWalk | |
FramesAttack | |
FramesShoot | |
FramesStun | |
FramesGotHit | |
FramesDie | |
FramesDead | |
FramesFidget | |
Sounds[] | |
SoundAttack | |
SoundDie | |
SoundGetHit | |
SoundGotHit | |
SoundFidget | |
SpellBuffs[buff] | |
Items[] | [MM7+] Indexes 0 and 1 are used for stolen items, indexes 2 and 3 are used if TreasureGenerated bit is set: index 2 holds the item and index 3 holds the gold. |
Group | |
Ally | Monster class that guards or is guraded by this one. That is, (Id + 2):div(3), like in Hostile.txt. |
Schedules[] | |
Summoner | |
LastAttacker | Last one who hit the monster |
NameId | [MM7+] From PlaceMon.txt |
Методы: |
|
IsAgainst(Mon2) | [MM7+] Returns aggression number between 0 and 4. If Mon2 isn't specified, attitude towards party is checked. |
LoadFrames(SoundLoaded = false) | If SoundLoaded = false, sound indexes would be loaded for the monster as well. |
ChooseTargetPlayer() | Returns player slot index |
CalcTakenDamage(DamageKind, Damage) | Returns the amount of damage the monster has to actually receive |
CalcHitByEffect(DamageKind) | Returns true if the monster couldn't dodge the effect |
CalcHitOrMiss(Player) | |
UpdateGraphicState() | Updates GraphicState in accordance with AIState |
ShowSpellEffect(Color24 = 0) | [MM7+] Shows effect from a spell (as a cylinder of colored dots around the monster) |
GotHit(By = 4, ResetAnimation = false) | Shows monster's getting hit animation, produces sound and boosts aggression level. By is the attacker object reference value. |
PlaySound(SoundIndex) | [MM7+] SoundIndex is from 0 to 3 or any of these corresponding strings: "Attack", "Die", "GotHit", "Fidget" |
LoadFramesAndSounds() | |
ChangeLook(id) | Takes on the look of another monster kind |
GetPropertiesFromId(id) | Takes all properties, except appearance and sounds from another monster kind |
SetId(id) | Changes Id and, if it's not 0, Id2 |
SetCustomFrames(Stand, Walk, Attack, Shoot, Stun, GotHit, Die, Dead, Fidget) | Any argument can be nil. Also loads the frames. |
GetIndex() |
structs.MapNote[MM8]Свойства: |
|
Active | |
X | |
Y | |
Text | |
Id |
structs.MapObjectСвойства: |
|
Type | look type (see Id in dobjlist.bin) |
TypeIndex | line in dobjlist.bin |
Pos[] | |
X | |
Y | |
Z | |
Velocity[] | |
VelocityX | |
VelocityY | |
VelocityZ | |
Direction | |
LookAngle | |
Visible | |
Temporary | |
HaltTurnBased | |
DroppedByPlayer | |
IgnoreRange | |
NoZBuffer | |
SkipAFrame | |
AttachToHead | |
Missile | |
Removed | |
Bits | |
Room | |
Age | |
MaxAge | |
LightMultiplier | |
Item | |
SpellType | |
Spell | same as SpellType |
SpellSkill | |
SpellLevel | |
SpellMastery | same as SpellLevel |
SpellEffect | [MM7+] |
Owner | |
Target | |
Range | Distance to target: 0 – less than 307.2, 1 – less than 1024, 2 – less then 2560, 3 – 2560 or more |
AttackType | 0 – Attack1, 1 – Attack2, 2 – Spell, 3 – Spell2, 4 – Explode |
StartPos[] | |
StartX | starting x |
StartY | starting y |
StartZ | starting z |
structs.MapOutlineСвойства: |
|
Vertex1 | |
Vertex2 | |
Facet1 | |
Facet2 | |
Z | |
Visible | |
Bits |
structs.MapOutlinesСвойства: |
|
Items[] | (Default) |
structs.MapSpriteСвойства: |
|
DecListId | |
DecName | |
TriggerByTouch | only for "Event Trigger" sprites – triggered when a player comes into TriggerRadius |
TriggerByMonster | only for "Event Trigger" sprites – triggered when a monster comes into TriggerRadius |
TriggerByObject | only for "Event Trigger" sprites – triggered when an object gets into TriggerRadius |
ShowOnMap | |
IsChest | |
Invisible | |
IsObeliskChest | [MM7+] |
IsShip | [MM6] |
Bits | |
Pos[] | |
X | |
Y | |
Z | |
Direction | |
Id | [MM7+] |
EventVariable | event variable for barrels etc. |
Event | normal event |
TriggerRadius | |
DirectionDegrees | only used if Direction is 0 |
structs.MapVertexСвойства: |
|
1 | same as X |
X | |
2 | same as Y |
Y | |
3 | same as Z |
Z |
structs.MissileSetupСвойства: |
|
AlwaysShowSprite | When there's a special way to display the object, still show the sprite as well |
HideSpecialDisplay | Don't display the object in a special way |
AutoCollision | When the object hits anything, show an explosion, play explosion sound of the spell and call MonsterAttacked or PlayerAttacked appropriately |
structs.ModelFacetСвойства: |
|
Normal[] | normal fixed pt (0..0x10000) |
NormalX | normal X fixed pt (0..0x10000) |
NormalY | normal Y fixed pt (0..0x10000) |
NormalZ | normal Z fixed pt (0..0x10000) |
NormalDistance | normal distance fixed pt (0..0x10000) |
ZCalc1 | = -(NormalX * 2^16) / NormalZ (or 0 if NormalZ is 0) |
ZCalc2 | = -(NormalY * 2^16) / NormalZ (or 0 if NormalZ is 0) |
ZCalc3 | = -(NormalDistance * 2^16) / NormalZ (or 0 if NormalZ is 0) |
IsPortal | |
IsSecret | [MM7+] show in red with Perception |
ScrollDown | [MM7+] moving texture |
AlignTop | [MM7+] align door texture in D3D |
IsWater | |
ScrollUp | [MM7+] moving texture |
ScrollLeft | [MM7+] moving texture |
ProjectToXY | |
ProjectToXZ | |
ProjectToYZ | |
ScrollRight | [MM7+] moving texture |
AlignLeft | [MM7+] align door texture in D3D |
Invisible | |
AnimatedTFT | |
AlignRight | [MM7+] align door texture in D3D |
AlignBottom | [MM7+] align door texture in D3D |
MoveByDoor | |
IsEventJustHint | [MM7+] |
AlternativeSound | |
IsSky | outdoor in software mode: horizontal flow |
FlipU | |
FlipV | |
TriggerByClick | |
TriggerByStep | |
DisableEventByCtrlClick | [MM8] indoor only: click event gets disabled by Ctrl+Click |
EventDisabledByCtrlClick | [MM8] |
TriggerByMonster | [MM6, MM7] happens even if there's no event assigned |
TriggerByObject | [MM6, MM7] happens even if there's no event assigned |
Untouchable | great for vertical facets of stairs. [MM7+] Shouldn't be used for sloped floor, like it's used in MM6. |
IsLava | |
HasData | |
Bits | |
VertexIds[] | |
UList[] | |
VList[] | |
XInterceptDisplacement[] | |
YInterceptDisplacement[] | |
ZInterceptDisplacement[] | |
BitmapId | |
BitmapU | |
BitmapV | |
MinX | Bounding Box Min X |
MaxX | Bounding Box Max X |
MinY | Bounding Box Min Y |
MaxY | Bounding Box Max Y |
MinZ | Bounding Box Min Z |
MaxZ | Bounding Box Max Z |
Id | |
Event | |
GradientVertexes[] | |
VertexesCount | |
PolygonType |
Polygon type: 0 = empty 1 = wall 2 = unused 3 = horizontal floor 4 = irregular floor (non-horizontal) 5 = horizontal ceiling 6 = irregular ceiling (non-horizontal) |
structs.ModelVertexСвойства: |
|
1 | same as X |
X | |
2 | same as Y |
Y | |
3 | same as Z |
Z |
structs.MonsterAttackInfoСвойства: |
|
Type | |
DamageDiceCount | |
DamageDiceSides | |
DamageAdd | |
Missile |
structs.MonsterKind[MM7+]Свойства: |
|
Undead | |
Demon | [MM7] |
Dragon | |
Elf | [MM7] |
Swimmer | |
Immobile | |
Peasant | [MM8] |
Titan | [MM7] |
NoArena | |
Ogre | [MM8] |
Elemental | [MM8] |
structs.MonsterScheduleСвойства: |
|
Pos[] | |
X | |
Y | |
Z | |
Bits | (1 – on) |
Action | |
Hour | |
Day | |
Month |
structs.MonstersTxtItemСвойства: |
|
Name | |
Picture | |
Id | Changing may cause random crashes after loading the game! Be careful. |
Level | |
TreasureItemPercent | |
TreasureDiceCount | |
TreasureDiceSides | |
TreasureItemLevel | |
TreasureItemType | |
Fly | |
MoveType | |
AIType | |
HostileType | |
Prefers.Necro | [MM8] |
Prefers.Knight | |
Prefers.Paladin | [MM6, MM7] |
Prefers.Archer | [MM6, MM7] |
Prefers.Druid | [MM6, MM7] |
Prefers.Cleric | |
Prefers.Troll | [MM8] |
Prefers.Minotaur | [MM8] |
Prefers.DarkElf | [MM8] |
Prefers.Vampire | [MM8] |
Prefers.Dragon | [MM8] |
Prefers.Sorcerer | [MM6, MM7] |
Prefers.Ranger | [MM7] |
Prefers.Thief | [MM7] |
Prefers.Monk | [MM7] |
Prefers.Male | in monsters.txt it's "M" in MM6 and "X" in MM7 and MM8 |
Prefers.Female | |
Prefers.Human | [MM7] |
Prefers.Elf | [MM7] |
Prefers.Dwarf | [MM7] |
Prefers.Goblin | [MM7] |
PrefClass | Preferred target |
Bonus | (steal, curse, ...) |
BonusMul | Disease1x5 etc. The chance that a monster would use the bonus is Level*BonusMul |
Attack1 | |
Attack2Chance | |
Attack2 | |
SpellChance | |
Spell | |
Spell2Chance | [MM7+] |
Spell2 | [MM7+] |
SpellSkill | |
Resistances[kind] | For immunity use const.MonsterImmune |
FireResistance | |
AirResistance | [MM7+] |
WaterResistance | [MM7+] |
EarthResistance | [MM7+] |
MindResistance | [MM7+] |
SpiritResistance | [MM7+] |
BodyResistance | [MM7+] |
LightResistance | [MM7+] |
DarkResistance | [MM7+] |
ElecResistance | [MM6] |
ColdResistance | [MM6] |
PoisonResistance | [MM6] |
PhysResistance | |
Special | [MM7+] 1 = shot, 2 = summon, 3 = explode |
SpecialA |
[MM7+] shot: C = count summon: A = {RandomLevel = 0, fixed = 1} – monster level (0 means A, B or C is chosen randomly, monster index should be that of A variation. Values of 2 and 3 are the same as 1, but in MM7 before GrayFace Patch v2.1 it was causing a bug), B = {ground = 0, air = 1}, C = already summoned count (up to 3), D = monster index explode: AdB + C, D = attack type |
SpecialB | [MM7+] |
SpecialC | [MM7+] |
MagicResistance | [MM6] |
PrefNum | Number of party members to hit using Attack1 & Attack2 |
BloodSplat | [MM7+] |
Spell2Skill | [MM7+] |
SpecialD | [MM7+] (summoned monster or damage type in case of explosive attack) |
QuestItem | [MM6] |
FullHP | |
FullHitPoints | |
ArmorClass | |
Exp | |
Experience | |
MoveSpeed | |
AttackRecovery |
structs.MoveToMapСвойства: |
|
Pos[] | |
X | |
Y | |
Z | |
Direction | 0 – 2047. 0 is East. |
LookAngle | |
SpeedZ | |
Defined | |
Методы: |
|
Set() |
structs.NPCNewsItem[MM6]Свойства: |
|
Topic | |
Text | |
Map |
structs.NPCProfTxtItem[MM6, MM7]Свойства: |
|
Chance | [MM6] |
Cost | |
Personality | [MM6] |
Benefit | |
ActionText | [MM7] |
JoinText | |
DismissText | [MM7] |
ProfNewsTopic[] | [MM6] |
ProfNewsText[] | [MM6] |
structs.OODialogManager[MM8]Свойства: |
|
VMT | |
CurrentDialogPtr | |
DialogPtrs[] | |
Count | |
Disabled | |
Методы: |
|
ShowDialog() | |
CloseCurrent(arg1 = 0, arg2 = true) | |
FindDialog() | |
CloseSpecific() |
structs.ObjectRefСвойства: |
|
ZBuf | |
Value | Raw value. In inventory screen this is item index, in other screens it equals Kind + Index*8. |
Kind | |
Index | |
Методы: |
|
Get() |
structs.OdmHeaderСвойства: |
|
Name | |
FileName | |
VersionStr | |
TilesetsFile | [MM8] 0 = dtile.bin, 1 = dtile2.bin, 2 = dtile3.bin |
Tilesets[] | |
Bits | [MM8] |
structs.OverlayItemСвойства: |
|
Id | |
Type | |
SFTIndex | |
SFTGroup |
structs.PFTItemСвойства: |
|
GroupId | |
FrameIndex | |
Time | time for this frame in 1/32 of a second |
TotalTime | total time for this group |
NotGroupEnd | |
GroupStart | |
Bits |
structs.PlayerСвойства: |
|
Biography | [MM8] |
Sex | [MM6, MM7] |
Cursed | |
Weak | |
Asleep | |
Afraid | |
Drunk | |
Insane | |
Poison1 | |
Disease1 | |
Poison2 | |
Disease2 | |
Poison3 | |
Disease3 | |
Paralyzed | |
Unconscious | |
Dead | |
Stoned | |
Eradicated | |
Zombie | [MM7+] |
Good | |
Conditions[cond] | |
Exp | |
Experience | |
Name | |
Class | |
Face | |
Stats[stat] | |
MightBase | |
MightBonus | |
IntellectBase | |
IntellectBonus | |
PersonalityBase | |
PersonalityBonus | |
EnduranceBase | |
EnduranceBonus | |
SpeedBase | |
SpeedBonus | |
AccuracyBase | |
AccuracyBonus | |
LuckBase | |
LuckBonus | |
ArmorClassBonus | |
LevelBase | |
LevelBonus | |
AgeBonus | |
Skills[skill] | |
Awards[] | |
Spells[spell] | |
UsedBlackPotions[] | |
Items[] | |
Inventory[] | (Items index) for main item cell, -(1 + main Inventory cell index) for other cells |
Resistances[kind] | |
FireResistanceBase | |
AirResistanceBase | [MM7+] |
WaterResistanceBase | [MM7+] |
EarthResistanceBase | [MM7+] |
SpiritResistanceBase | [MM7+] |
MindResistanceBase | [MM7+] |
BodyResistanceBase | [MM7+] |
FireResistanceBonus | |
AirResistanceBonus | [MM7+] |
WaterResistanceBonus | [MM7+] |
EarthResistanceBonus | [MM7+] |
SpiritResistanceBonus | [MM7+] |
MindResistanceBonus | [MM7+] |
BodyResistanceBonus | [MM7+] |
Voice | [MM7+] |
ColdResistanceBase | [MM6] |
ColdResistanceBonus | [MM6] |
ElecResistanceBase | [MM6] |
ElecResistanceBonus | [MM6] |
PoisonResistanceBase | [MM6] |
PoisonResistanceBonus | [MM6] |
MagicResistanceBase | [MM6] |
MagicResistanceBonus | [MM6] |
SpellBuffs[buff] | |
RecoveryDelay | |
SkillPoints | |
HP | |
HitPoints | |
SP | |
SpellPoints | |
BirthYear | |
EquippedItems[slot] | |
ItemExtraHand | |
ItemMainHand | |
ItemBow | |
ItemArmor | |
ItemHelm | |
ItemBelt | |
ItemCloak | |
ItemGauntlets | Was called ItemGountlets before MMExtension v2.3, old name is supported for backward compatibility |
ItemBoots | |
ItemAmulet | |
ItemRing1 | |
ItemRing2 | |
ItemRing3 | |
ItemRing4 | |
ItemRing5 | |
ItemRing6 | |
SpellBookPage | |
QuickSpell | |
AttackSpell | Added in version 2.5 of my patches |
PlayerBits[] | |
RosterBitIndex | [MM8] |
MeleeAttackBonus | [MM6, MM7] |
MeleeDamageBonus | [MM6, MM7] |
RangedAttackBonus | [MM6, MM7] |
RangedDamageBonus | [MM6, MM7] |
FullHPBonus | [MM6, MM7] |
FullHitPointsBonus | [MM6, MM7] |
FullSPBonus | [MM6, MM7] |
FullSpellPointsBonus | [MM6, MM7] |
Expression | |
ExpressionTimePassed | |
ExpressionLength | |
Beacons[] | |
DevineInterventionCasts | |
ArmageddonCasts | |
FaceBeforeZombie | [MM7] |
OriginalFace | [MM7] |
VoiceBeforeZombie | [MM7] |
OriginalVoice | [MM7] |
Методы: |
|
GetSex(BasedOnVoice[MM8] = false) | [MM7+] Determines sex based on Face or Voice |
GetBaseMight() | |
GetBaseIntellect() | |
GetBasePersonality() | |
GetBaseEndurance() | |
GetBaseAccuracy() | |
GetBaseSpeed() | |
GetBaseLuck() | |
GetBaseLevel() | |
GetLevel() | |
GetMight() | |
GetIntellect() | |
GetPersonality() | |
GetEndurance() | |
GetAccuracy() | |
GetSpeed() | |
GetLuck() | |
GetMeleeAttack(IgnoreExtraHand [MM7+] = false) | |
CalcMeleeDamage(JustWeaponDamage = false, IgnoreExtraHand = false, MonsterId = -1) | |
GetRangedAttack() | |
CalcRangedDamage(MonsterId = -1) | |
CalcHitOrMiss(Monster, Range = 0, Bonus = 0) | AttackType: 0 – melee, 1 – less than 1024, 2 – less then 2560, 3 – 2560 or more. See the Mechanics page on my site for more info on the formula. |
GetMeleeDamageRangeText() | |
GetRangedDamageRangeText() | |
CanTrain() | |
AddHP(Amount) | |
DoDamage(Damage, DamageKind = const.Damage.Phys) | |
DoBadThing(Thing, Monster[MM7+]) | Monster must be specified for stealing in MM7+ |
GetAttackDelay(Shoot = false) | |
GetFullHP() | |
GetFullSP() | |
GetMeleeDamageMin() | [MM7+] |
GetMeleeDamageMax() | [MM7+] |
GetRangedDamageMin() | [MM7+] |
GetRangedDamageMax() | [MM7+] |
GetBaseResistance(Res) | [MM7+] |
GetResistance(Res) | [MM7+] |
HasItemBonus(Bonus2) | [MM7+] Checks whether the player is wearing an item with specified Bonus2 See SPCITEMS.TXT for more info about each bonus. |
GetBaseFireResistance() | [MM6] |
GetBaseElectricityResistance() | [MM6] |
GetBaseColdResistance() | [MM6] |
GetBasePoisonResistance() | [MM6] |
GetBaseMagicResistance() | [MM6] |
GetFireResistance() | [MM6] |
GetElectricityResistance() | [MM6] |
GetColdResistance() | [MM6] |
GetPoisonResistance() | [MM6] |
GetMagicResistance() | [MM6] |
WearsItem(ItemNum, Slot = 16) | If Slot isn't specified, searches all slots for the item |
RemoveFromInventory(Slot) | |
GetStartingClass() | [MM8] |
GetRace() | [MM7] |
GetDiplomacyTotalSkill() | [MM6] |
GetBaseArmorClass() | |
GetArmorClass() | |
GetBaseAge() | |
GetAge() | |
Recover(ByAmount) | |
SetRecoveryDelayRaw(Delay) | |
CalcStatBonusByItems(Stat, IgnoreExtraHand [MM7+] = false) | |
CalcStatBonusByMagic(Stat) | |
CalcStatBonusBySkills(Stat) | |
GetMerchantTotalSkill() | |
GetDisarmTrapTotalSkill() | |
ShowFaceExpression(Expression, Time = 0) | |
ShowFaceAnimation(Animation) | |
IsConscious() | |
GetSkill(Skill) | [MM7+] |
GetPerceptionTotalSkill() | [MM7+] |
GetLearningTotalSkill() | [MM7+] |
AddCondition(Condition, CanResist = false) |
[MM7+] Passing const.Condition.Good isn't supported. CanResist only affects application of Protection from Magic spell. If it's true and the spell protects the player, spell strength is decreased instead of condition being applied. |
GetMainCondition() | [MM7+] Returns the condition that affects character stats. Also see GetDisplayedCondition. |
ResetToClass(arg1) | [MM6, MM7] |
GetDisplayedCondition() | Returns the condition displayed on character face and in character properties. Since pacth 2.5 it can differ from GetMainCondition. |
EnumActiveItems(includeBroken) | |
GetActiveItem(slot, includeBroken) | |
CountItems({item1, item2, ...}) | |
SetRecoveryDelay(Delay) | |
GetIndex() | Returns player index in Party.PlayersArray |
GetSlot() | Returns player slot index. Returns nil in MM8 if the player is not in the active party. |
structs.ProgressBarСвойства: |
|
Max | |
Current | |
Kind | |
SeenScreens[] | [MM7+] |
PcxLoading | |
PcxWomover | |
PcxDemover | |
PcxWomover2 | |
PcxDemover2 | |
BmpFireball | |
BmpBardata | |
BmpLoadprog | [MM7+] |
Методы: |
|
Show() | |
Hide() | |
Draw() | |
Increment() | |
SetMax(arg1) |
structs.SFTСвойства: |
|
MatchIndex | used when searching for a group by name |
Frames[] | (Default) |
Groups[][] | sorted by name |
GroupIndex[] | |
Методы: |
|
FindGroup(arg1 = "") | |
LoadGroup(arg1) |
structs.ShopItemKindСвойства: |
|
Level | |
Types[1..4] | (Default) |
structs.SpawnPointСвойства: |
|
Pos[] | |
X | |
Y | |
Z | |
Radius | |
Kind | |
Index | Index: monster (1-3: M1-M3, 4-6: M1a-M3a, 7-9: M1b-M3b, 10-12: M1c-M3c) or item (1-6 for regular items, 7 for artifact) |
OnAlertMap | |
Bits | |
Group | [MM7+] |
structs.SpcItemsTxtItemСвойства: |
|
NameAdd | |
BonusStat | |
ChanceForSlot[] | |
W1 | |
W2 | |
Miss | |
Arm | |
Shld | |
Helm | |
Belt | |
Cape | |
Gaunt | |
Boot | |
Ring | |
Amul | |
Value | |
Lvl |
structs.SpellBuffСвойства: |
|
ExpireTime | |
Power | |
Skill | |
OverlayId | |
Caster | |
Bits | |
Методы: |
|
Set(ExpireTime, Skill, Power, OverlayId, Caster) |
structs.SpellEffect[MM7+]Свойства: |
structs.SpritesLodСвойства: |
|
File | |
FileName | |
Loaded | |
IOBuffer | |
IOBufferSize | |
LodHeaderSignature | |
Description | |
ArchivesCount | |
ArchivesCArray | |
Type | |
ChapterHandle | |
ChapterSize | |
Files[] | |
FilesOffset | |
SpritesSW[] | |
IsHardware | |
SpritesD3D[] | |
Методы: |
|
HasFile(name) | Does a slow search for a file. For sorted LOD archives FindFile works faster. |
FindFile(name, unsorted = false) |
Finds a file and returns file stream address or 0 if file isn't found. By default performs fast binary search. Pass unsorted = true when searching in Game.GamesLod and Game.SaveGameLod, because these archives aren't sorted lexicographically and thus binary search can't be used for them. Returned file stream can be used in Game.FileRead, Game.FileSeek and Game.FileTell functions. Its position is set to the beginning of specified file. |
LoadSprite() |
structs.StartStat[MM7+]Свойства: |
|
Base | |
Max | |
Spend | how much you spend on it to add a point |
Add | how much is added when you spend a point |
structs.StdItemsTxtItemСвойства: |
|
NameAdd | |
BonusStat | |
ChanceForSlot[] | |
Arm | |
Shld | |
Helm | |
Belt | |
Cape | |
Gaunt | |
Boot | |
Ring | |
Amul |
structs.TFTItemСвойства: |
|
Name | texture name |
Index | index in bitmaps.lod |
Time | time for this frame in 1/32 of a second |
TotalTime | total time for this group |
NotGroupEnd | |
GroupStart | |
Bits |
structs.TileItemСвойства: |
|
Name | |
Id | |
Bitmap | |
TileSet | |
Section | |
Burn | |
Water | |
Block | |
Repulse | |
Flat | |
Wave | |
NoDraw | |
WaterTransition | |
Transition | |
ScrollDown | |
ScrollUp | |
ScrollLeft | |
ScrollRight | |
Bits |
structs.TilesetDefСвойства: |
|
Group | |
Offset |
structs.TownPortalTownInfoСвойства: |
|
Pos[] | |
X | |
Y | |
Z | |
Direction | |
LookAngle | |
MapStatsIndex | |
MapIndex | [MM6] |
Map |
structs.TravelInfoСвойства: |
|
MapIndex | |
DaysAvailable[] | |
Monday | |
Tuesday | |
Wednesday | |
Thursday | |
Friday | |
Saturday | |
Sunday | |
DaysCount | |
Pos[] | |
X | |
Y | |
Z | |
Direction | |
QBit | |
Map |
Constants
const.ActionsЗначения: |
|
Exit = 113 | |
CustomDialogButton = 1000 | |
CustomDialogHint = 1001 | |
CustomDialogMouseUp = 1002 |
const.CharScreensЗначения: |
|
Stats = 100 | |
Skills = 101 | |
Awards = 102 | |
Inventory = 103 |
const.ChestBitsЗначения: |
|
Trapped = 1 | |
ItemsPlaced = 2 | |
Identified = 4 |
const.DlgIDЗначения: |
|
Generic = 1 | a lot of dialogs use this Id |
Menu = 3 | |
Inventory = 4 | character screen, not necessarily Inventory |
Controls = 6 | |
Info = 9 | Quests, Autonotes, Map, Calendar, History, Town Portal, Lloyd Beacon. See const.InfoDialog for values of Param that define the dialog type. |
NPC = 10 | Param is NPC index |
QuickReference = 12 | |
Rest = 16 | |
WalkToMap = 17 | |
SpellBook = 18 | |
SimpleMessage = 19 | |
Chest = 20 | |
SaveGame = 23 | |
LoadGame = 24 | |
House = 25 | Param is the house index |
MapEntrance = 26 | |
SelectTarget = 27 | Heal and other such spells |
Scroll = 30 | When reading a message scroll |
ItemSpell = 31 | |
EscMessage = 70 | |
Query = 80 | |
CheatCreateItem = 89 | |
Button = 90 | shown for 1 frame when clicking most buttons |
ButtonImg2 = 91 | |
ButtonTransparent = 92 | |
ButtonTransparentImg2 = 93 | |
ButtonSaveLoad = 94 | clicking Save/Load button in corresponding dialog |
ButtonEscTransparent = 95 | |
ButtonEsc = 96 | |
ButtonEscImg2 = 97 | |
ButtonRestAndHeal = 98 | |
DrawImage = 99 | used in Info screen to draw the currently selected book |
CheatCreateMonster = 103 | |
ConfigureKeyboard = 105 | |
VideoOptions = 106 | |
CustomDialog = 1000 | used by CustomDialog function |
BlockDialogs = 1001 | in MM8 if custom dialogs exist, these screens are created for each OO dialog in order to prevent processing of said custom dialogs |
BlockDialogsNoDraw = 1002 | used in situation discribed above when it's also important to block drawing the dialogs |
const.HouseScreensЗначения: |
|
Teacher = -1 | |
ChoosePerson = 0 | |
Main = 1 | |
BuyStandard = 2 | |
Sell = 3 | |
Identify = 4 | |
BuySpecial | |
BuySpecialMM6 = 6 | |
BankDeposit = 7 | |
BankWithdraw = 8 | |
Heal = 10 | |
Donate = 11 | |
ProfNews = 12 | NPC command |
JoinMenu = 13 | NPC command |
News = 14 | NPC command |
TavernSleep = 15 | |
TavernFood = 16 | |
Train = 17 | |
BuySpells = 18 | |
A = 19 | NPC command |
B = 20 | NPC command |
C = 21 | NPC command |
D = 22 | [MM7+] NPC command |
E = 23 | [MM7+] NPC command |
F = 24 | [MM7+] NPC command |
Beg = 22 | [MM6] NPC command |
SeerHint = 22 | [MM6] NPC command |
Threat = 23 | [MM6] NPC command |
Bribe = 24 | [MM6] NPC command |
TavernDrink = 25 | |
TavernTip = 26 | |
Staff = 36 | |
Sword = 37 | |
Dagger = 38 | |
Axe = 39 | |
Spear = 40 | |
Bow = 41 | |
Mace = 42 | |
Blaster = 43 | |
Shield = 44 | |
Leather = 45 | |
Chain = 46 | |
Plate = 47 | |
Fire = 48 | |
Air = 49 | |
Water = 50 | |
Earth = 51 | |
Spirit = 52 | |
Mind = 53 | |
Body = 54 | |
Light = 55 | |
Dark = 56 | |
DarkElfAbility = 57 | [MM8] |
VampireAbility = 58 | [MM8] |
DragonAbility = 59 | [MM8] |
IdentifyItem | |
Merchant | |
Repair | |
Bodybuilding | |
Meditation | |
Perception | |
Regeneration = 66 | [MM8] |
Diplomacy = 63 | [MM6, MM7] |
Thievery = 64 | [MM6, MM7] |
DisarmTraps | |
Dodging | [MM7+] |
Unarmed | [MM7+] |
IdentifyMonster | [MM7+] |
Armsmaster | [MM7+] |
Stealing | [MM7+] |
Alchemy | [MM7+] |
Learning | |
Travel1 | |
Travel2 | |
Travel3 | |
HireOrDismiss | NPC command |
MoreInformation | NPC command |
TeachSkill | NPC command |
DoTeachSkill | NPC command |
JoinGuild | NPC command |
DoJoinGuild | NPC command |
BountyHuntNPC | NPC command |
SeerILostIt | NPC command |
ArenaPage | NPC command |
ArenaSquire | NPC command |
ArenaKight | NPC command |
ArenaLord | NPC command |
ArenaMenu | NPC command |
ArenaGoBack | NPC command |
ArenaWin | NPC command |
ArenaAlreadyWon | NPC command |
DisplayInventory = 94 | [MM7+] |
LearnSkills = 96 | [MM7+] |
BountyHunt = 99 | [MM7+] |
PayFine = 100 | [MM7+] |
ArcomageMenu = 101 | [MM7+] |
ArcomageRules = 102 | [MM7+] |
ArcomageConditions = 103 | [MM7+] |
ArcomagePlay = 104 | [MM7+] |
Travel4 = 109 | [MM7+] |
BuySpellsFire = 110 | [MM8] |
BuySpellsAir = 111 | [MM8] |
BuySpellsWater = 112 | [MM8] |
BuySpellsEarth = 113 | [MM8] |
BuySpellsSpirit = 114 | [MM8] |
BuySpellsMind = 115 | [MM8] |
BuySpellsBody = 116 | [MM8] |
BuySpellsLight = 117 | [MM8] |
BuySpellsDark = 118 | [MM8] |
JoinRoster = 119 | [MM8] Yes item in the join menu |
JoinRosterNo = 120 | [MM8] |
SeerPilgrimage = 88 | [MM6] NPC command |
StreetNPC = 200 | Not used by the game, only by MMExt for PopulateNPCDialog event. |
LackFame = 201 | Not used by the game, only by MMExt for PopulateNPCDialog event. |
BegThreatBribe = 202 | Not used by the game, only by MMExt for PopulateNPCDialog event. |
ThreatBribe = 203 | Not used by the game, only by MMExt for PopulateNPCDialog event. |
const.InfoDialogЗначения: |
|
LloydBeacon = 177 | |
TownPortal = 195 | |
Quests = 200 | |
Autonotes = 201 | |
Map = 202 | |
Calendar = 203 | |
History = 224 |
const.MonsterActionЗначения: |
|
Attack1 = 0 | |
Attack2 = 1 | |
Spell1 = 2 | |
Spell2 = 3 | [MM7+] |
const.MonsterKind[MM7+]Значения: |
|
Undead = 1 | |
Demon = 2 | [MM7] |
Dragon | |
Elf = 4 | [MM7] |
Swimmer | |
Immobile | |
Peasant = 5 | [MM8] |
Titan = 7 | [MM7] |
NoArena | |
Ogre = 7 | [MM8] |
Elemental = 8 | [MM8] |
const.ObjectRefKindЗначения: |
|
Nothing = 0 | |
Door = 1 | |
Object = 2 | |
Monster = 3 | |
Party = 4 | Index is player index in Party.PlayersArray |
Sprite = 5 | |
Facet = 6 | Outdoors Index = ModelId*64 + FaceId |
Light = 7 |
const.Race[MM7]Значения: |
|
Human = 0 | |
Elf = 1 | |
Goblin = 2 | |
Dwarf = 3 |
const.ScreensЗначения: |
|
Game = 0 | |
Menu = 1 | |
Controls = 2 | |
Info = 3 | Quests, Autonotes, Map, Calendar, History, Town Portal, Lloyd Beacon |
NPC = 4 | |
Rest = 5 | |
Query = 6 | like with hotkeys in Chinese debug MM6 |
Inventory = 7 | character screen, not necessarily Inventory |
SpellBook = 8 | |
NewGameBriefing = 9 | was called NewGameBreefing before MMExtension v2.3, old name is supported for backward compatibility |
Chest = 10 | |
SaveGame = 11 | |
LoadGame = 12 | |
House = 13 | |
InventoryInShop = 14 | double clicking a character in any Buy dialog in MM6 or in Buy Standard in MM7 |
InventoryInChest = 15 | |
MainManu = 16 | or movie |
WalkToMap = 17 | |
MapEntrance = 18 | or Question screen |
SimpleMessage = 19 | |
SelectTarget = 20 | Heal and other such spells in MM8 |
CreateParty = 21 | |
EscMessage = 22 | |
ItemSpell = 23 | |
KeyConfig = 26 | |
VideoOptions = 28 | |
AdventurersInn = 29 | |
ItemSpellMM6 = 103 | |
QuickReference = 104 |
const.SeasonЗначения: |
|
Automn = 0 | |
Summer = 1 | |
Fall = 2 | |
Winter = 3 |
const.StatsЗначения: |
|
Might = 0 | |
Intellect = 1 | |
Personality = 2 | |
Endurance = 3 | |
Accuracy = 4 | |
Speed = 5 | |
Luck = 6 | |
HP = 7 | |
HitPoints = 7 | |
SP = 8 | |
SpellPoints = 8 | |
ArmorClass = 9 | |
FireResistance = 10 | |
AirResistance = 11 | [MM7+] |
WaterResistance = 12 | [MM7+] |
EarthResistance = 13 | [MM7+] |
MindResistance = 14 | [MM7+] |
BodyResistance = 15 | [MM7+] |
Alchemy = 16 | [MM7+] |
Stealing = 17 | [MM7+] |
DisarmTraps = 18 | [MM7+] |
IdentifyItem = 19 | [MM7+] |
IdentifyMonster = 20 | [MM7+] |
Armsmaster = 21 | [MM7+] |
Dodging = 22 | [MM7+] |
Unarmed = 23 | [MM7+] |
ElecResistance = 11 | [MM6] |
ColdResistance = 12 | [MM6] |
PoisonResistance = 13 | [MM6] |
Level | |
MeleeAttack | |
MeleeDamageBase | |
MeleeDamageMin | For Stats screen. Only used in CalcStatBonusByItems, other events use MeleeDamageBase |
MeleeDamageMax | For Stats screen. Only used in CalcStatBonusByItems, other events use MeleeDamageBase |
RangedAttack | |
RangedDamageBase | |
RangedDamageMin | For Stats screen. Only used in CalcStatBonusByItems, other events use RangedDamageBase |
RangedDamageMax | For Stats screen. Only used in CalcStatBonusByItems, other events use RangedDamageBase |
SpiritResistance = 33 | [MM7+] |
FireMagic = 34 | [MM7+] |
AirMagic = 35 | [MM7+] |
WaterMagic = 36 | [MM7+] |
EarthMagic = 37 | [MM7+] |
SpiritMagic = 38 | [MM7+] |
MindMagic = 39 | [MM7+] |
BodyMagic = 40 | [MM7+] |
LightMagic = 41 | [MM7+] |
DarkMagic = 42 | [MM7+] |
Meditation = 43 | [MM7+] |
Bow = 44 | [MM7+] |
Shield = 45 | [MM7+] |
Learning = 46 | [MM7+] |
DarkElf = 47 | [MM8] |
Vampire = 48 | [MM8] |
Dragon = 49 | [MM8] |
MagicResistance = 23 | [MM6] |
evt.PlayersЗначения: |
|
0 = 0 | |
1 = 1 | |
2 = 2 | |
3 = 3 | |
4 = 4 | [MM8] |
Current | |
current | |
All = 5 | |
all = 5 | |
Random = 6 | |
random = 6 |
evt.VarNumЗначения: |
|
SexIs = 1 | |
ClassIs = 2 | |
HP = 3 | |
HasFullHP = 4 | |
SP = 5 | |
HasFullSP = 6 | |
AC = 7 | |
ArmorClass = 7 | |
ACBonus = 8 | |
ArmorClassBonus = 8 | |
BaseLevel = 9 | |
LevelBonus = 10 | |
AgeBonus = 11 | |
Awards = 12 | |
Exp = 13 | |
Experience = 13 | |
QBits = 16 | |
Inventory = 17 | |
Items = 17 | |
HourIs = 18 | |
DayOfYearIs = 19 | |
DayOfWeekIs = 20 | |
Gold = 21 | |
GoldAddRandom = 22 | |
Food = 23 | |
FoodAddRandom = 24 | |
MightBonus = 25 | |
IntellectBonus = 26 | |
PersonalityBonus = 27 | |
EnduranceBonus = 28 | |
SpeedBonus = 29 | |
AccuracyBonus = 30 | |
LuckBonus = 31 | |
BaseMight = 32 | |
BaseIntellect = 33 | |
BasePersonality = 34 | |
BaseEndurance = 35 | |
BaseSpeed = 36 | |
BaseAccuracy = 37 | |
BaseLuck = 38 | |
CurrentMight = 39 | |
CurrentIntellect = 40 | |
CurrentPersonality = 41 | |
CurrentEndurance = 42 | |
CurrentSpeed = 43 | |
CurrentAccuracy = 44 | |
CurrentLuck = 45 | |
FireResistance = 46 | |
AirResistance = 47 | [MM7+] |
WaterResistance = 48 | [MM7+] |
EarthResistance = 49 | [MM7+] |
SpiritResistance = 50 | [MM7+] |
MindResistance = 51 | [MM7+] |
BodyResistance = 52 | [MM7+] |
LightResistance = 53 | [MM7+] unused resistance |
DarkResistance = 54 | [MM7+] unused resistance |
ElecResistance = 47 | [MM6] |
ColdResistance = 48 | [MM6] |
PoisonResistance = 49 | [MM6] |
MagicResistance | unused resistance |
FireResBonus | |
AirResBonus = 58 | [MM7+] |
WaterResBonus = 59 | [MM7+] |
EarthResBonus = 60 | [MM7+] |
SpiritResBonus = 61 | [MM7+] |
MindResBonus = 62 | [MM7+] |
BodyResBonus = 63 | [MM7+] |
LightResBonus = 64 | [MM7+] unused resistance |
DarkResBonus = 65 | [MM7+] unused resistance |
ElecResBonus = 52 | [MM6] |
ColdResBonus = 53 | [MM6] |
PoisonResBonus = 54 | [MM6] |
MagicResBonus | unused resistance |
StaffSkill | |
SwordSkill | |
DaggerSkill | |
AxeSkill | |
SpearSkill | |
BowSkill | |
MaceSkill | |
BlasterSkill | |
ShieldSkill | |
LeatherSkill | |
ChainSkill | |
PlateSkill | |
FireSkill | |
AirSkill | |
WaterSkill | |
EarthSkill | |
SpiritSkill | |
MindSkill | |
BodySkill | |
LightSkill | |
DarkSkill | |
DarkElfAbilitySkill = 89 | [MM8] |
VampireAbilitySkill = 90 | [MM8] |
DragonAbilitySkill = 91 | [MM8] |
IdentifyItemSkill | |
MerchantSkill | |
RepairItemSkill | |
RepairSkill | |
BodybuildingSkill | |
MeditationSkill | |
PerceptionSkill | |
RegenerationSkill = 98 | [MM8] |
DiplomacySkill | [MM6, MM7] |
ThieverySkill | [MM6, MM7] |
DisarmTrapSkill | |
DisarmTrapsSkill | |
DodgingSkill | [MM7+] |
UnarmedSkill | [MM7+] |
IdentifyMonsterSkill | [MM7+] |
ArmsmasterSkill | [MM7+] |
StealingSkill | [MM7+] |
AlchemySkill | [MM7+] |
LearningSkill | |
Cursed | |
Weak | |
Asleep | |
Afraid | |
Drunk | |
Insane | |
Poison1 | |
PoisonedGreen | |
Disease1 | |
DiseasedGreen | |
Poison2 | |
PoisonedYellow | |
Disease2 | |
DiseasedYellow | |
Poison3 | |
PoisonedRed | |
Disease3 | |
DiseasedRed | |
Paralysed | |
Paralyzed | |
Unconscious | |
Dead | |
Stoned | |
Eradicated | |
MainCondition | |
MapVar0 | |
MapVar1 | |
MapVar2 | |
MapVar3 | |
MapVar4 | |
MapVar5 | |
MapVar6 | |
MapVar7 | |
MapVar8 | |
MapVar9 | |
MapVar10 | |
MapVar11 | |
MapVar12 | |
MapVar13 | |
MapVar14 | |
MapVar15 | |
MapVar16 | |
MapVar17 | |
MapVar18 | |
MapVar19 | |
MapVar20 | |
MapVar21 | |
MapVar22 | |
MapVar23 | |
MapVar24 | |
MapVar25 | |
MapVar26 | |
MapVar27 | |
MapVar28 | |
MapVar29 | |
MapVar30 | |
MapVar31 | |
MapVar32 | |
MapVar33 | |
MapVar34 | |
MapVar35 | |
MapVar36 | |
MapVar37 | |
MapVar38 | |
MapVar39 | |
MapVar40 | |
MapVar41 | |
MapVar42 | |
MapVar43 | |
MapVar44 | |
MapVar45 | |
MapVar46 | |
MapVar47 | |
MapVar48 | |
MapVar49 | |
MapVar50 | |
MapVar51 | |
MapVar52 | |
MapVar53 | |
MapVar54 | |
MapVar55 | |
MapVar56 | |
MapVar57 | |
MapVar58 | |
MapVar59 | |
MapVar60 | |
MapVar61 | |
MapVar62 | |
MapVar63 | |
MapVar64 | |
MapVar65 | |
MapVar66 | |
MapVar67 | |
MapVar68 | |
MapVar69 | |
MapVar70 | |
MapVar71 | |
MapVar72 | |
MapVar73 | |
MapVar74 | |
MapVar75 | |
MapVar76 | |
MapVar77 | |
MapVar78 | |
MapVar79 | |
MapVar80 | |
MapVar81 | |
MapVar82 | |
MapVar83 | |
MapVar84 | |
MapVar85 | |
MapVar86 | |
MapVar87 | |
MapVar88 | |
MapVar89 | |
MapVar90 | |
MapVar91 | |
MapVar92 | |
MapVar93 | |
MapVar94 | |
MapVar95 | |
MapVar96 | |
MapVar97 | |
MapVar98 | |
MapVar99 | |
AutonotesBits | |
IsMightMoreThanBase | |
IsIntellectMoreThanBase | |
IsPersonalityMoreThanBase | |
IsEnduranceMoreThanBase | |
IsSpeedMoreThanBase | |
IsAccuracyMoreThanBase | |
IsLuckMoreThanBase | |
PlayerBits | |
NPCs | [MM6, MM7] |
ReputationIs | |
DaysCounter1 | evt.Set starts the count, evt.Cmp compares the difference of dates |
DaysCounter2 | evt.Set starts the count, evt.Cmp compares the difference of dates |
DaysCounter3 | evt.Set starts the count, evt.Cmp compares the difference of dates |
DaysCounter4 | evt.Set starts the count, evt.Cmp compares the difference of dates |
DaysCounter5 | evt.Set starts the count, evt.Cmp compares the difference of dates |
DaysCounter6 | evt.Set starts the count, evt.Cmp compares the difference of dates |
Flying | |
HasNPCProfession | |
TotalCircusPrize | |
SkillPoints | |
MonthIs | |
Counter1 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
Counter2 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
Counter3 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
Counter4 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
Counter5 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
Counter6 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
Counter7 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
Counter8 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
Counter9 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
Counter10 | [MM7+] evt.Set starts the count, evt.Cmp compares the exact time spent in hours |
SpecialDate1 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %51 |
SpecialDate2 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %52 |
SpecialDate3 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %53 |
SpecialDate4 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %54 |
SpecialDate5 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %55 |
SpecialDate6 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %56 |
SpecialDate7 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %57 |
SpecialDate8 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %58 |
SpecialDate9 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %59 |
SpecialDate10 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %60 |
SpecialDate11 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %61 |
SpecialDate12 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %62 |
SpecialDate13 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %63 |
SpecialDate14 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %64 |
SpecialDate15 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %65 |
SpecialDate16 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %66 |
SpecialDate17 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %67 |
SpecialDate18 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %68 |
SpecialDate19 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %69 |
SpecialDate20 | [MM7+] evt.Set remembers current time and plays sound. The date can be used in messages as %70 |
Reputation | [MM7+] |
History1 | [MM7+] |
History2 | [MM7+] |
History3 | [MM7+] |
History4 | [MM7+] |
History5 | [MM7+] |
History6 | [MM7+] |
History7 | [MM7+] |
History8 | [MM7+] |
History9 | [MM7+] |
History10 | [MM7+] |
History11 | [MM7+] |
History12 | [MM7+] |
History13 | [MM7+] |
History14 | [MM7+] |
History15 | [MM7+] |
History16 | [MM7+] |
History17 | [MM7+] |
History18 | [MM7+] |
History19 | [MM7+] |
History20 | [MM7+] |
History21 | [MM7+] |
History22 | [MM7+] |
History23 | [MM7+] |
History24 | [MM7+] |
History25 | [MM7+] |
History26 | [MM7+] |
History27 | [MM7+] |
History28 | [MM7+] |
History29 | [MM7+] |
MapAlert | [MM7+] |
BankGold | [MM7+] |
Deaths | [MM7+] |
MontersHunted | [MM7+] |
PrisonTerms | [MM7+] |
ArenaWinsPage | [MM7+] |
ArenaWinsSquire | [MM7+] |
ArenaWinsKnight | [MM7+] |
ArenaWinsLord | [MM7+] |
Invisible | [MM7+] |
IsWearingItem | [MM7+] |
Players = 318 | [MM8] |
BaseStats[] | |
Conditions[] | |
Counters[] | [MM7+] |
CurrentStats[] | |
DaysCounters[] | |
History[] | [MM7+] |
MapVars[] | |
ResBonus[] | |
Resistance[] | |
Skills[] | |
SpecialDates[] | [MM7+] |