Usage
This page covers how to add dota-lua-types and dota-panorama-types to your project and use them effectively.
Requirements
- JDK 17 or later
- Gradle 8.x (Kotlin DSL recommended)
Adding the Dependencies
Maven Central
Both packages are published to Maven Central. Add them to your build.gradle.kts:
repositories {
mavenCentral()
}
dependencies {
// Dota 2 VScript (server-side Lua) types
implementation("io.github.isycat:dota-lua-types:<version>")
// Dota 2 Panorama UI types (add only if you need Panorama)
implementation("io.github.isycat:dota-panorama-types:<version>")
}
Check the GitHub releases for the latest version.
Project Structure
When using ktox-dota for Dota 2 development, your project typically uses a multi-module structure to separate server-side (Lua) and client-side (Panorama) code:
my-dota-project/
├── build.gradle.kts # Root build script
├── settings.gradle.kts # Project and module definitions
├── lua/ # Server-side module (VScripts)
│ ├── build.gradle.kts
│ └── src/main/kotlin/ # Your Kotlin VScript sources
└── panorama/ # Client-side module (UI)
├── build.gradle.kts
├── content/ # Assets like images, sounds, etc.
├── src/main/kotlin/ # Your Kotlin UI sources
├── src/main/layout/ # XML and .dota.xml.kts layouts
└── src/main/styles/ # CSS, SASS, and SCSS styles
- Root Project: Contains shared build logic and orchestrates the subprojects.
:luamodule: Specifically for server-side code. This is where you usedota-lua-types. It is compiled to Lua files that go into your game'svscriptsfolder.:panoramamodule: Specifically for client-side UI. This is where you usedota-panorama-typesanddota-panorama-layout-dsl. It is compiled to Javascript and XML files for your game'spanoramafolder. The Panorama module is split into:content/: Static assets.src/main/kotlin/: Kotlin UI logic.src/main/layout/: UI layout files (.xmland.dota.xml.kts).src/main/styles/: Stylesheets (.css,.sass,.scss).
This structure allows you to share common data models or utility classes between both modules if they are placed in a shared module.
dota-lua-types
Package structure
| Kotlin package | Contents |
|---|---|
com.isycat.dota.lua |
Interfaces for all VScript game entities (CBaseEntity, BaseNPC, BaseNPCHero, …) |
com.isycat.dota.lua |
Enums for all Dota 2 flags and constants |
com.isycat.dota.lua |
Strongly-typed game events (EventKey<T> + data classes) |
com.isycat.dota.lua |
Value classes for opaque IDs (EntityIndex, PlayerID, …) |
Accessing global singletons
Common singletons are exposed as top-level val properties:
import com.isycat.dota.lua.*
// Game rules access
val gameMode = GameRules.getGameMode()
// Particle manager
val particle = ParticleManager.createParticle("particles/units/heroes/hero_axe/axe_culling_blade_hit.vpcf", ParticleAttachment.ABSORIGIN_FOLLOW, null)
// Custom events
CustomGameEventManager.registerListener("my_event") { _, eventData ->
// handle event
}
Listening to game events
import com.isycat.dota.lua.*
onGameEvent(DOTA_GAME_STATE_CHANGE) { event ->
if (event.newState == DOTA_GameState.GAME_STATE_GAME_IN_PROGRESS) {
// game started
}
}
Working with entities
import com.isycat.dota.lua.*
val hero: BaseNPCHero = /* obtained from game */
val health = hero.health // val Int — native: GetHealth
hero.health = 500 // var — native: SetHealth
val isAlive = hero.isAlive // val Boolean — native: IsAlive
Enums
All Dota 2 flag and constant enums are available as Kotlin enum class with integer values and @NativeName annotations:
import com.isycat.dota.lua.*
val damage = DamageTypes.MAGICAL // native: DAMAGE_TYPE_MAGICAL
val unitState = UnitState.STUNNED // native: UNIT_STATE_STUNNED
dota-panorama-types
Package structure
| Kotlin package | Contents |
|---|---|
com.isycat.dota.panorama |
Panorama panel interfaces (Panel, Button, Label, …) |
com.isycat.dota.panorama |
Panorama API interfaces (GameEvents, Players, …) |
com.isycat.dota.panorama |
Panorama enums |
com.isycat.dota.panorama |
Panorama events and engine events |
com.isycat.dota.panorama |
CSS property constants (CssProperties) |
Working with panels
import com.isycat.dota.panorama.*
fun setupPanel(panel: Panel) {
panel.setPanelEvent("onactivate") {
// handle click
}
panel.addClass("highlighted")
panel.visible = true
}
CSS properties
Use CssProperties constants to avoid typos in CSS property names:
import com.isycat.dota.panorama.*
panel.style.setProperty(CssProperties.BACKGROUND_COLOR, "#FF000080")
panel.style.setProperty(CssProperties.OPACITY, "0.5")
Listening to Panorama events
import com.isycat.dota.panorama.*
GameEvents.subscribe("DOTAHeroPickCompleted") { event ->
// handle hero pick completed
}
NativeName annotations
Every property and function carries a @NativeName annotation that maps the idiomatic Kotlin name back to the native Dota 2 engine name. This is used by the runtime (e.g. a Kotlin-to-Lua transpiler) to call the correct engine function.
When you access entity.health the transpiler calls entity:GetHealth() / entity:SetHealth(value) in Lua.
Annotations module
Both packages depend on dota-annotations which provides the @NativeName annotation. It is transitively included, so you do not need to add it explicitly.
If you need to reference the annotation type directly: